--- ServiceManager 的启动和工作原理 --- 1. ServiceManager 启动流程是怎样的? 2. 怎么获取 ServiceManager 的 binder 对象? 3. 怎么向 ServiceManager 添加服务? 4. 怎么从 ServiceManager 获取服务? #### ServiceManager 的启动 1. 启动进程 2. 启用 binder 机制 3. 发布自己的服务 4. 等待并响应请求 ##### 启动进程 ```ini service servicemanager /system/bin/servicemanager clas core user system group system critical //... ``` ```c int main(int argc, char **argv) { struct binder_status *bs; // 1.打开 binder 驱动 bs = binder_open(128*1024); // 2.把自己注册为上下文管理者 binder_become_context_manager(bs); // 3.进入 loop 循环,不断等待请求、处理请求 binder_loop(bs, svcmgr_handler); return 0; } ``` ```c struct binder_status *binder_open(size_t, mapsize) { struct binder_state *bs; bs = malloc(sizeof(*bs)); // 1.打开 binder 驱动,返回一个 fd bs->fd = open("/dev/binder", O_RDWR); bs->mapsize = mapsize; // 2.给 fd 映射一块内存,128 kb bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); return bs; } ``` ```c // 注册成上下文,其实就是告诉 binder 驱动,ServiceManager 已经就绪了 int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MSR, 0); } ``` binder_loop 分为两个阶段,第一阶段主要是注册为 binder 线程: ```c void binder_loop(struct binder_state *bs, binder_handler func) { uint32_t readbuf[32]; // 把当前线程注册为 binder 线程,也就是告诉 binder 驱动,当前线程可以处理 binder 请求的 readbuf[0] = BC_ENTER_LOOPER; binder_write(bs, readbuf, sizeof(uint32_t)); //... } ``` ```c int binder_write(struct binder_state *bs, void *data, size_t len) { // BINDER_WRITE_READ 表示可读可写 // write_size > 0 执行写 // read_size > 0 执行读 // write_size > 0 && read_size > 0,先写再读 struct binder_write_read bwr; bwr.write_size = len; bwr.write_consumed = 0; bwr.write_buffer = (uintptr_t) data; bwr.read_size = 0; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); return res; } ``` 第二阶段,就是读请求处理请求了: ```c void binder_loop(struct binder_state *bs, binder_handler func) { struct binder_write_read bwr; //... bwr.write_size = 0; for(;;) { bwr.read_size = sizeof(readbuf); bwr.read_buffer = (unitptr_t) readbuf; ioctl(bs->fd, BINDER_WRITE_READ, &bwr); // 解析请求,并在回掉函数 func 处理请求 binder_parse(bs, 0, (uintptr_t)readbuf, bwr.read_consumed, func); } } ``` #### 如何获取 ServiceManager? 以 SurfaceFlinger 为例: ```c sp defaultServiceManager() { if(gDefaultServiceManager != null) { return gDefaultServiceManager; } while(gDefaultServiceManager == null) { gDefaultServiceManager = getContextObject(); if(gDefaultServiceManager==null) sleep(1); } } ``` ```c sp ProcessState::getContextObject(...) { // 返回 ServiceManager 的 Proxy 对象,注意 handler 值为 0 return getStrongProxyForHandle(0); } ``` ```c sp ProcessState::getStrongProxyForHandle(int32_t handle) { // 以 binder handle 值作为索引,获取数组里面对应的 handle_entry handle_entry* e = loopupHandleLocked(handle); IBinder* b = e->binder; if(b == NULL) { // ServiceManager 的 Proxy 对象就是 BpBinder(0); b = new BpBinder(handle); e->binder = b; } return b; } ``` #### 怎么向 ServiceManager 添加服务? ```c // 添加服务,Service 名称和 Service Binder 对象 status_t addService(const String16& name, const sp& service, ...) { //... // 通过 remote 函数获取 BpBinder 对象,然后调用 BpBinder 的 transact 函数 remote() -> transact(ADD_SERVICE_TRANSACTION, data, &reply); } ``` ```c status_t BpBinder::transact(unit32_t code, const Parcel& data, Parcel* reply, ...) { // IPCThreadState 线程单例,直接跟 binder 驱动交互 IPCThreadState::self()->transact(mHandle, code, data, ...); } ``` 在 ServiceManager 收到请求之后,如何处理? ```c int svcmgr_handler(..., struct binder_transaction_data *txn, ...) { switch(txn->code) { //... case SVC_MSR_ADD_SERVICE: // 注册到 ServiceManage 的虽然传递的是 binder 实体对象 // 但是真正 ServiceManager 收到的只是一个 handle 值 // ServiceManager 会根据 handle 值还有 binder 相关信息封装成一个数据结构插入到单链表里 do_add_service(bs, s, len, handle, ...); break; } } ``` #### 怎么从 ServiceManager 获取服务? 关于怎么获取服务呢,和注册服务差不多,都需要向 ServiceManager 发起一个 binder 调用。 ```java public static IBinder getService(String name) { IBinder service = sCache.get(name); if(service != null) { return service; }else { // 获取 ServiceManager 的 binder 对象,然后调用它的 getService 函数 return getIServiceManager().getService(name); } return null; } ``` ServiceManager 在收到请求之后,是如何处理的呢? ```c int svcmgr_handler(..., struct binder_transaction_data *txn, ...) { uint32_t handle; switch(txn->code) { case SVC_MGR_GET_SERVICE: // 拿到服务的名称 s = bio_get_string16(msg, &len); // 找到对应服务的 handle 值 handle = do_find_service(bs, s, len, ...); // 返回 handle 值,Client 端再根据 handle 值封装一个 BpBinder 就行了 bio_put_ref(reply, handle); return 0; } } ```