六、Android Binder机制浅析之注册MediaPlayerService(2)

来源:互联网 发布:stp文件打开软件 编辑:程序博客网 时间:2024/06/11 17:01

MediaPlayerService的注册

Mediaserver的代码主要在frameworks\av\media\mediaserver\main_mediaserver.cpp中实现:

[cpp] view plain copy
  1. int main(int argc, char** argv)  
  2. {  
  3.     ……  
  4. sp<ProcessState> proc(ProcessState::self());  
  5. // 获得ServiceManager的实例  
  6.     sp<IServiceManager> sm = defaultServiceManager();  
  7.   
  8. // Mediaserver进程承载了好几个服务  
  9. AudioFlinger::instantiate();  
  10.     MediaPlayerService::instantiate();  
  11.     CameraService::instantiate();  
  12.     AudioPolicyService::instantiate();  
  13. registerExtensions();  
  14.   
  15. // 开始循环接收消息  
  16.     ProcessState::self()->startThreadPool();  
  17.     IPCThreadState::self()->joinThreadPool();  
  18. }  

由main函数可知,MediaServer中运行着多个Service,下面我们主要以MediaPlayerService为例讲解其通过Binder机制与ServiceManager进程通信的过程。

 

MediaPlayerService::instantiate();调用的实现如下:

[cpp] view plain copy
  1. void MediaPlayerService::instantiate() {  
  2.     defaultServiceManager()->addService(  
  3.             String16("media.player"), new MediaPlayerService());  
  4. }  

在上一篇文章中我们已经说到defaultServiceManager函数返回的是一个BpServiceManager对象。类BpServiceManager继承自IServiceManager,因此addService如下所示:

[cpp] view plain copy
  1. virtual status_t addService(const String16& name, const sp<IBinder>& service,  
  2.             bool allowIsolated)  
  3. {  
  4.     // Parcel可以把它当成是一个数据包类  
  5.         Parcel data, reply;  
  6.         data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());  
  7.         data.writeString16(name);  
  8.         data.writeStrongBinder(service);  
  9.         data.writeInt32(allowIsolated ? 1 : 0);  
  10.   
  11.         // remote()返回的是mRemote,也就是BpBinder对象  
  12.         status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);  
  13.         return err == NO_ERROR ? reply.readExceptionCode() : err;  
  14. }  

BpBinder的transact实现如下:

[cpp] view plain copy
  1. status_t BpBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     // Once a binder has died, it will never come back to life.  
  5.     if (mAlive) {  
  6.         status_t status = IPCThreadState::self()->transact(  
  7.             mHandle, code, data, reply, flags);  
  8.         if (status == DEAD_OBJECT) mAlive = 0;  
  9.         return status;  
  10.     }  
  11.   
  12.     return DEAD_OBJECT;  
  13. }  

上一篇文章中也说过BpBinder并不参与实际的底层Binder设备通信的工作,这里也看到,在transact函数中,其最后把工作传给了IPCThreadState。

 

接着来看IPCThreadState self函数的实现:

[cpp] view plain copy
  1. IPCThreadState* IPCThreadState::self()  
  2. {  
  3.     // 第一次进来为false  
  4.     if (gHaveTLS) {  
  5. restart:  
  6.         const pthread_key_t k = gTLS;  
  7.         /* 
  8.             TLS是Thread Local Storage即线程本地存储空间的简称。 
  9.             这种空间每个线程都有,且线程之间不共享这些空间。 
  10.             通过pthread_getspecific/ pthread_setspecific函数可以获取/设置这些空间中的 
  11.             内容。 
  12.             显然,这里的TLS中保存了IPCThreadState的对象。 
  13.         */  
  14.         IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);  
  15.         if (st) return st;  
  16.         return new IPCThreadState;  
  17.     }  
  18.       
  19.     if (gShutdown) return NULL;  
  20.       
  21.     pthread_mutex_lock(&gTLSMutex);  
  22.     if (!gHaveTLS) {  
  23.         if (pthread_key_create(&gTLS, threadDestructor) != 0) {  
  24.             pthread_mutex_unlock(&gTLSMutex);  
  25.             return NULL;  
  26.         }  
  27.         gHaveTLS = true;  
  28.     }  
  29.     pthread_mutex_unlock(&gTLSMutex);  
  30.     goto restart;  
  31. }  

接着来看看IPCThreadState的构造函数。

