Service Manager Handle Add Service
到现在为止,service_manager已经得到了一个从media_server发送过来的BR_TRANSACTION类型的数据包,于是它调用binder_parser()函数去处理该数据包。
-
- int binder_parse(struct binder_state *bs, struct binder_io *bio,
- uint32_t *ptr, uint32_t size, binder_handler func)
- {
- ......
- case BR_TRANSACTION: {
- struct binder_txn *txn = (void *) ptr;
- if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
- LOGE("parse: txn too small!/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;
- }
- ......
- }
binder_parse会调用svcmgr_handler(也就是参数func)按照BpServerManager相反的步骤处理BR_TRANSACTION数据包。这里binder_txn结构实际上与binder_transaction_data结构是一样的。在本文的例子中,事务码(transaction code)为SVC_MGR_ADD_SERVICE。
-
- 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;
- if (txn->target != svcmgr_handle)
- return -1;
- 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);
- 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);
- if (do_add_service(bs, s, len, ptr, txn->sender_euid))
- 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:
- LOGE("unknown code %d/n", txn->code);
- return -1;
- }
- bio_put_uint32(reply, 0);
- return 0;
- }
于是service_manager知道了一个名为s的服务将会运行,并且ervice_manager通过bio_get_ref()获取到对象的信息。
-
- void *bio_get_ref(struct binder_io *bio)
- {
- struct binder_object *obj;
- obj = _bio_get_obj(bio);
- if (!obj)
- return 0;
- if (obj->type == BINDER_TYPE_HANDLE)
- return obj->pointer;
- return 0;
- }
bio_get_ref()函数做的工作与flatten_binder()函数相反。do_add_service()函数最终会调用binder_acquire()来获取ptr所指对象的强引用。
小结:
本节展示了服务是如何添加到service manager中去的。
假设你想要实现自己的服务IFunnyTest,你需要做一下步骤:
- 将你的服务的名字添加到service_manager中的allowed service列表中。
Get IAudioFlinger
获取服务接口的唯一方法就是通过IServiceManager::getService()函数。假设AudioSystem需要获取一个IAudioFlinger。
-
-
- const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
- {
- Mutex::Autolock _l(gLock);
- if (gAudioFlinger.get() == 0) {
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> binder;
- do {
- binder = sm->getService(String16("media.audio_flinger"));
- if (binder != 0)
- break;
- LOGW("AudioFlinger not published, waiting...");
- usleep(500000);
- } while(true);
- if (gAudioFlingerClient == NULL) {
- gAudioFlingerClient = new AudioFlingerClient();
- } else {
- if (gAudioErrorCallback) {
- gAudioErrorCallback(NO_ERROR);
- }
- }
- binder->linkToDeath(gAudioFlingerClient);
- gAudioFlinger = interface_cast<IAudioFlinger>(binder);
- gAudioFlinger->registerClient(gAudioFlingerClient);
- }
- LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
- return gAudioFlinger;
- }
IServiceManager::getService()函数会调用BpServiceManager::getService()函数。
- virtual sp<IBinder> getService(const String16& name) const
- {
- unsigned n;
- for (n = 0; n < 5; n++){
- sp<IBinder> svc = checkService(name);
- if (svc != NULL) return svc;
- LOGI("Waiting for sevice %s.../n", String8(name).string());
- sleep(1);
- }
- return NULL;
- }
-
- virtual sp<IBinder> checkService( const String16& name) const
- {
- Parcel data, reply;
- data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
- data.writeString16(name);
- remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
- return reply.readStrongBinder();
- }
与前文分析类似,该调用最终会通过binder内核驱动在service_manager进程中处理。代码参见上一节svcmgr_handler()函数的SVC_MGR_GET_SERVICE分支。
此时service_manager会回复一个之前由media_server设置的的handle(也就是AudioFlinger的实例的地址)。BpServiceManager::checkService()会由remote()->transact()调用返回。与IServiceManager的分析类似,它会创建一个新的BpBinder实例指向service_manager返回的handle。interface_cast<IAudioFlinger>(binder) 最终返回一个BpAudioFlinger实例。
小结:
与获取IServieManager类似,但是这一次是通过service_manager去获取一个handle。之前获取IServiceManager时总是返回handle 0。
RPC Call IAudioFlinger::SetMode
如果我们在AAA这个进程中调用IAudioFlinger::SetMode()函数,实际上是调用的BpAudioFlinger::setMode()函数。
-
- class BpAudioFlinger : public BpInterface<IAudioFlinger>
- {
- public:
- ......
- virtual status_t setMode(int mode)
- {
- Parcel data, reply;
- data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
- data.writeInt32(mode);
- remote()->transact(SET_MODE, data, &reply);
- return reply.readInt32();
- }
- ......
- }
与IServiceManager::addService()类似,该函数最终会生成一个数据包,并写入到binder内核驱动中,然后等待读取回复。不同的是,这次的target handle指向了media_server进程中的某个地址。
Handle IAudioFlinger::SetMode
binder内核驱动最终会唤醒media_server进程中的在IPCThreadState::joinThreadPool()中运行的读线程。现在让我们回顾一下这段代码。
- void IPCThreadState::joinThreadPool(bool isMain)
- {
- LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL/n", (void*)pthread_self(), getpid());
- mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
-
- status_t result;
- do {
- int32_t cmd;
-
-
- if (mIn.dataPosition() >= mIn.dataSize()) {
- size_t numPending = mPendingWeakDerefs.size();
- if (numPending > 0) {
- for (size_t i = 0; i < numPending; i++) {
- RefBase::weakref_type* refs = mPendingWeakDerefs[i];
- refs->decWeak(mProcess.get());
- }
- mPendingWeakDerefs.clear();
- }
- numPending = mPendingStrongDerefs.size();
- if (numPending > 0) {
- for (size_t i = 0; i < numPending; i++) {
- BBinder* obj = mPendingStrongDerefs[i];
- obj->decStrong(mProcess.get());
- }
- mPendingStrongDerefs.clear();
- }
- }
-
- result = talkWithDriver();
- if (result >= NO_ERROR) {
- size_t IN = mIn.dataAvail();
- if (IN < sizeof(int32_t)) continue;
- cmd = mIn.readInt32();
- IF_LOG_COMMANDS() {
- alog << "Processing top-level Command: "
- << getReturnString(cmd) << endl;
- }
- result = executeCommand(cmd);
- }
-
-
-
-
-
- int my_id;
- #ifdef HAVE_GETTID
- my_id = gettid();
- #else
- my_id = getpid();
- #endif
- if (!set_sched_policy(my_id, SP_FOREGROUND)) {
-
- setpriority(PRIO_PROCESS, my_id, ANDROID_PRIORITY_NORMAL);
- }
-
-
- if(result == TIMED_OUT && !isMain) {
- break;
- }
- } while (result != -ECONNREFUSED && result != -EBADF);
- LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p/n",
- (void*)pthread_self(), getpid(), (void*)result);
-
- mOut.writeInt32(BC_EXIT_LOOPER);
- talkWithDriver(false);
- }
这一次,talkWithDriver()函数会返回BpServiceManager::setMode()生成的数据包,并调用executeCommand()函数执行命令。在本例中,命令为BR_TRANSACTION。
- status_t IPCThreadState::executeCommand(int32_t cmd)
- {
- ......
- switch(cmd){
- ......
- case BR_TRANSACTION:
- {
- binder_transaction_data tr;
- ......
- Parcel reply;
- ......
- if (tr.target.ptr) {
- sp<BBinder> b((BBinder*)tr.cookie);
- const status_t error = b->transact(tr.code, buffer, &reply, 0);
- if (error < NO_ERROR) reply.setError(error);
-
- } else {
- const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0);
- if (error < NO_ERROR) reply.setError(error);
- }
-
- if ((tr.flags & TF_ONE_WAY) == 0) {
- LOG_ONEWAY("Sending reply to %d!", mCallingPid);
- sendReply(reply, 0);
- } else {
- LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
- }
-
- ......
- }
- break;
- ......
- }
- ......
- }
if(tr.target.ptr)为真的分支部分是最重要的。它从binder内核驱动中获取到一个地址并转换为BBinder类型的指针(该指针在执行IServiceManager::addService()函数时放入binder内核驱动)。记住,AudioFlinger继承自BBinder。该指针实际上与AudioFlinger实例是同一个指针。于是接下来的transact()函数调用最终是调用的BnAudioFlinger的onTransact()虚函数。
- status_t BnAudioFlinger::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- ......
- case SET_MODE: {
- CHECK_INTERFACE(IAudioFlinger, data, reply);
- int mode = data.readInt32();
- reply->writeInt32( setMode(mode) );
- return NO_ERROR;
- } break;
- ......
- }
- }
然后调用sendReply()写入reply。
- status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
- {
- status_t err;
- status_t statusBuffer;
- err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
- if (err < NO_ERROR) return err;
-
- return waitForResponse(NULL, NULL);
- }
结果(reply)被写入到binder内核驱动。然后内核驱动会唤醒AAA进程中的读线程(去取结果)。
总结
Android IPC system一共由四个部分组成:
- Binder驱动:IPC系统的核心。在服务提供方(service provider)和服务使用方(service user)之间传输数据。
- 服务提供方:提供某种服务。解析从binder驱动中收到的RPC调用数据,并执行相应的动作。
- service_manager:一个特殊的服务提供方。为其他的服务提供方提供服务管理服务。
- 服务使用方:远程调用服务提供方。生成一个RPC调用数据,然后发送给binder驱动。
本文例子中主要的流程如下:
1. service_manager启动。在binder驱动中注册一个特殊节点0。
2. media_server从该特殊节点0获取到一个IServiceManager代理。
3. media_server调用IServiceManager::addService()去添加IAudioFlinger服务。该调用发送给节点0,由节点0发送给binder驱动。
4. binder驱动知道该数据是给节点0,并且包含有binder一个对象的命令。于是它生成另一个节点(假设为A)给IAudioFlinger服务,并将数据发送给service_manager。
5. service_manager从binder驱动中读取该数据,然后处理IServiceManager::addService()远程调用。
6. 另一个进程P获取到节点0的一个IServiceManager代理。
7. 进程P调用IServiceManager::getService()来获取IAudioFlinger服务。该调用会发送给节点0,节点0发送数据给binder驱动。
8. binder驱动知道数据是给节点0,于是将它传递给service_manager。
9. service_manager从binder驱动中读取数据,然后处理IServiceManager::getService()调用,并返回代表IAudioFlinger服务的节点A。
10. 进程P调用IAudioFlinger::setMode,调用会传递给节点A。
11. binder驱动知道数据是给节点A,于是将数据传递给media_server。
12. media_server从binder驱动中读取数据,然后处理IAudioFlinger::setMode()远程调用,然后发送reply数据给binder驱动。
13. binder驱动将reply传递给进程P。
14. 进程P从binder驱动中读取数据并最终获取到reply。
|