1. Frameworks/av/media/mediaserver/main_mediaserver.cpp
1.1 main
int main(int argc, char** argv)
{
signal(SIGPIPE, SIG_IGN);
char value[PROPERTY_VALUE_MAX];
bool doLog =(property_get("ro.test_harness", value, "0") > 0)&& (atoi(value) == 1);
pid_t childPid;
// FIXME The advantage of making theprocess containing media.log service the parent process of
// the process that contains all the otherreal services, is that it allows us to collect more
// detailed information such as signalnumbers, stop and continue, resource usage, etc.
// But it is also more complex. Consider replacing this by independentprocesses, and using
// binder on death notification instead.
if (doLog && (childPid = fork()) !=0) {
// media.log service
//prctl(PR_SET_NAME, (unsigned long)"media.log", 0, 0, 0);
// unfortunately ps ignores PR_SET_NAMEfor the main thread, so use this ugly hack
strcpy(argv[0], "media.log");
sp<ProcessState>proc(ProcessState::self());
MediaLogService::instantiate();
ProcessState::self()->startThreadPool();
for (;;) {
siginfo_t info;
int ret = waitid(P_PID, childPid,&info, WEXITED | WSTOPPED | WCONTINUED);
if (ret == EINTR) {
continue;
}
if (ret < 0) {
break;
}
char buffer[32];
const char *code;
switch (info.si_code) {
case CLD_EXITED:
code = "CLD_EXITED";
break;
case CLD_KILLED:
code = "CLD_KILLED";
break;
case CLD_DUMPED:
code = "CLD_DUMPED";
break;
case CLD_STOPPED:
code = "CLD_STOPPED";
break;
case CLD_TRAPPED:
code = "CLD_TRAPPED";
break;
case CLD_CONTINUED:
code ="CLD_CONTINUED";
break;
default:
snprintf(buffer, sizeof(buffer),"unknown (%d)", info.si_code);
code = buffer;
break;
}
struct rusage usage;
getrusage(RUSAGE_CHILDREN,&usage);
ALOG(LOG_ERROR,"media.log", "pid %d status %d code %s user %ld.%03lds sys%ld.%03lds",
info.si_pid,info.si_status, code,
usage.ru_utime.tv_sec,usage.ru_utime.tv_usec / 1000,
usage.ru_stime.tv_sec,usage.ru_stime.tv_usec / 1000);
sp<IServiceManager> sm =defaultServiceManager();
sp<IBinder> binder =sm->getService(String16("media.log"));
if (binder != 0) {
Vector<String16> args;
binder->dump(-1, args);
}
switch (info.si_code) {
case CLD_EXITED:
case CLD_KILLED:
case CLD_DUMPED: {
ALOG(LOG_INFO,"media.log", "exiting");
_exit(0);
// not reached
}
default:
break;
}
}
} else {
// all other services
if (doLog) {
prctl(PR_SET_PDEATHSIG,SIGKILL); // if parent media.log dies before me, kill mealso
setpgid(0, 0); // but if I die first,don't kill my parent
}
// 创建一个ProcessState对象实例
sp<ProcessState> proc(ProcessState::self());
// MediaServer对于 ServiceManager来说,是个客户端,它需要向
// ServiceManager注册。调用 defaultServiceManager得到一个IServiceManager.
sp<IServiceManager> sm =defaultServiceManager();
ALOGI("ServiceManager: %p",sm.get());
// 初始化音频系统的AudioFlinger服务
AudioFlinger::instantiate();
// MediaPlayer服务
MediaPlayerService::instantiate();
// Camera服务
CameraService::instantiate();
// AudioPolicy服务
AudioPolicyService::instantiate();
// This anull function
registerExtensions();
// Createa thread and join this thread into ThreadPool
ProcessState::self()->startThreadPool();
// Joinself inot thread pool
IPCThreadState::self()->joinThreadPool();
}
}
2. frameworks/native/libs/binder/ProcessState.cpp
2.1 ProcessState::self()
sp<ProcessState>ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = newProcessState;
return gProcess;
}
2.2 ProcessState::self()
ProcessState::ProcessState()
:mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
,mBinderContextCheckFunc(NULL)
,mBinderContextUserData(NULL)
,mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// XXX Ideally, thereshould be a specific define for whether we
// have mmap (orwhether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
// mmap the binder,providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0,BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart ==MAP_FAILED) {
// *sigh*
ALOGE("Using/dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not beopened. Terminating.");
}
2.3 open_driver()
static int open_driver()
{
int fd =open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD,FD_CLOEXEC);
int vers;
status_t result =ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binderioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 ||vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binderdriver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
size_t maxThreads =15;
result = ioctl(fd,BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binderioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening'/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
3. frameworks/native/libs/binder/IServiceManager.cpp
3.1 defaultServiceManager ()
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager!= NULL) return gDefaultServiceManager;
{
AutoMutex_l(gDefaultServiceManagerLock);
if(gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
returngDefaultServiceManager;
}
4. frameworks/native/libs/binder/ProcessState.cpp
4.1 defaultServiceManager ()
sp<IBinder> ProcessState::getContextObject(constsp<IBinder>& caller)
{
returngetStrongProxyForHandle(0);
}
4.2 ProcessState::getStrongProxyForHandle
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_thandle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create anew BpBinder if there isn't currently one, OR we
// are unable toacquire a weak reference on this current one.
// See comment
// ingetWeakProxyForHandle() for more info about this.
IBinder* b =e->binder;
if (b == NULL ||!e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs= b->getWeakRefs();
result = b;
} else {
// This little bitof nastyness is to allow us to add a primary
// reference tothe remote proxy when this team doesn't have one
// but anotherteam is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
4.3 BpBinder and BBinder
BpBinder and BBinder all inherit from IBinder, BpBinder is clientend, BBinder is service end in light of binder communication. BpBinder isone-one correspondent with BBinder, BpBinder identify BBinder by handle.
Frameworks/native/libs/binder/BpBinder.cpp
BpBinder::BpBinder(int32_t handle)
: mHandle(handle) // handle is 0
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGV("CreatingBpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
4.4 BpServiceManager and BnServiceManager(IServiceManager)
In
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
ProcessState::self()->getContextObject(NULL)返回一个BpBinder对象,然后interface_cast用BpBinder对象生成了一个BpServiceManager对象。 Interface_cast定义与实现在frameworks/native/include/binder/IInterface.h
从图中可以看出, BnServiceManager直接继承于BBinder 。而BpServiceManager不是如此。BpServiceManager是利用一个BpBinder的成员变量指针mRemote而与Binder通讯的。
Frameworks/native/libs/binder/IServiceManager.cpp
BpServiceManager(constsp<IBinder>& impl)
:BpInterface<IServiceManager>(impl)
{
}
Frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(constsp<IBinder>& remote)
: BpRefBase(remote)
{
}
Frameworks/native/libs/binder/Binder.cpp
BpRefBase::BpRefBase(const sp<IBinder>& o)
:mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs =mRemote->createWeak(this); // Heldfor our entire lifetime.
}
}
从上面的可以看到ProcessState::self()->getContextObject(NULL)返回一个BpBinder对象,再经过interface_cast生成BpServiceManager,并把BpBinder赋给BpServiceManager的成员变量mRemote.
从defaultServiceManager,我们得到了两个对象,一个BpBinder,其handle为0,一个BpServiceManager对象,其mRemote指向BpBinder对象。
5. frameworks/native/include/binder/BindServer.h
5.1 AudioFlinger::instantiate()
AudioFlinger inherit from BinderService, and no rewritinginstantiate of BinderService.
Therefore call BinderService::instantiate()
namespaceandroid {
template<typenameSERVICE>
classBinderService
{
public:
static status_tpublish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
returnsm->addService(
String16(SERVICE::getServiceName()),
newSERVICE(), allowIsolated);
}
static void publishAndJoinThreadPool(boolallowIsolated = false) {
sp<IServiceManager>sm(defaultServiceManager());
sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
ProcessState::self()->startThreadPool();
ProcessState::self()->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
static voidinstantiate() { publish(); }
static status_t shutdown() {
return NO_ERROR;
}
};
}; // namespace android
6. frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
6.1 MediaPlayerService::instantiate
voidMediaPlayerService::instantiate() {
//注意:defaultServiceManager返回的是一个BpServiceManager对象
defaultServiceManager()->addService(
String16("media.player"),new MediaPlayerService());
}
见8. 详述。
7. frameworks/native/include/binder/BindServer.h
7.1 CameraService::instantiate()
同 5.1 AudioFlinger::instantiate()
7.2 AudioPolicyService::instantiate()
同 5.1 AudioFlinger::instantiate()
8. MediaPlayerService::instantiate()
8.1 MediaPlayerService::instantiate()
// frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
voidMediaPlayerService::instantiate() {
//注意:defaultServiceManager返回的是一个BpServiceManager对象
defaultServiceManager()->addService(
String16("media.player"),new MediaPlayerService());
}
8.2 BpServiceManager:: addService ()
// frameworks/native/libs/binder/IServiceManager.cpp
virtual status_t addService(constString16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err =remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ?reply.readExceptionCode() : err;
}
8.3 BpBinder::transact ()
前面已经提过, BpServiceManager的mRemote成员变量指向一个BpBinder对象,而remote()就是返回mRemote.
frameworks/native/libs/binder/BpBinder.cpp
status_tBpBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will nevercome back to life.
if (mAlive) {
status_t status= IPCThreadState::self()->transact(
mHandle,code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
8.4 IPCThreadState::transact ()
Frameworks/native/libs/binder/IPCThreadState.cpp
status_tIPCThreadState::transact(int32_t handle,
uint32_t code,const Parcel& data,
Parcel*reply, uint32_t flags)
{
status_t err = data.errorCheck();
flags |= TF_ACCEPT_FDS;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_TRANSACTION thr" << (void*)pthread_self() << " / hand "
<< handle << " /code " << TypeCode(code) << ": "
<< indent << data<< dedent << endl;
}
if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND frompid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ?"READ REPLY" : "ONE WAY");
err =writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}
if (err != NO_ERROR) {
if (reply) reply->setError(err);
return (mLastError = err);
}
if ((flags & TF_ONE_WAY) == 0) {
#if 0
if (code == 4) { // relayout
ALOGI(">>>>>> CALLING transaction 4");
} else {
ALOGI(">>>>>> CALLING transaction %d",code);
}
#endif
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err =waitForResponse(&fakeReply);
}
#if 0
if (code == 4) { // relayout
ALOGI("<<<<<< RETURNING transaction 4");
} else {
ALOGI("<<<<<< RETURNING transaction %d",code);
}
#endif
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_REPLY thr" << (void*)pthread_self() << " / hand "
<< handle <<": ";
if (reply) alog << indent<< *reply << dedent << endl;
else alog << "(nonerequested)" << endl;
}
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
8.5 MediaPlayerService::MediaPlayerService ()
Frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerServicecreated");
mNextConnId = 1;
mBatteryAudio.refCount = 0;
for (int i = 0; i < NUM_AUDIO_DEVICES;i++) {
mBatteryAudio.deviceOn[i] = 0;
mBatteryAudio.lastTime[i] = 0;
mBatteryAudio.totalTime[i] = 0;
}
// speaker is on by default
mBatteryAudio.deviceOn[SPEAKER] = 1;
MediaPlayerFactory::registerBuiltinFactories();
}
8.5 MediaPlayerFactory::registerBuiltinFactories()
Frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
voidMediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
sInitComplete = true;
}
status_tMediaPlayerFactory::registerFactory_l(IFactory* factory,
player_type type) {
if (NULL == factory) {
ALOGE("Failed to registerMediaPlayerFactory of type %d, factory is"
" NULL.", type);
return BAD_VALUE;
}
if (sFactoryMap.indexOfKey(type) >= 0) {
ALOGE("Failed to registerMediaPlayerFactory of type %d, type is"
" already registered.",type);
return ALREADY_EXISTS;
}
if (sFactoryMap.add(type, factory) < 0){
ALOGE("Failed to registerMediaPlayerFactory of type %d, failed to add"
" to map.", type);
return UNKNOWN_ERROR;
}
return OK;
}
9. Binder Communication Layer
9.1 BpBinder::transact ()
9.2 IPCThreadState::transact()
9.3 IPCThreadState::writeTransactionData()
status_tIPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, constParcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
tr.target.handle =handle; // handle 标识目的端,其中0标识ServiceManager
tr.code = code;
tr.flags = binderFlags;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size =data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets =data.ipcObjects();
} else if (statusBuffer) {
tr.flags |= TF_STATUS_CODE;
*statusBuffer = err;
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = statusBuffer;
tr.offsets_size = 0;
tr.data.ptr.offsets = NULL;
} else {
return (mLastError = err);
}
// mIn, mOut是连个Parcel对象,发送和接收命令缓冲区。
// 每个IPCThreadState都有一个mIn, mOut;mIn是用来接收从binder设备
//来的数据,而mOut是用来存储发往binder设备的数据。
//写命令到缓冲区
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;
}
9.4 IPCThreadState::waitForResponse
发送请求与接收响应
status_tIPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
int32_t cmd;
int32_t err;
while (1) {
if((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = mIn.readInt32();
IF_LOG_COMMANDS() {
alog << "ProcessingwaitForResponse Command: "
<< getReturnString(cmd)<< endl;
}
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply &&!acquireResult) goto finish;
break;
case BR_DEAD_REPLY:
err = DEAD_OBJECT;
goto finish;
case BR_FAILED_REPLY:
err = FAILED_TRANSACTION;
goto finish;
case BR_ACQUIRE_RESULT:
{
ALOG_ASSERT(acquireResult !=NULL, "Unexpected brACQUIRE_RESULT");
const int32_t result =mIn.readInt32();
if (!acquireResult) continue;
*acquireResult = result ?NO_ERROR : INVALID_OPERATION;
}
goto finish;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr,sizeof(tr));
ALOG_ASSERT(err == NO_ERROR,"Not enough command data for brREPLY");
if (err != NO_ERROR) gotofinish;
if (reply) {
if ((tr.flags &TF_STATUS_CODE) == 0) {
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),
freeBuffer, this);
} else {
err =*static_cast<const status_t*>(tr.data.ptr.buffer);
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
}
} else {
freeBuffer(NULL,
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), this);
continue;
}
}
goto finish;
default:
err =executeCommand(cmd);
if (err != NO_ERROR) goto finish;
break;
}
}
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult =err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
9.5 IPCThreadState:: talkWithDriver
status_tIPCThreadState::talkWithDriver(bool doReceive)
{
if (mProcess->mDriverFD <= 0) {
return -EBADF;
}
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition()>= mIn.dataSize();
// We don't want to write anything if weare still reading
// from data left in the input buffer andthe caller
// has requested to read the next data.
const size_t outAvail = (!doReceive ||needRead) ? mOut.dataSize() : 0;
bwr.write_size = outAvail;
bwr.write_buffer = (long unsignedint)mOut.data();
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsignedint)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
if (outAvail != 0) {
alog << "Sendingcommands to driver: " << indent;
const void* cmds = (constvoid*)bwr.write_buffer;
const void* end = ((constuint8_t*)cmds)+bwr.write_size;
alog << HexDump(cmds,bwr.write_size) << endl;
while (cmds < end) cmds =printCommand(alog, cmds);
alog << dedent;
}
alog << "Size of receivebuffer: " << bwr.read_size
<< ", needRead: "<< needRead << ", doReceive: " << doReceive<< endl;
}
// Return immediately if there is nothingto do.
if ((bwr.write_size == 0) &&(bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
IF_LOG_COMMANDS() {
alog << "About toread/write, write size = " << mOut.dataSize() << endl;
}
#ifdefined(HAVE_ANDROID_OS)
if(ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
alog << "Finishedread/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
IF_LOG_COMMANDS() {
alog << "Our err: "<< (void*)err << ", write consumed: "
<< bwr.write_consumed<< " (of " << mOut.dataSize()
<< "),read consumed: " << bwr.read_consumed << endl;
}
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
if (bwr.write_consumed <(ssize_t)mOut.dataSize())
mOut.remove(0,bwr.write_consumed);
else
mOut.setDataSize(0);
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
}
IF_LOG_COMMANDS() {
TextOutput::Bundle _b(alog);
alog << "Remaining datasize: " << mOut.dataSize() << endl;
alog << "Received commandsfrom driver: " << indent;
const void* cmds = mIn.data();
const void* end = mIn.data() +mIn.dataSize();
alog << HexDump(cmds,mIn.dataSize()) << endl;
while (cmds < end) cmds =printReturnCommand(alog, cmds);
alog << dedent;
}
return NO_ERROR;
}
return err;
}
9.6 IPCThreadState:: executeCommand
现在假设请求后得到回复响应
status_tIPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch (cmd) {
case BR_ERROR:
result = mIn.readInt32();
break;
case BR_OK:
break;
case BR_ACQUIRE:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
ALOG_ASSERT(refs->refBase() == obj,
"BR_ACQUIRE: object %pdoes not match cookie %p (expected %p)",
refs, obj,refs->refBase());
obj->incStrong(mProcess.get());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_ACQUIREfrom driver on %p", obj);
obj->printRefs();
}
mOut.writeInt32(BC_ACQUIRE_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_RELEASE:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
ALOG_ASSERT(refs->refBase() == obj,
"BR_RELEASE: object %pdoes not match cookie %p (expected %p)",
refs, obj,refs->refBase());
IF_LOG_REMOTEREFS() {
LOG_REMOTEREFS("BR_RELEASEfrom driver on %p", obj);
obj->printRefs();
}
mPendingStrongDerefs.push(obj);
break;
case BR_INCREFS:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
refs->incWeak(mProcess.get());
mOut.writeInt32(BC_INCREFS_DONE);
mOut.writeInt32((int32_t)refs);
mOut.writeInt32((int32_t)obj);
break;
case BR_DECREFS:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
// NOTE: This assertion is not valid,because the object may no
// longer exist (thus the(BBinder*)cast above resulting in a different
// memory address).
//ALOG_ASSERT(refs->refBase() ==obj,
// "BR_DECREFS: object %p does notmatch cookie %p (expected %p)",
// refs, obj, refs->refBase());
mPendingWeakDerefs.push(refs);
break;
case BR_ATTEMPT_ACQUIRE:
refs =(RefBase::weakref_type*)mIn.readInt32();
obj = (BBinder*)mIn.readInt32();
{
const bool success =refs->attemptIncStrong(mProcess.get());
ALOG_ASSERT(success &&refs->refBase() == obj,
"BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected%p)",
refs, obj,refs->refBase());
mOut.writeInt32(BC_ACQUIRE_RESULT);
mOut.writeInt32((int32_t)success);
}
break;
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr,sizeof(tr));
ALOG_ASSERT(result == NO_ERROR,
"Not enough command datafor brTRANSACTION");
if (result != NO_ERROR) break;
Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<constuint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<constsize_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t),freeBuffer, this);
const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;
mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;
int curPrio =getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio >ANDROID_PRIORITY_NORMAL) {
// We have inherited areduced priority from the caller, but do not
// want to run in thatstate in this process. The driver setour
// priority already (thoughnot our scheduling class), so bounce
// it back to the defaultbefore invoking the transaction.
setpriority(PRIO_PROCESS,mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >=ANDROID_PRIORITY_BACKGROUND) {
// We want to use theinherited priority from the caller.
// Ensure this thread is inthe background scheduling class,
// since the driver won'tmodify scheduling classes for us.
// The scheduling group isreset to default by the caller
// once this method returns afterthe transaction is complete.
set_sched_policy(mMyThreadId, SP_BACKGROUND);
}
}
//ALOGI(">>>>TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);
Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog <<"BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj" << tr.target.ptr << " / code "
<< TypeCode(tr.code)<< ": " << indent << buffer
<< dedent <<endl
<< "Data addr ="
<<reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<<reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
//here, b can be CameraService object etc.
sp<BBinder> b((BBinder*)tr.cookie);
conststatus_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR)reply.setError(error);
} else {
const status_t error =the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR)reply.setError(error);
}
//ALOGI("<<<<TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);
if ((tr.flags & TF_ONE_WAY) ==0) {
LOG_ONEWAY("Sending replyto %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sendingreply to %d!", mCallingPid);
}
mCallingPid = origPid;
mCallingUid = origUid;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLYthr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr<< ": " << indent << reply << dedent <<endl;
}
}
break;
case BR_DEAD_BINDER:
{
BpBinder *proxy =(BpBinder*)mIn.readInt32();
proxy->sendObituary();
mOut.writeInt32(BC_DEAD_BINDER_DONE);
mOut.writeInt32((int32_t)proxy);
} break;
case BR_CLEAR_DEATH_NOTIFICATION_DONE:
{
BpBinder *proxy =(BpBinder*)mIn.readInt32();
proxy->getWeakRefs()->decWeak(proxy);
} break;
case BR_FINISHED:
result = TIMED_OUT;
break;
case BR_NOOP:
break;
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
break;
default:
printf("*** BAD COMMAND %dreceived from Binder driver\n", cmd);
result = UNKNOWN_ERROR;
break;
}
if (result != NO_ERROR) {
mLastError = result;
}
return result;
}
ServiceManager 分析
1. Main()
Frameworks/native/cmds/servicesmanager/Service_manager.c
static struct {
unsigned uid;
const char *name;
} allowed[] = {
{AID_MEDIA, "media.audio_flinger" },
{AID_MEDIA, "media.log" },
{AID_MEDIA, "media.player" },
{AID_MEDIA, "media.camera" },
{AID_MEDIA, "media.audio_policy" },
{AID_DRM, "drm.drmManager" },
{AID_NFC, "nfc" },
{AID_BLUETOOTH, "bluetooth" },
{AID_RADIO, "radio.phone" },
{AID_RADIO, "radio.sms" },
{AID_RADIO, "radio.phonesubinfo" },
{AID_RADIO, "radio.simphonebook" },
/* TODO: remove after phone services areupdated: */
{AID_RADIO, "phone" },
{AID_RADIO, "sip" },
{AID_RADIO, "isms" },
{AID_RADIO, "iphonesubinfo" },
{AID_RADIO, "simphonebook" },
{AID_MEDIA, "common_time.clock" },
{AID_MEDIA, "common_time.config" },
{AID_KEYSTORE, "android.security.keystore" },
};
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n",strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
2. binder_open ()
frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(unsignedmapsize)
{
struct binder_state *bs;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return 0;
}
bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd,0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
/* TODO: check version */
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
3. binder_become_context_manager ()
frameworks/native/cmds/servicemanager/binder.c
int binder_become_context_manager(structbinder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); // set self handleto 0
}
4. binder_loop ()
frameworks/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs,binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
if (res == 0) {
ALOGE("binder_loop: unexpected reply?!\n");
break;
}
if (res < 0) {
ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
break;
}
}
}
5. binder_parse ()
frameworks/native/cmds/servicemanager/binder.c
int binder_parse(struct binder_state *bs,struct binder_io *bio,
uint32_t *ptr, uint32_t size,binder_handler func)
{
int r = 1;
uint32_t *end = ptr + (size / 4);
while (ptr < end) {
uint32_t cmd = *ptr++;
#if TRACE
fprintf(stderr,"%s:\n", cmd_name(cmd));
#endif
switch(cmd) {
case BR_NOOP:
break;
case BR_TRANSACTION_COMPLETE:
break;
case BR_INCREFS:
case BR_ACQUIRE:
case BR_RELEASE:
case BR_DECREFS:
#if TRACE
fprintf(stderr," %08x%08x\n", ptr[0], ptr[1]);
#endif
ptr += 2;
break;
case BR_TRANSACTION: {
struct binder_txn *txn = (void *) ptr;
if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
ALOGE("parse: txn toosmall!\n");
return -1;
}
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
bio_init(&reply, rdata,sizeof(rdata), 4);
bio_init_from_txn(&msg,txn);
res = func(bs, txn, &msg,&reply);
binder_send_reply(bs,&reply, txn->data, res);
}
ptr += sizeof(*txn) / sizeof(uint32_t);
break;
}
case BR_REPLY: {
struct binder_txn *txn = (void*) ptr;
if ((end - ptr) *sizeof(uint32_t) < sizeof(struct binder_txn)) {
ALOGE("parse: reply toosmall!\n");
return -1;
}
binder_dump_txn(txn);
if (bio) {
bio_init_from_txn(bio, txn);
bio = 0;
} else {
/* todo FREE BUFFER */
}
ptr += (sizeof(*txn) / sizeof(uint32_t));
r = 0;
break;
}
case BR_DEAD_BINDER: {
struct binder_death *death = (void*) *ptr++;
death->func(bs, death->ptr);
break;
}
case BR_FAILED_REPLY:
r = -1;
break;
case BR_DEAD_REPLY:
r = -1;
break;
default:
ALOGE("parse: OOPS %d\n", cmd);
return -1;
}
}
return r;
}
6. svcmgr_handler ()
Frameworks/native/cmds/servicesmanager/Service_manager.c
int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
int allow_isolated;
// ALOGI("target=%p code=%d pid=%d uid=%d\n",
// txn->target, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target != svcmgr_handle)
return -1;
// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
s= bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len, txn->sender_euid);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, ptr,txn->sender_euid, allow_isolated))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
In executeCommand function
sp<BBinder> b((BBinder*)tr.cookie);
conststatus_t error = b->transact(tr.code, buffer, &reply, tr.flags);
here, b can be CameraService / MediaPlayerService etc
MediaPlayerService inherits from BnMediaPlayerService, which fromBnInterface, which from BBinder
BnMediaPlayerService rewrite onTransact ofBBinder, neither rewrite transact
Therefore, here BBinder::transact() called.
1. b->transact()
2. BBinder::transact()
Frameworks/native/libs/binder/Binder.cpp
status_tBBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err =onTransact(code, data, reply, flags);
break;
}
if(reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
3. BnMediaPlayerService::onTransact()
Frameworks/av/media/libmedia/IMediaPlayerService.cpp
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
case DECODE_URL: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const char* url = data.readCString();
uint32_t sampleRate;
int numChannels;
audio_format_t format;
sp<IMemory> player = decode(url, &sampleRate,&numChannels, &format);
reply->writeInt32(sampleRate);
reply->writeInt32(numChannels);
reply->writeInt32((int32_t) format);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
case DECODE_FD: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
int fd = dup(data.readFileDescriptor());
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
uint32_t sampleRate;
int numChannels;
audio_format_t format;
sp<IMemory> player = decode(fd, offset, length, &sampleRate,&numChannels, &format);
reply->writeInt32(sampleRate);
reply->writeInt32(numChannels);
reply->writeInt32((int32_t) format);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaRecorder> recorder = createMediaRecorder();
reply->writeStrongBinder(recorder->asBinder());
return NO_ERROR;
} break;
case CREATE_METADATA_RETRIEVER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaMetadataRetriever>retriever = createMetadataRetriever();
reply->writeStrongBinder(retriever->asBinder());
return NO_ERROR;
} break;
case GET_OMX: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IOMX> omx = getOMX();
reply->writeStrongBinder(omx->asBinder());
return NO_ERROR;
} break;
case MAKE_CRYPTO: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<ICrypto> crypto = makeCrypto();
reply->writeStrongBinder(crypto->asBinder());
return NO_ERROR;
} break;
case MAKE_DRM: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IDrm> drm = makeDrm();
reply->writeStrongBinder(drm->asBinder());
return NO_ERROR;
} break;
case MAKE_HDCP: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
bool createEncryptionModule = data.readInt32();
sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
reply->writeStrongBinder(hdcp->asBinder());
return NO_ERROR;
} break;
case ADD_BATTERY_DATA: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
uint32_t params = data.readInt32();
addBatteryData(params);
return NO_ERROR;
} break;
case PULL_BATTERY_DATA: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pullBatteryData(reply);
return NO_ERROR;
} break;
case LISTEN_FOR_REMOTE_DISPLAY: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IRemoteDisplayClient> client(
interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
String8 iface(data.readString8());
sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));
reply->writeStrongBinder(display->asBinder());
return NO_ERROR;
} break;
case UPDATE_PROXY_CONFIG:
{
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const char *host = NULL;
int32_t port = 0;
const char *exclusionList = NULL;
if (data.readInt32()) {
host = data.readCString();
port = data.readInt32();
exclusionList =data.readCString();
}
reply->writeInt32(updateProxyConfig(host, port, exclusionList));
return OK;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}