Android Binder原理(五)系统服务的获取过程

  • Binder原理
  • Android框架层

本文首发于微信公众号「后厂技术官」

<!--more-->

前言

在本系列的此前文章中,以MediaPlayerService为例,讲解了系统服务是如何注册的(addService),既然有注册那肯定也要有获取,本篇文章仍旧以MediaPlayerService为例,来讲解系统服务的获取过程(getService)。文章会分为两个部分进行讲解,分别是客户端MediaPlayerService请求获取服务和服务端ServiceManager处理请求,先来学习第一部分。

1.客户端MediaPlayerService请求获取服务

要想获取MediaPlayerService,需要先调用getMediaPlayerService函数,如下所示。 frameworks/av/media/libmedia/IMediaDeathNotifier.cpp

1IMediaDeathNotifier::getMediaPlayerService() 2{ 3 ALOGV("getMediaPlayerService"); 4 Mutex::Autolock _l(sServiceLock); 5 if (sMediaPlayerService == 0) { 6 sp<IServiceManager> sm = defaultServiceManager();//1 7 sp<IBinder> binder; 8 do { 9 binder = sm->getService(String16("media.player"));//2 10 if (binder != 0) {//3 11 break; 12 } 13 ALOGW("Media player service not published, waiting..."); 14 usleep(500000); //4 15 } while (true); 16 17 if (sDeathNotifier == NULL) { 18 sDeathNotifier = new DeathNotifier(); 19 } 20 binder->linkToDeath(sDeathNotifier); 21 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);//5 22 } 23 ALOGE_IF(sMediaPlayerService == 0, "no media player service!?"); 24 return sMediaPlayerService; 25}

注释1处的defaultServiceManager返回的是BpServiceManager,注释2处获取名为”media.player”的系统服务(MediaPlayerService),返回的值为BpBinder。由于这个时候MediaPlayerService可能还没有向ServiceManager注册,那么就不能满足注释3的条件,在注释4处休眠0.5s后继续调用getService函数,直到获取服务对应的为止。 注释5处的interface_cast函数用于将BpBinder转换成BpMediaPlayerService,其原理就是通过BpBinder的handle来找到对应的服务,即BpMediaPlayerService。

注释2处的获取服务是本文的重点,BpServiceManager的getService函数如下所示。 frameworks/native/libs/binder/IServiceManager.cpp::BpServiceManager

1 virtual sp<IBinder> getService(const String16& name) const 2 { 3 ... 4 int n = 0; 5 while (uptimeMillis() < timeout) { 6 n++; 7 if (isVendorService) { 8 ALOGI("Waiting for vendor service %s...", String8(name).string()); 9 CallStack stack(LOG_TAG); 10 } else if (n%10 == 0) { 11 ALOGI("Waiting for service %s...", String8(name).string()); 12 } 13 usleep(1000*sleepTime); 14 15 sp<IBinder> svc = checkService(name);//1 16 if (svc != NULL) return svc; 17 } 18 ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); 19 return NULL; 20 }

getService函数中主要做的事就是循环的查询服务是否存在,如果不存在就继续查询,查询服务用到了注释1处的checkService函数,代码如下所示。 frameworks/native/libs/binder/IServiceManager.cpp::BpServiceManager

1 virtual sp<IBinder> checkService( const String16& name) const 2 { 3 Parcel data, reply;//1 4 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); 5 data.writeString16(name);//2 6 remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);//3 7 return reply.readStrongBinder(); 8 }

注释1处的data,看过上一篇文章的同学应该很熟悉,它出现在BpServiceManager的addService函数中,data是一个数据包,后面会不断的将数据写入到data中。注释2处将字符串"media.player"写入到data中。 注释3处的remote()指的是mRemote,也就是BpBinder,BpBinder的transact函数如下所示。

frameworks/native/libs/binder/BpBinder.cpp

1status_t BpBinder::transact( 2 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 3{ 4 if (mAlive) { 5 status_t status = IPCThreadState::self()->transact( 6 mHandle, code, data, reply, flags); 7 if (status == DEAD_OBJECT) mAlive = 0; 8 return status; 9 } 10 11 return DEAD_OBJECT; 12}

BpBinder将逻辑处理交给IPCThreadState,后面的调用链在Android Binder原理(三)系统服务的注册过程中讲过,这里再次简单的过一遍,IPCThreadState::self()会创建创建IPCThreadState,IPCThreadState的transact函数如下所示。 frameworks/native/libs/binder/IPCThreadState.cpp

1status_t IPCThreadState::transact(int32_t handle, 2 uint32_t code, const Parcel& data, 3 Parcel* reply, uint32_t flags) 4{ 5 status_t err; 6 7 flags |= TF_ACCEPT_FDS; 8 ... 9 err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);//1 10 11 if (err != NO_ERROR) { 12 if (reply) reply->setError(err); 13 return (mLastError = err); 14 } 15 16 if ((flags & TF_ONE_WAY) == 0) { 17 ... 18 if (reply) { 19 err = waitForResponse(reply);//2 20 } else { 21 Parcel fakeReply; 22 err = waitForResponse(&fakeReply); 23 } 24 ... 25 } else { 26 //不需要等待reply的分支 27 err = waitForResponse(NULL, NULL); 28 } 29 30 return err; 31}

调用BpBinder的transact函数实际上就是调用IPCThreadState的transact函数。注释1处的writeTransactionData函数用于传输数据,其中第一个参数BC_TRANSACTION代表向Binder驱动发送命令协议。 注释1处的writeTransactionData用于准备发送的数据,其内部会将BC_TRANSACTION和binder_transaction_data结构体写入到mOut中。 接着查看waitForResponse函数做了什么,代码如下所示。 frameworks/native/libs/binder/IPCThreadState.cpp

1status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) 2{ 3 uint32_t cmd; 4 int32_t err; 5 while (1) { 6 if ((err=talkWithDriver()) < NO_ERROR) break;//1 7 err = mIn.errorCheck(); 8 if (err < NO_ERROR) break; 9 if (mIn.dataAvail() == 0) continue; 10 cmd = (uint32_t)mIn.readInt32(); 11 IF_LOG_COMMANDS() { 12 alog << "Processing waitForResponse Command: " 13 << getReturnString(cmd) << endl; 14 } 15 switch (cmd) { 16 case BR_TRANSACTION_COMPLETE: 17 if (!reply && !acquireResult) goto finish; 18 break; 19 ... 20 default: 21 //处理各种命令协议 22 err = executeCommand(cmd); 23 if (err != NO_ERROR) goto finish; 24 break; 25 } 26} 27finish: 28 ... 29 return err; 30}

注释1处的talkWithDriver函数的内部通过ioctl与Binder驱动进行通信,代码如下所示。 frameworks/native/libs/binder/IPCThreadState.cpp

1status_t IPCThreadState::talkWithDriver(bool doReceive) 2{ 3 if (mProcess->mDriverFD <= 0) { 4 return -EBADF; 5 } 6 //和Binder驱动通信的结构体 7 binder_write_read bwr; //1 8 //mIn是否有可读的数据,接收的数据存储在mIn 9 const bool needRead = mIn.dataPosition() >= mIn.dataSize(); 10 const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; 11 bwr.write_size = outAvail; 12 bwr.write_buffer = (uintptr_t)mOut.data();//2 13 //这时doReceive的值为true 14 if (doReceive && needRead) { 15 bwr.read_size = mIn.dataCapacity(); 16 bwr.read_buffer = (uintptr_t)mIn.data();//3 17 } else { 18 bwr.read_size = 0; 19 bwr.read_buffer = 0; 20 } 21 ... 22 if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; 23 bwr.write_consumed = 0; 24 bwr.read_consumed = 0; 25 status_t err; 26 do { 27 IF_LOG_COMMANDS() { 28 alog << "About to read/write, write size = " << mOut.dataSize() << endl; 29 } 30#if defined(__ANDROID__) 31 if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)//4 32 err = NO_ERROR; 33 else 34 err = -errno; 35#else 36 err = INVALID_OPERATION; 37#endif 38 ... 39 } while (err == -EINTR); 40 ... 41 return err; 42}

注释1处的 binder_write_read是和Binder驱动通信的结构体,在注释2和3处将mOut、mIn赋值给binder_write_read的相应字段,最终通过注释4处的ioctl函数和Binder驱动进行通信。这一过程的时序图如下所示。 MUr7w9.md.png

这时我们需要再次查看Android Binder原理(三)系统服务的注册过程这篇文章第2小节给出的图。 Ka0Dx0.png

从这张简化的流程图可以看出,我们当前分析的是客户端进程的流程,当MediaPlayerService向Binder驱动发送BC_TRANSACTION命令后,Binder驱动会向ServiceManager发送BR_TRANSACTION命令,接下来我们来查看服务端ServiceManager是如何处理获取服务这一请求的。

2.服务端ServiceManager处理请求

说到服务端ServiceManager处理请求,不得不说到ServiceManager的启动过程,具体的请看Android Binder原理(四)ServiceManager的启动过程这篇文章。 这里简单回顾servicemanager的入口函数,如下所示。

frameworks/native/cmds/servicemanager/service_manager.c

1int main(int argc, char** argv) 2{ 3 ... 4 bs = binder_open(driver, 128*1024); 5 ... 6 if (binder_become_context_manager(bs)) { 7 ALOGE("cannot become context manager (%s)\n", strerror(errno)); 8 return -1; 9 } 10 ... 11 if (getcon(&service_manager_context) != 0) { 12 ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n"); 13 abort(); 14 } 15 binder_loop(bs, svcmgr_handler);//1 16 return 0; 17}

main函数主要做了三件事,其中最后一件事就是调用binder_loop函数,这里需要注意,它的第二个参数为svcmgr_handler,后面会再次提到svcmgr_handler。 binder_loop函数如下所示。 frameworks/native/cmds/servicemanager/binder.c

1void binder_loop(struct binder_state *bs, binder_handler func) 2{ 3... 4 for (;;) { 5 bwr.read_size = sizeof(readbuf); 6 bwr.read_consumed = 0; 7 bwr.read_buffer = (uintptr_t) readbuf; 8 9 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 10 11 if (res < 0) { 12 ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); 13 break; 14 } 15 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); 16 if (res == 0) { 17 ALOGE("binder_loop: unexpected reply?!\n"); 18 break; 19 } 20 if (res < 0) { 21 ALOGE("binder_loop: io error %d %s\n", res, strerror(errno)); 22 break; 23 } 24 } 25}

在无限循环中不断的调用ioctl函数,它不断的使用BINDER_WRITE_READ指令查询Binder驱动中是否有新的请求,如果有就交给binder_parse函数处理。如果没有,当前线程就会在Binder驱动中睡眠,等待新的进程间通信请求。 binder_parse函数如下所示。 frameworks/native/cmds/servicemanager/binder.c

1int binder_parse(struct binder_state *bs, struct binder_io *bio, 2 uintptr_t ptr, size_t size, binder_handler func) 3{ 4 int r = 1; 5 uintptr_t end = ptr + (uintptr_t) size; 6 7 while (ptr < end) { 8 uint32_t cmd = *(uint32_t *) ptr; 9 ptr += sizeof(uint32_t); 10#if TRACE 11 fprintf(stderr,"%s:\n", cmd_name(cmd)); 12#endif 13 switch(cmd) { 14 ... 15 case BR_TRANSACTION: { 16 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; 17 if ((end - ptr) < sizeof(*txn)) { 18 ALOGE("parse: txn too small!\n"); 19 return -1; 20 } 21 binder_dump_txn(txn); 22 if (func) { 23 unsigned rdata[256/4]; 24 struct binder_io msg; 25 struct binder_io reply; 26 int res; 27 28 bio_init(&reply, rdata, sizeof(rdata), 4); 29 bio_init_from_txn(&msg, txn); 30 res = func(bs, txn, &msg, &reply);//1 31 if (txn->flags & TF_ONE_WAY) { 32 binder_free_buffer(bs, txn->data.ptr.buffer); 33 } else { 34 binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); 35 } 36 } 37 ptr += sizeof(*txn); 38 break; 39 } 40 ... 41 } 42 43 return r; 44}

这里截取了BR_TRANSACTION命令的处理部分,注释1出的func通过一路传递指向的是svcmgr_handler,svcmgr_handler函数如下所示。 frameworks/native/cmds/servicemanager/service_manager.c

1int svcmgr_handler(struct binder_state *bs, 2 struct binder_transaction_data *txn, 3 struct binder_io *msg, 4 struct binder_io *reply) 5{ 6 ... 7 switch(txn->code) { 8 case SVC_MGR_GET_SERVICE: 9 case SVC_MGR_CHECK_SERVICE: 10 s = bio_get_string16(msg, &len); 11 if (s == NULL) { 12 return -1; 13 } 14 handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid); 15 if (!handle) 16 break; 17 bio_put_ref(reply, handle); 18 return 0; 19 20 ... 21 default: 22 ALOGE("unknown code %d\n", txn->code); 23 return -1; 24 } 25 26 bio_put_uint32(reply, 0); 27 return 0; 28}

当要获取服务时,会调用do_find_service函数,代码如下所示。 frameworks/native/cmds/servicemanager/service_manager.c

1uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid) 2{ 3 struct svcinfo *si = find_svc(s, len);//1 4 5 if (!si || !si->handle) { 6 return 0; 7 } 8 9 if (!si->allow_isolated) { 10 uid_t appid = uid % AID_USER; 11 if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { 12 return 0; 13 } 14 } 15 if (!svc_can_find(s, len, spid, uid)) { 16 return 0; 17 } 18 19 return si->handle; 20}

注释1处的find_svc函数用于查询服务,返回的svcinfo是一个结构体,其内部包含了服务的handle值,最终会返回服务的handle值。接着来看find_svc函数: frameworks/native/cmds/servicemanager/service_manager.c

1struct svcinfo *find_svc(const uint16_t *s16, size_t len) 2{ 3 struct svcinfo *si; 4 5 for (si = svclist; si; si = si->next) { 6 if ((len == si->len) && 7 !memcmp(s16, si->name, len * sizeof(uint16_t))) { 8 return si; 9 } 10 } 11 return NULL; 12}

系统服务的注册流程中,在Kernel Binder中会调用do_add_service函数,其内部会将包含服务名和handle值的svcinfo保存到svclist列表中。同样的,在获取服务的流程中,find_svc函数中会遍历svclist列表,根据服务名查找对应服务是否已经注册,如果已经注册就会返回对应的svcinfo,如果没有注册就返回NULL。

总结

这篇文章将系统服务的获取过程分为两个部分,代码涉及到了Native Binder和Kernel Binder。在下一篇文章中会继续学习Java Binder相关的内容。

点赞
收藏

评论区

加载中...

相关推荐

Android Binder原理(一)学习Binder前必须要了解的知识点

本文首发于微信公众号「刘望舒」前言Binder原理是掌握系统底层原理的基石,也是进阶高级工程师的必备知识点,这篇文章不会过多介绍Binder原理,而是讲解学习Binder前需要的掌握的知识点。1.Linux和Android的IPC机制种类IPC全名为interProcessCommunication,含义为进程间

Android Binder原理(二)ServiceManager中的Binder机制

Binder原理Android框架层本文首发于微信公众号「刘望舒」<more前言在上一篇文章中,我们了解了学习Binder前必须要了解的知识点,其中有一点就是Binder机制的三个部分:JavaBinder、NativeBinder、KernelBinder,其中JavaBinder和Native

Android Binder原理(七)Java Binder中系统服务的注册过程

Binder原理Android框架层本文首发于微信公众号「后厂技术官」<!more前言在这篇文章中,我介绍的是NativeBinder中的系统服务的注册过程,这一过程的核心是ServiceManager,而在JavaBinder中,也有一个ServiceManager,只不过这个ServiceManager是Java文件。既然要将系统服务注册到Ser

Android Binder原理(四)ServiceManager的启动过程

Binder原理Android框架层本文首发于微信公众号「刘望舒」<!more前言在上一篇文章中,我们以MediaPlayerService为例,讲解了系统服务是如何注册的(addService),既然有注册就势必要有获取,但是在了解获取服务前,我们最好先了解ServiceManager的启动过程,这样更有助于理解系统服务的注册和获取的过程。另外还有一点

Android解析WindowManager(三)Window的添加过程

Android框架层Android系统服务WindowManagercategories:Android框架层本文首发于微信公众号「刘望舒」前言在此前的系列文章中我们学习了WindowManager体系和Window的属性,这一篇我们接着来讲Window的添加过程。建议阅读此篇文章前先阅读本系列的前两篇文章。<!more1.概述WindowMana

Android解析WindowManagerService(一)WMS的诞生

Android框架层Android系统服务WindowManagerServiceAndroid框架层本文首发于微信公众号「后厂技术官」前言此前我用多篇文章介绍了WindowManager,这个系列我们来介绍WindowManager的管理者WMS,首先我们先来学习WMS是如何产生的。本文源码基于Android8.0,与Android7.1.2