Binder: addService初探
source link: https://mp.weixin.qq.com/s?__biz=MzIzNTc5NDY4Nw%3D%3D&%3Bmid=2247485610&%3Bidx=1&%3Bsn=2ef38084699d2fcc5241a6cc57772751
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
点
击
蓝
字
关
注
我
们
吧
在 Binder: ServiceManager的获取 文章中,分析了 ProcessState
与 IPCThreadState
的创建过程。最后在 defaultServiceManager
中,返回的是持有 BpBinder
的 BpServiceManager
对象。
int main(int argc __unused, char **argv __unused) { signal(SIGPIPE, SIG_IGN); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> 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<IBinder>& 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<IServiceManager> public: explicit BpServiceManager(const sp<IBinder>& impl) // BpBinder(0) : BpInterface<IServiceManager>(impl) {} inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote) BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(nullptr), mState(0) class BpRefBase : public virtual RefBase { protected: explicit BpRefBase(const sp<IBinder>& 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<int32_t> 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<Thread> 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<RefBase::weakref_type*>( tr.target.ptr)->attemptIncStrong(this)) { // BBinder error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast<BBinder*>(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
端,看它是如何接收与处理数据的。
扫码二维码
获取更多精彩
Android补给站
点个 在看 你最好看
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK