Binder: addService初探
在 Binder: ServiceManager的获取 文章中,分析了 ProcessState
与 IPCThreadState
的创建过程。最后在 defaultServiceManager
中,返回的是持有 BpBinder
的 BpServiceManager
对象。
int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); sp proc(ProcessState::self()); sp sm(defaultServiceManager()); // BpServiceManager ALOGI("ServiceManager: %p", sm.get()); AIcu_initializeIcuOrDie(); MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions(); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); } void MediaPlayerService::instantiate() { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); }
所以在 instantiate
方法中调用的 addService
其实是 BpServiceManager
中的方法,将名称为 media.player
的 MediaPlayerService
对象进行注册
addService
下面我们直接看 BpServiceManager
中的 addService
。
virtual status_t addService(const String16& name, const sp& service, bool allowIsolated, int dumpsysPriority) { // 封装成Parcel对象 Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); data.writeInt32(dumpsysPriority); // 发送数据到远端 status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }
这里将数据统一封装到 Parcel
对象中,最后通过 remote()
的 transact
方法将数据传输到远端,对应的 code
为 ADD_SERVICE_TRANSACTION
。
现在我们在来看下 remote()
到底是什么。
它是 BpServiceManager
中的一个方法,这个方法来自于它的父类
class BpServiceManager : public BpInterface public: explicit BpServiceManager(const sp& impl) // BpBinder(0) : BpInterface(impl) {} inline BpInterface::BpInterface(const sp& remote) : BpRefBase(remote) BpRefBase::BpRefBase(const sp& o) : mRemote(o.get()), mRefs(nullptr), mState(0) class BpRefBase : public virtual RefBase { protected: explicit BpRefBase(const sp& o); virtual ~BpRefBase(); virtual void onFirstRef(); virtual void onLastStrongRef(const void* id); virtual bool onIncStrongAttempted(uint32_t flags, const void* id); inline IBinder* remote() { return mRemote; } inline IBinder* remote() const { return mRemote; } private: BpRefBase(const BpRefBase& o); BpRefBase& operator=(const BpRefBase& o); IBinder* const mRemote; RefBase::weakref_type* mRefs; std::atomic mState; };
从上面继承流程可以得到这个 remote()
返回的就是 mRemote
,而 mRemote
其实是最开始的参数 BpBinder(0)
。说明这里调用的是 BpBinder
的 transact
方法
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come 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; }
进入 BpBinder
发现又转调到 IPCThreadState
的 transact
方法
status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ... // 传输数据 err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr); if ((flags & TF_ONE_WAY) == 0) { ... if (reply) { // 等待远程数据的返回 err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } } else { err = waitForResponse(nullptr, nullptr); } return err; }
这里主要做的就两件事
-
writeTransactionData Parcel cmd BC_TRANSACTION BC_ service
-
waitForResponse cmd BR_REPLY BR_ client
今天我们不研究这几个方法,后续文章会专门分析数据的交互。
到这里 MediaPlayerService
已经注册完毕,我们接下最前面的 main
方法继续往下走。
startThreadPool
ProcessState::self()->startThreadPool();
又是 ProcessState
中的方法,进入 startThreadPooll
中看一下。
void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true); } } void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); // 开启binder线程池 sp t = new PoolThread(isMain); t->run(name.string()); } }
在 spawnPooledThread
方法中创建了 PoolThread
线程池,它继承于 Thread
,最后调用了线程的 run
方法
joinThreadPool
IPCThreadState::self()->joinThreadPool();
继续看 joinThreadPooll
方法, 它在 IPCThreadState
中
void IPCThreadState::joinThreadPool(bool isMain) { mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); status_t result; do { processPendingDerefs(); // 等待命令行的到来 result = getAndExecuteCommand(); } while (result != -ECONNREFUSED && result != -EBADF); mOut.writeInt32(BC_EXIT_LOOPER); // 与binder驱动通信 talkWithDriver(false); }
这里主要的方法是 getAndExecuteCommand()
,它是用来处理接收 service
端发送过来的数据,因为 service
与 client
是可以互相发起数据的交互。这个时候 client
就相当于 service
,它开启轮询不断地监听 service
发过来的数据。最终它会调用 executeCommand
来统一处理。
status_t IPCThreadState::executeCommand(int32_t cmd) { switch ((uint32_t)cmd) { ... case BR_TRANSACTION_SEC_CTX: case BR_TRANSACTION: { ... if (tr.target.ptr) { if (reinterpret_cast( tr.target.ptr)->attemptIncStrong(this)) { // BBinder error = reinterpret_cast(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast(tr.cookie)->decStrong(this); } else { error = UNKNOWN_TRANSACTION; } } else { error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); } ... if ((tr.flags & TF_ONE_WAY) == 0) { // 向服务端发送回应reply,注意这里的0,特定标识; sendReply(reply, 0); } else { LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); } ... } break; ... default: ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd); result = UNKNOWN_ERROR; break; } if (result != NO_ERROR) { mLastError = result; } return result; }
为了简化代码只展示了主要的一部分代码, BR_TRANSACTION
类似于上面所说的 BC_TRANSACTION
,这里代表的是从服务端有数据发送过来,说明服务端主动传输数据。
所以这个时候就与 service
端建立了通信。
至此在 client
端的数据交互流程已经分析完毕,后续我们再来看 binder
传输过程中的 service
端,看它是如何接收与处理数据的。