[cpp] view plain copy
  1. IPCThreadState::IPCThreadState()  
  2.     : mProcess(ProcessState::self()),  
  3.       mMyThreadId(androidGetTid()),  
  4.       mStrictModePolicy(0),  
  5.       mLastTransactionBinderFlags(0)  
  6. {  
  7.     // 在构造函数中,把自己设置到了TLS中。  
  8.     pthread_setspecific(gTLS, this);  
  9. clearCaller();  
  10. // mIn和mOut两个都是Parcel,可以把它看成发送和接受数据的缓冲区。  
  11.     mIn.setDataCapacity(256);  
  12.     mOut.setDataCapacity(256);  
  13. }  

主要的数据传输工作还是在IPCThreadState的transact函数中:

[cpp] view plain copy
  1. status_t IPCThreadState::transact(int32_t handle,  
  2.                                   uint32_t code, const Parcel& data,  
  3.                                   Parcel* reply, uint32_t flags)  
  4. {  
  5.     status_t err = data.errorCheck();  
  6.   
  7.     flags |= TF_ACCEPT_FDS;  
  8.   
  9.     …….  
  10.       
  11. if (err == NO_ERROR) {  
  12.         // BC_TRANSACTION是应用程序向底层binder设备发送消息的消息码,  
  13.         // 底层binder设备向应用程序回复消息则以BR_开头。  
  14.         err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);  
  15. }  
  16.   
  17.     if ((flags & TF_ONE_WAY) == 0) {  
  18.         if (reply) {  
  19.             err = waitForResponse(reply);  
  20.         } else {  
  21.             Parcel fakeReply;  
  22.             err = waitForResponse(&fakeReply);  
  23.         }  
  24.     } else {  
  25.         err = waitForResponse(NULL, NULL);  
  26.     }  
  27.       
  28.     return err;  
  29. }  

这个函数很简单,就是调用writeTransactionData函数向底层发送数据,然后调用waitForResponse等待底层的应答。


接着来看writeTransactionData:

[cpp] view plain copy
  1. status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,  
  2.     int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)  
  3. {  
  4.     binder_transaction_data tr;  
  5.   
  6.     // 此处的handle标识了要发送数据的目标端,0即代表ServiceManager  
  7.     tr.target.handle = handle;  
  8.     tr.code = code;  
  9.     tr.flags = binderFlags;  
  10.     tr.cookie = 0;  
  11.     tr.sender_pid = 0;  
  12.     tr.sender_euid = 0;  
  13.       
  14.     const status_t err = data.errorCheck();  
  15.     if (err == NO_ERROR) {  
  16.         tr.data_size = data.ipcDataSize();  
  17.         tr.data.ptr.buffer = data.ipcData();  
  18.         tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);  
  19.         tr.data.ptr.offsets = data.ipcObjects();  
  20.     } else if (statusBuffer) {  
  21.         tr.flags |= TF_STATUS_CODE;  
  22.         *statusBuffer = err;  
  23.         tr.data_size = sizeof(status_t);  
  24.         tr.data.ptr.buffer = statusBuffer;  
  25.         tr.offsets_size = 0;  
  26.         tr.data.ptr.offsets = NULL;  
  27.     } else {  
  28.         return (mLastError = err);  
  29.     }  
  30.       
  31.     // 把要发送的数据写到mOut中去,而不是真正的发送  
  32.     mOut.writeInt32(cmd);  
  33.     mOut.write(&tr, sizeof(tr));  
  34.       
  35.     return NO_ERROR;  
  36. }  
这个函数并不是真正的发送数据,而是将要发送的数据写到了mOut中去,等待后面的发送操作。


发送出去之后,再等待答复waitForResponse:

