Android源码分析:ServiceManager启动代码解析
之前已经分析过获取ServiceManager了,不过那是在使用端,在分析使用ServiceManager去获取服务或者添加服务的时候发现,我使用的Android Studio for Platform默认没有把ServiceManager的源码导入。并且同时我们不知道ServiceManager的服务端是怎么启动,怎么响应的,因此决定还是需要分析一下这块的代码。 首先简单画了一下启动的流程,如下图所示(Entry表示我们的调用入口,也就是后面所说的main函数): sequenceDiagram autonumber Entry->>+ProcessState: initWithDriver ProcessState->>ProcessState: init ProcessState-->>-Entry: return ProcessState Entry->>ServiceManager: new Entry->>ServiceManager: addService(this) Entry ->>IPCThreadState: setTheContentObject Entry->>ProcessState: becomeContextManager Entry->>Looper:prepare Entry ->>Looper:addFd loop 永不退出 Entry ->>Looper:pollAll endServiceManager的启动是在系统启动的时候进行启动的,它的启动是使用Linux系统的服务启动方式进行配置,配置文件在servicemanager.rc当中,配置如下: service servicemanager /system/bin/servicemanager class core animation user system group system readproc critical onrestart restart apexd ... task_profiles ServiceCapacityLow shutdown critical 具体系统如何调用这个Service的我们这里不必关心,我们可以直接来看ServiceManager启动相关的代码,代码在frameworks/native/cmds/servicemanager目录下面。启动的逻辑在main.cpp的main方法中,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int main(int argc, char** argv) { ... const char* driver = argc == 2 ? argv[1] : "/dev/binder"; sp<ProcessState> ps = ProcessState::initWithDriver(driver); ps->setThreadPoolMaxThreadCount(0); //设置最大线程数,因为serviceManager不使用`startThreadPool`启动线程池,因此设置为0 ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>()); if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { LOG(ERROR) << "Could not self register servicemanager"; } IPCThreadState::self()->setTheContextObject(manager); ps->becomeContextManager(); sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/); BinderCallback::setupTo(looper); ClientCallbackCallback::setupTo(looper, manager); while(true) { looper->pollAll(-1); } // 应该不会走到,除非发生了错误 return EXIT_FAILURE; } 代码如上,数量不多,并且其中看到了不少熟悉的类名,首先是使用ProcessState类去调用它的initWithDriver,这里最终也会走到init方法,做的事情也是创建ProcessState实例,并且打开Binder驱动,获取驱动的FD,可以参考前面的文章。 第7行代码,我们可以看到,创建了一个ServiceManager对象,这个对象与我们之前分析的ServiceManager是不同的,它是ServiceManager的Binder服务端,这个代码也跟我们的初始化代码在同一个目录。拿到这个manager后面做的第一件事情就是调用addService把自己也加进去,addService的代码后面再来分析。 再看12行代码,setTheContextObject处传入了manager,这里IPCThreadState初始化代码之前也已经分析过,此处略过,这个方法也只是把manager作为它的成员放入,暂时略过,直接看后面的becomeContextManager源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 bool ProcessState::becomeContextManager() { AutoMutex _l(mLock); flat_binder_object obj { .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX, }; //与Binder交互,发送命令BINDER_SET_CONTEXT_MGR_EXT,让当前进程成为Binder的上下文管理者 int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj); if (result != 0) { android_errorWriteLog(0x534e4554, "121035042"); int unused = 0; // 执行失败,则重置该参数 result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused); } ... return result == 0; } 上面的代码就是告诉binder驱动,当前的进程要成为binder的上下文管理者,驱动内部作何处理我们便不再深究。 继续看我们前面的代码,就出现了熟悉的Looper,这个Java层的Looper用法和功能都一样,preapre之后又在死循环中调用pollAll,从而我们的代码就会永远在这里执行而不会退出。但是Looper在这里有什么用处,我们需要看看前面的代码。首先是15行的调用,其源码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 static sp<BinderCallback> setupTo(const sp<Looper>& looper) { sp<BinderCallback> cb = sp<BinderCallback>::make(); int binder_fd = -1; IPCThreadState::self()->setupPolling(&binder_fd); int ret = looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr /*data*/); return cb; } 第5行代码调用的setupPolling代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 status_t IPCThreadState::setupPolling(int* fd) { if (mProcess->mDriverFD < 0) { //当前驱动没有成功打开时候,直接返回报错 return -EBADF; } mOut.writeInt32(BC_ENTER_LOOPER); //写入Binder调用命令 flushCommands(); *fd = mProcess->mDriverFD; //保存Binder驱动的文件描述符到fd当中 return 0; } void IPCThreadState::flushCommands() { if (mProcess->mDriverFD < 0) return; talkWithDriver(false); //与驱动进行交互 if (mOut.dataSize() > 0) { //二次确认,未成功则继续交互 talkWithDriver(false); } } 可以看到上面的代码主要是与Binder驱动交互,并且执行命令进入Binder的循环,且拿到binder驱动的文件描述符,其中talkWithDriver为与binder交互的具体流程,后续在介绍其代码。 拿到binder驱动的文件描述符后执行Looper的addFd方法,最终执行的方法代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 //Looper.cpp int Looper::addFd(int fd, int ident, int events, const sp<LooperCallback>& callback, void* data) { ... { // 此代码段上锁 AutoMutex _l(mLock); if (mNextRequestSeq == WAKE_EVENT_FD_SEQ) mNextRequestSeq++; const SequenceNumber seq = mNextRequestSeq++; Request request; request.fd = fd; request.ident = ident; request.events = events; request.callback = callback; request.data = data; epoll_event eventItem = createEpollEvent(request.getEpollEvents(), seq); auto seq_it = mSequenceNumberByFd.find(fd); if (seq_it == mSequenceNumberByFd.end()) { //列表中不存在该fd int epollResult = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem); if (epollResult < 0) { ... return -1; } mRequests.emplace(seq, request); mSequenceNumberByFd.emplace(fd, seq); } else { int epollResul
以上内容来自博客订阅源,版权归原作者。关注作者后可以在 关注列表 第一时间查看作者文章。

登录后,加入这场讨论。
登录参与