[cpp] view plain copy
  1. status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)  
  2. {  
  3.     int32_t cmd;  
  4.     int32_t err;  
  5.   
  6. while (1) {  
  7.     /* 
  8. 原来最终还是在IPCThreadState类中通过talkWithDriver与底层Binder设备建立数据通信,包括发送数据和接收数据。 
  9.         */  
  10.         if ((err=talkWithDriver()) < NO_ERROR) break;  
  11.         err = mIn.errorCheck();  
  12.         if (err < NO_ERROR) break;  
  13.         if (mIn.dataAvail() == 0) continue;  
  14.           
  15.         cmd = mIn.readInt32();  
  16.           
  17.         IF_LOG_COMMANDS() {  
  18.             alog << "Processing waitForResponse Command: "  
  19.                 << getReturnString(cmd) << endl;  
  20.         }  
  21.   
  22.         switch (cmd) {  
  23.         case BR_TRANSACTION_COMPLETE:  
  24.             if (!reply && !acquireResult) goto finish;  
  25.             break;  
  26.           
  27.         ……  
  28.   
  29.         default:  
  30.             err = executeCommand(cmd);  
  31.             if (err != NO_ERROR) goto finish;  
  32.             break;  
  33.         }  
  34.     }  
  35.   
  36. finish:  
  37.     if (err != NO_ERROR) {  
  38.         if (acquireResult) *acquireResult = err;  
  39.         if (reply) reply->setError(err);  
  40.         mLastError = err;  
  41.     }  
  42.       
  43.     return err;  
  44. }  

加入我们在发送了数据之后,然后马上得到了回应,此时将执行executeCommand:

[cpp] view plain copy
  1. status_t IPCThreadState::executeCommand(int32_t cmd)  
  2. {  
  3.     BBinder* obj;  
  4.     RefBase::weakref_type* refs;  
  5.     status_t result = NO_ERROR;  
  6.       
  7.     switch (cmd) {  
  8.     case BR_ERROR:  
  9.         result = mIn.readInt32();  
  10.         break;  
  11.           
  12.     …...  
  13.       
  14.     case BR_TRANSACTION:  
  15.         {  
  16.             binder_transaction_data tr;  
  17.             result = mIn.read(&tr, sizeof(tr));  
  18.             ALOG_ASSERT(result == NO_ERROR,  
  19.                 "Not enough command data for brTRANSACTION");  
  20.             if (result != NO_ERROR) break;  
  21.               
  22.             Parcel buffer;  
  23.             buffer.ipcSetDataReference(  
  24.                 reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),  
  25.                 tr.data_size,  
  26.                 reinterpret_cast<const size_t*>(tr.data.ptr.offsets),  
  27.                 tr.offsets_size/sizeof(size_t), freeBuffer, this);  
  28.               
  29.             const pid_t origPid = mCallingPid;  
  30.             const uid_t origUid = mCallingUid;  
  31.               
  32.             mCallingPid = tr.sender_pid;  
  33.             mCallingUid = tr.sender_euid;  
  34.               
  35.             int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);  
  36.             if (gDisableBackgroundScheduling) {  
  37.                 if (curPrio > ANDROID_PRIORITY_NORMAL) {  
  38.                     // We have inherited a reduced priority from the caller, but do not  
  39.                     // want to run in that state in this process.  The driver set our  
  40.                     // priority already (though not our scheduling class), so bounce  
  41.                     // it back to the default before invoking the transaction.  
  42.                     setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);  
  43.                 }  
  44.             } else {  
  45.                 if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {  
  46.                     // We want to use the inherited priority from the caller.  
  47.                     // Ensure this thread is in the background scheduling class,  
  48.                     // since the driver won't modify scheduling classes for us.  
  49.                     // The scheduling group is reset to default by the caller  
  50.                     // once this method returns after the transaction is complete.  
  51.                     set_sched_policy(mMyThreadId, SP_BACKGROUND);  
  52.                 }  
  53.             }  
  54.   
  55.             //ALOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);  
  56.               
  57.             Parcel reply;  
  58.             if (tr.target.ptr) {  
  59.                 sp<BBinder> b((BBinder*)tr.cookie);  
  60.                 const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);  
  61.                 if (error < NO_ERROR) reply.setError(error);  
  62.   
  63.             } else {  
  64.                 const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);  
  65.                 if (error < NO_ERROR) reply.setError(error);  
  66.             }  
  67.               
  68.             //ALOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",  
  69.             //     mCallingPid, origPid, origUid);  
  70.               
  71.             if ((tr.flags & TF_ONE_WAY) == 0) {  
  72.                 LOG_ONEWAY("Sending reply to %d!", mCallingPid);  
  73.                 sendReply(reply, 0);  
  74.             } else {  
  75.                 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);  
  76.             }  
  77.               
  78.             mCallingPid = origPid;  
  79.             mCallingUid = origUid;  
  80.   
  81.             IF_LOG_TRANSACTIONS() {  
  82.                 TextOutput::Bundle _b(alog);  
  83.                 alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "  
  84.                     << tr.target.ptr << ": " << indent << reply << dedent << endl;  
  85.             }  
  86.               
  87.         }  
  88.         break;  
  89.       
  90.     case BR_DEAD_BINDER:  
  91.         {  
  92.             BpBinder *proxy = (BpBinder*)mIn.readInt32();  
  93.             proxy->sendObituary();  
  94.             mOut.writeInt32(BC_DEAD_BINDER_DONE);  
  95.             mOut.writeInt32((int32_t)proxy);  
  96.         } break;  
  97.           
  98.     case BR_CLEAR_DEATH_NOTIFICATION_DONE:  
  99.         {  
  100.             BpBinder *proxy = (BpBinder*)mIn.readInt32();  
  101.             proxy->getWeakRefs()->decWeak(proxy);  
  102.         } break;  
  103.           
  104.    ……  
  105.           
  106.     case BR_SPAWN_LOOPER:  
  107.         mProcess->spawnPooledThread(false);  
  108.         break;  
  109.           
  110.     default:  
  111.         printf("*** BAD COMMAND %d received from Binder driver\n", cmd);  
  112.         result = UNKNOWN_ERROR;  
  113.         break;  
  114.     }  
  115.   
  116.     if (result != NO_ERROR) {  
  117.         mLastError = result;  
  118.     }  
  119.       
  120.     return result;  
  121. }  

上面的writeTransactionData和waitForResponse函数都没有看到与binder通信的部分,其实秘密就在talkWithDriver函数中:

[cpp] view plain copy
  1. status_t IPCThreadState::talkWithDriver(bool doReceive)  
  2. {  
  3.     if (mProcess->mDriverFD <= 0) {  
  4.         return -EBADF;  
  5.     }  
  6.       
  7.     binder_write_read bwr;  
  8.       
  9.     // Is the read buffer empty?  
  10.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  11.       
  12.     // We don't want to write anything if we are still reading  
  13.     // from data left in the input buffer and the caller  
  14.     // has requested to read the next data.  
  15.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  16.       
  17.     bwr.write_size = outAvail;  
  18.     bwr.write_buffer = (long unsigned int)mOut.data();  
  19.   
  20.     // This is what we'll read.  
  21.     if (doReceive && needRead) {  
  22.         bwr.read_size = mIn.dataCapacity();  
  23.         bwr.read_buffer = (long unsigned int)mIn.data();  
  24.     } else {  
  25.         bwr.read_size = 0;  
  26.         bwr.read_buffer = 0;  
  27.     }  
  28.       
  29.     // Return immediately if there is nothing to do.  
  30.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  31.   
  32.     bwr.write_consumed = 0;  
  33.     bwr.read_consumed = 0;  
  34.     status_t err;  
  35.     do {  
  36. #if defined(HAVE_ANDROID_OS)  
  37.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  38.             err = NO_ERROR;  
  39.         else  
  40.             err = -errno;  
  41. #else  
  42.         err = INVALID_OPERATION;  
  43. #endif  
  44.         if (mProcess->mDriverFD <= 0) {  
  45.             err = -EBADF;  
  46.         }  
  47.     } while (err == -EINTR);  
  48.   
  49.     if (err >= NO_ERROR) {  
  50.         if (bwr.write_consumed > 0) {  
  51.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  52.                 mOut.remove(0, bwr.write_consumed);  
  53.             else  
  54.                 mOut.setDataSize(0);  
  55.         }  
  56.         if (bwr.read_consumed > 0) {  
  57.             mIn.setDataSize(bwr.read_consumed);  
  58.             mIn.setDataPosition(0);  
  59.         }  
  60.   
  61.         return NO_ERROR;  
  62.     }  
  63.       
  64. return err;  
  65. }  

原来应用层最后是调用ioctl来和底层binder设备进行数据的互通的,包括读、写。此时,就已经往底层binder驱动中注册了MediaPlayerService服务了。


开始消息循环

再来看Mediaserver min函数的最后两句代码:

[cpp] view plain copy
  1. // 开始循环接收消息  
  2. ProcessState::self()->startThreadPool();  
  3. IPCThreadState::self()->joinThreadPool();  

首先来看startThreadPool函数的实现:

[cpp] view plain copy
  1. void ProcessState::startThreadPool()  
  2. {  
  3.     AutoMutex _l(mLock);  
  4.     if (!mThreadPoolStarted) {  
  5.         mThreadPoolStarted = true;  
  6.         // 注意此处参数为true  
  7.         spawnPooledThread(true);  
  8.     }  
  9. }  

[cpp] view plain copy
  1. void ProcessState::spawnPooledThread(bool isMain)  
  2. {  
  3.     if (mThreadPoolStarted) {  
  4.         String8 name = makeBinderThreadName();  
  5.         ALOGV("Spawning new pooled thread, name=%s\n", name.string());  
  6.         sp<Thread> t = new PoolThread(isMain);  
  7.         t->run(name.string());  
  8.     }  
  9. }  

调用new PoolThread(isMain)创建了一个新线程。PoolThread是继承自Thread的线程类。

[cpp] view plain copy
  1. class PoolThread : public Thread  
  2. {  
  3. public:  
  4.     PoolThread(bool isMain)  
  5.         : mIsMain(isMain)  
  6.     {  
  7.     }  
  8.       
  9. protected:  
  10.     virtual bool threadLoop()  
  11. {  
  12.     // 线程主循环函数也很简单,就是调用了IPCThreadState类的joinThreadPool  
  13.         IPCThreadState::self()->joinThreadPool(mIsMain);  
  14.         return false;  
  15.     }  
  16.       
  17.     const bool mIsMain;  
  18. };  


煞费苦心,新创建的线程最后调用的还是IPCThreadState的joinThreadPool函数。我们主要来看它的实现:

[cpp] view plain copy
  1. void IPCThreadState::joinThreadPool(bool isMain)  
  2. {  
  3.     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  4.       
  5.     // This thread may have been spawned by a thread that was in the background  
  6.     // scheduling group, so first we will make sure it is in the foreground  
  7.     // one to avoid performing an initial transaction in the background.  
  8.     set_sched_policy(mMyThreadId, SP_FOREGROUND);  
  9.           
  10.     status_t result;  
  11.     do {  
  12.         processPendingDerefs();  
  13.         // now get the next command to be processed, waiting if necessary  
  14.         result = getAndExecuteCommand();  
  15.   
  16.         if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {  
  17.             ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",  
  18.                   mProcess->mDriverFD, result);  
  19.             abort();  
  20.         }  
  21.           
  22.         // Let this thread exit the thread pool if it is no longer  
  23.         // needed and it is not the main process thread.  
  24.         if(result == TIMED_OUT && !isMain) {  
  25.             break;  
  26.         }  
  27.     } while (result != -ECONNREFUSED && result != -EBADF);  
  28.   
  29.     LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",  
  30.         (void*)pthread_self(), getpid(), (void*)result);  
  31.       
  32.     mOut.writeInt32(BC_EXIT_LOOPER);  
  33.     talkWithDriver(false);  
  34. }  

主要实现还是在getAndExecuteCommand函数中:

[cpp] view plain copy
  1. status_t IPCThreadState::getAndExecuteCommand()  
  2. {  
  3.     status_t result;  
  4.     int32_t cmd;  
  5.   
  6.     result = talkWithDriver();  
  7.     if (result >= NO_ERROR) {  
  8.         size_t IN = mIn.dataAvail();  
  9.         if (IN < sizeof(int32_t)) return result;  
  10.         cmd = mIn.readInt32();  
  11.         IF_LOG_COMMANDS() {  
  12.             alog << "Processing top-level Command: "  
  13.                  << getReturnString(cmd) << endl;  
  14.         }  
  15.   
  16.         result = executeCommand(cmd);  
  17.   
  18.         // After executing the command, ensure that the thread is returned to the  
  19.         // foreground cgroup before rejoining the pool.  The driver takes care of  
  20.         // restoring the priority, but doesn't do anything with cgroups so we  
  21.         // need to take care of that here in userspace.  Note that we do make  
  22.         // sure to go in the foreground after executing a transaction, but  
  23.         // there are other callbacks into user code that could have changed  
  24.         // our group so we want to make absolutely sure it is put back.  
  25.         set_sched_policy(mMyThreadId, SP_FOREGROUND);  
  26.     }  
  27.   
  28.     return result;  
  29. }  

getAndExecuteCommand是通过talkWithDriver函数与底层binder设备进行通信的,得到返回数据后调用executeCommand处理相应的消息。

0 0