Android的Binder机制浅析

**
1. 引言** 

一般实际的软件系统中进程间通信(IPC)的实现方法有命名管道(named pipe),共享内存(shared memory),消息队列(message queue),Socket等方法。在Android的框架(Framework)中,以Binder作为框架内进程间(通常如服务和客户间)通信的主要实现手段。这可能是出于效率和软件架构考虑。Binder通信的底层基础是Binder设备,本文通过一些实例简要介绍基于Binder通信的流程,由于整个机制,尤其是驱动和一些数据封装部分相当复杂,本文也仅仅关注了其主体的流程,难免有疏漏和错误。 

2. Binder相关模块及其流程 Binder通信主要涉及以下文件: 
进程状态对象: 
include/utils/ProcessState.h, lib/utils/ProcessState.cpp 
IPC通信机制和状态: 
include/utils/IPCThreadState.h, lib/utils/ProcessState.cpp 
Binder基础类: 
include/utils/Binder.h,(以及一些派生类等) 
(本文不加说明,相对目录均从/frameworks/base出发) 

设备驱动模块: 
Binder驱动模块位于Android根目录下/kernel/drivers/misc/binder.c中。 

2.1 主要模块概览 

图1显示了Framework中模块。其中XXX表示某具体应用。例如对Surface,其接口就是ISurface,本地调用端就是BpSurface,实现端就是BnSurface;对ServiceManager其接口就是IServiceManager,本地调用端就是BpServiceManager,实现端就是BnServiceManager。

clip_image002

图1 IPC-Binder相关对象继承关系

接口IXXX规定了这个应用需要实现的一些方法,例如ISurface中就定义了以下方法:

方法名

说明

registerBuffers

注册Buffer

postBuffer

输送Buffer

unregisterBuffers

注销Buffer

createOverlay

创建叠层

以Surface应用为例,远端实现侧(进程)是一个Surface操作的具体实现。而在另一个具体的进程中只要通过创建和使用BpSurface,就能够调用这个远端进程的功能。 
于是BpXXX,在这里即BpSurface,由于继承了ISurface,必须也实现这些方法。而通常BpXXX是本地调用远端具体实现的入口,因此在这其中通常是启动IPC,传入和传出数据和参数的过程,这其中mRemote(BpBinder对象)是媒介,详见后续讨论。 
而BnXXX,即BnSurface,同样也继承了IServiceManager,也实现这些方法。而BnXXX(或其派生类),必须真正实现这些方法的具体工作,因为它是被BpXXX调用的。

又如SurfaceFlingerClient,其接口ISurfaceFlingerClient定义如下方法:

方法名

说明

getControlBlocks

获得控制块

createSurface

创建一个Surface对象(Bp, Bn侧)

destroySurface

销毁一个Surface对象

setState

设置状态

而媒体播放器服务MediaPlayerService,其接口IMediaPlayerService定义如下方法:

方法名

说明

createMediaRecorer

创建一个媒体录制器(MediaRecorder)

createMetadataRetriever

创建一个元数据读取器(MetadataRetriever)

create

创建一个媒体播放器(MediaPlayer)

decode

解码一个流

同样服务管理模块ServiceManager也是一个基于Binder的应用,接口IServiceManager定义了如下方法:

方法名

说明

getService

获得一个服务

checkService

查询服务

addService

添加一个服务

listServices

列举服务

2.2 Binder初始化
由于Binder的基础是Binder设备,因此设备的启动和配置是首要操作。 
首先一个是Binder处理进程,它是android启动后第一个运行的binder相关程序。以下代码主要在cmds/serviceManager/binder.c中。以下是代码分析片段:

1 1: int main(int argc, char **argv) 2 3 2: { 4 5 3: struct binder_state *bs; 6 7 4: void *svcmgr = BINDER_SERVICE_MANAGER; //一个NULL指针 8 9 5:  10 11 6: bs = binder_open(mapsize = 128*1024) 12 13 7: { 14 15 8:16 17 9: bs->fd = open("/dev/binder", O_RDWR); 18 19 10:20 21 11: bs->mapsize = mapsize; 22 23 12: bs->mapped = mmap(NULL, mpasize, PROT_READ, MAP_PRIVATE, bs->fd, 0); 24 25 13:26 27 14: } 28 29 15:  30 31 16: binder_become_context_manager(bs) 32 33 17: { 34 35 18: // 将本进程在内核中注册为context manager 36 37 19: ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); 38 39 20: } 40 41 21:  42 43 22: svcmgr_handle = svcmgr; 44 45 23: binder_loop(bs, svcmgr_handler) // binder消息分发的关键循环 46 47 24: { 48 49 25:50 51 26: for(;;) { 52 53 27:54 55 28: // 一般阻塞再此,直到有消息送达(阻塞点1),详见激活点1 56 57 29: ioctl(bs->fd, BINDER_WRITE_READ, &bwr) 58 59 30: { 60 61 31:62 63 32: binder_thread_write() {} 64 65 33: binder_thread_read() 66 67 34: { 68 69 35: …激活后,相应处理中会在ptr所指buffer中将cmd设置为 70 71 36: BR_TRANSACTION 72 73 37: } 74 75 38:76 77 39: } 78 79 40: 80 81 41: // 解析消息 82 83 42: binder_parse(bs, bio = 0, ptr=readbuf, size = bwr.read_consumed, 84 85 43: func = svcmgr_handler) 86 87 44: { 88 89 45: while (解析readbuf未完) 90 91 46: { 92 93 47: cmd = *ptr++; 94 95 48: switch(cmd) 96 97 49: { 98 99 50:100 101 51: case BR_TRANSACTION: 102 103 52: func {=svcmgr_handler}(bs, txn, &msg, &reply) 104 105 53: { 106 107 54:108 109 55: switch(txn->code) 110 111 56: { 112 113 57: case SVC_MGR_GET_SERVICE:114 115 58: case SVC_MGR_CHECK_SERVICE:116 117 59:118 119 60: } 120 121 61:122 123 62: } 124 125 63: binder_send_reply(bs, &reply, txn->data, res) 126 127 64: { 128 129 65: data=130 131 66: binder_write(bs, &data, sizeof(data)) 132 133 67: { 134 135 68: ioctl(bs->fd, BINDER_WRITE_READ, &bwr) 136 137 69: } 138 139 70: } 140 141 71: } 142 143 72: } 144 145 73: } 146 147 74: } 148 149 75: } 150 151 76: return 0; 152 153 77: }

2.3 Runtime初始化 

以下的服务进程和2.2介绍的类似,也是实现了ServiceManager的接口功能,只是它是用C++实现的,并且其本身也做成了Binder类型。 
因此,它可能是在上述2.2初始化之后最先加入的服务,而此后它将服务于维护其他服务。同样它也注册成Context Manager,这样在客户侧调用时无需制定具体的对象句柄。 
以下程序位于cmds/runtime/main_runtime.cpp。

1 1: int main() 2 3 2: { 4 5 3:6 7 4: boot_init() 8 9 5: { 10 11 6: proc = ProcessState::self(); 12 13 7: proc->becomeContextManager(contextChecker, NULL) 14 15 8: { 16 17 9:18 19 10: // 本进程变为Context Manager,接受后续的Binder处理 20 21 11: ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy); 22 23 12:24 25 13: } 26 27 14:  28 29 15: sm = new BServiceManager; 30 31 16:  32 33 17: proc->setContextObject(IBinder object = sm) 34 35 18: { 36 37 19: setContextObject(sm, "default") 38 39 20: { 40 41 21: mContexts.add("default", sm) 42 43 22: { 44 45 23: 装入映射表mContexts中… 46 47 24: } 48 49 25: } 50 51 26: } 52 53 27:54 55 28: run() 56 57 29: { 58 59 30:60 61 31: IPCThreadState::self()->joinThreadPool() 62 63 32: { 64 65 33: 等待消息,过程类似2.7中的讨论 66 67 34: } 68 69 35: } 70 71 36: } 72 73 37:74 75 38: }

BServiceManager实现BnServiceManager,由于ServiceManager服务程序作为ContextManager,因此后续在defaultServiceManager()上进行IServiceManager调用(如调用getService())都将定向到这个对象,而BServiceManager则维护了系统中的所有服务。 

2.4 Bp对象的创建
Bp相关类型在framework中通过宏定义实现。这个宏定义在include/utils/IInterface.h中以DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE命名。在相关的类定义中加入,例如在BpSurface这个例子中,它在ISurface.cpp中出现。

1 1: sp BpSurfaceFlingerClient::createSurface(..) 2 3 2: { 4 5 3:6 7 4: data上设置参数 8 9 5: mRemote->transact(CREATE_SURFACE, data, &reply) 10 11 6: { 12 13 7:IPC调用到Bn侧功能并返回 14 15 8: } 16 17 9:18 19 10: sp binder = reply.readStrongBinder() 20 21 11: { 22 23 12: unflatten_binder(proc=ProcessState::self(), *this, sp* out = &val) 24 25 13: { 26 27 14: // 从in中取出flat_binder_object 28 29 15: flat_binder_object *flat = in.readObject(false); 30 31 16: if (flat) 32 33 17: { 34 35 18: switch(flat->type) 36 37 19: { 38 39 20:40 41 21: case BINDER_TYPE_HANDLE: // 本节注释1 42 43 22: *out = proc->getStrongProxyForHandle(flat->handle) 44 45 23: /* ProcessState:: getStrongProxyForHandle() */ 46 47 24: { 48 49 25: // 查表获得一个表项,若首次则创建一个表项 50 51 26: e = lookupHandleLocked(handle); 52 53 27: if (e != NULL) { 54 55 28: IBinder * b = e->binder; 56 57 29: if (b == NULL ||) 58 59 30: { // 初次e->binder为空 60 61 31: e->binder = b = new BpBinder(handle) 62 63 32: { mHandle = handle; } 64 65 33:66 67 34: result = b; 68 69 35: } 70 71 36: } 72 73 37: return result; 74 75 38: } 76 77 39: return finish_unflatten_binder(NULL, *flat, in); 78 79 40: } 80 81 41: } 82 83 42: } 84 85 43: return val; 86 87 44: } 88 89 45: return interface_cast(binder) // 上述宏定义的展开 90 91 46: { 92 93 47: return sp ISurface::asInterface(binder) 94 95 48: { 96 97 49: sp intr; 98 99 50: if (binder != NULL) 100 101 51: { 102 103 52:104 105 53: intr = new BpSurface(binder) 106 107 54: { 108 109 55: 基类创建:BpRefBase(binder) 110 111 56: { 112 113 57: mRemote = binder.get(); // 即刚创建的BpBinder 114 115 58: } 116 117 59: } 118 119 60: } 120 121 61: } 122 123 62: } 124 125 63: }

可见BpSurfaceFlingerClient的作用之一是创建BpSurface对象。两者都在客户端(同一进程中)。 

----- 
【注释1】 在binder_transaction传递(ioctl在BINDER_WRITE_READ的BC_REPLY返回时,详见后续章节)中会将扁平处理的binder信息flat_binder_object中的类型从BINDER_TYPE_BINDER转换为BINDER_TYPE_HANDLE,而具体的handle是从底层对象注册用的红黑树上取出的唯一handle号,这样Bp侧用这个handle号和Bn侧的具体对象对应。

2.5 Bn对象的创建 

而在Bn侧BnSurfaceFlingerClient::onTransact处理上述mRemote->transact的过程:

1 1: BnSurfaceFlingerClient::onTransact() 2 3 2: { 4 5 3:6 7 4: switch(code) { 8 9 5: case CREATE_SURFACE: 10 11 6: 从data上获取参数 12 13 7: sp s = BClient::createSurface() 14 15 8: { 16 17 9:18 19 10: 创建一个Bn侧的ISurface实体对象s 20 21 11: (BnSurface类型,具体如LayerBuffer::SurfaceBuffer) 22 23 12:24 25 13: sBinder = s->IInterface::asBinder() 26 27 14: { 28 29 15: BnInterface::onAsBinder() 30 31 16: { 32 33 17: return this; 34 35 18: } 36 37 19: } 38 39 20: reply->writeStrongBinder(sBinder) 40 41 21: { 42 43 22: flatten_binder(ProcessState::self(), binder= sBinder, out = this = reply) 44 45 23: { 46 47 24: flat_binder_object obj; 48 49 25: obj.flags =50 51 26: if (sBinder!= NULL) 52 53 27: { 54 55 28: local = binder->localBinder() { return this; } 56 57 29: if (!local)58 59 30: else 60 61 31: { 62 63 32: obj.type = BINDER_TYPE_BINDER; 64 65 33: obj.binder = local->getWeakRefs(); 66 67 34: obj.cookie = local; // 这个在后续访问操作使用 68 69 35: } 70 71 36: } 72 73 37: … 其他分支略 74 75 38:  76 77 39: return finish_flatten_binder(sBinder, obj, out) 78 79 40: { 80 81 41: out->writeObject(obj, nullMetaData = false) 82 83 42: { 84 85 43: …将obj数据写到out这个Parcel对象中 86 87 44: } 88 89 45: } 90 91 46: } 92 93 47: } 94 95 48: // 此后reply这个Parcel将通过IPC传回客户端 96 97 49: } 98 99 50:100 101 51: } 102 103 52: }

上述客户端和远端代码基本展示了Surface的创建过程。Bp和Bn侧的Surface创建完成后才有后续Surface的具体运作。 

2.6 BpSurface运作 

以前面提到的ISurface上的postBuffer接口的工作为例。这部分将深一些到IPC 事务(transaction)作业内部。其实前一节的Surface的创建过程已经调用了ISurfaceFlingerClient::createSurface接口,已经走了一遍类似的transaction事务流程,而前一节主要以BpSurface和BnSurface为例介绍在IPC流程的前提——两侧的建立为目的,在这里再对此后的事务操作进行详细介绍。 
从BpSurface出发:

1 1: void BpSurface::postBuffer(offset) 2 3 2: { 4 5 3: data.writeInterfacetoken(ISurface::getInterfaceDescriptor()); // ISurface接口描述符 6 7 4: data.writeInt32(offset); 8 9 5: mRemote->transact(code =POST_BUFFER, data, reply = &reply, 10 11 6: flags = IBinder::FLAG_ONEWAY) // FLAG_ONEWAY=1 12 13 7: (mRemote即刚才建立的BpBinder对象,即BpBinder::transact(..)14 15 8: { 16 17 9:18 19 10: IPCThreadState::self()->transact(handle = mHandle, code, data, reply, flags) 20 21 11: { // handle是对应Bn侧Surface对象的有效值 22 23 12:24 25 13: writeTransactionData(cmd = BC_TRANSACTION, flags, handle, 26 27 14: code, data, NULL) 28 29 15: { 30 31 16: binder_transaction_data tr; 32 33 17: tr.target.handle = handle; 34 35 18: tr.code = code; tr.flags = flags; 36 37 19: ... 38 39 20: mOut.writeInt32(cmd) 40 41 21: mOut.write(&tr, sizeof(tr)); 42 43 22:44 45 23: } 46 47 24:48 49 25: waitForResponse(reply = NULL, acquireResult = NULL) // 不需要返回值 50 51 26: { 52 53 27: while(1) 54 55 28: { 56 57 29: talkWithDriver() 58 59 30: { 60 61 31:62 63 32: ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 64 65 33:66 67 34: } 68 69 35: … 处理返回值 70 71 36: } 72 73 37: } 74 75 38: } 76 77 39:78 79 40: } 80 81 41: }

上述ioctl将调用请求做成通过Binder发送到远端。其过程在后续章节介绍。

2.7 Binder驱动概要
在/kernel/drivers/misc/binder.c的Binder设备驱动中,定义了以下函数,它在内核中处理上述ioctl调用,完成Binder的功能。

1 1: static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 2 3 2: { 4 5 3:6 7 4: // 以下将本函数调用者进程挂起(如上述BpSurface所在进程),直到处理完返回 8 9 5: wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); 10 11 6:  12 13 7: // 进程私有数据 14 15 8: binder_proc proc = filp->private_data; 16 17 9: // 获得调用者进程的线程池数据结构 18 19 10: binder_thread *thread = binder_get_thread(proc); 20 21 11:22 23 12: switch(cmd) 24 25 13: { 26 27 14: case BINDER_WRITE_READ: 28 29 15:30 31 16: // 从用户空间将bind_write_read参数复制到bwr 32 33 17: copy_from_user(&bwr, ubuf, sizeof(bwr); 34 35 18:36 37 19: binder_thread_write(proc, thread, bwr.write_buffer, bwr.write_size, 38 39 20: bwr.write_consumed) 40 41 21: { 42 43 22: while (处理bwr.write_buffer未完成) 44 45 23: { 46 47 24: // 从用户空间获取cmd数据到内核空间 48 49 25: get_user(cmd, (uint32_t __user *)ptr); 50 51 26:52 53 27: switch(cmd) 54 55 28: { 56 57 29:58 59 30: case BC_TRANSACTION: case BC_REPLY: 60 61 31: // 从用户空间得到binder_transaction_data数据 62 63 32: copy_from_user(&tr, ptr, sizeof(tr)); 64 65 33:66 67 34: binder_transaction(proc, thread, tr=&tr, 68 69 35: reply=(cmd==BC_REPLY)=false) 70 71 36: { 72 73 37:74 75 38: if (reply) 76 77 39: { // 是回复 78 79 40:80 81 41: } 82 83 42: else 84 85 43: { // 是正向请求 86 87 44: if (tr->target.handle) 88 89 45: { // 从红黑树中获得对应的节点 90 91 46: ref = binder_get_ref(proc, tr->target.handle); 92 93 47:94 95 48: target_node = ref->node; 96 97 49: } 98 99 50: else100 101 51: // 找到节点对应的服务进程 102 103 52: target_proc = target_node->proc; 104 105 53:106 107 54: } 108 109 55: if (target_thread)110 111 56: else 112 113 57: { 114 115 58: target_list = &target_proc->todo; 116 117 59: target_wait = &target_proc->wait; 118 119 60: } 120 121 61:122 123 62: for(遍历其中的flat objects) 124 125 63: { 126 127 64: …在postBuffer这个例子中忽略 128 129 65: …在createSurface中它将消息内含flat object进行处理 130 131 66: … 以实现两侧物件BINDERHANDLE类型转换, 132 133 67: … 即完成2.4的注释1中的过程: 134 135 68: switch(fp->type) 136 137 69: { 138 139 70:140 141 71: case BINDER_TYPE_BINDER: 142 143 72:144 145 73: node=binder_new_node(proc, 146 147 74: ptr = fp->binder, cookie = fp->cookie) 148 149 75: { 150 151 76:152 153 77: node->proc = proc; 154 155 78: // 这个进程就是BnSurfaceFlingerClient和 156 157 79: // BnSurface所在进程 158 159 80: node->ptr = ptr; 160 161 81: node->cookie = cookie; 162 163 82:164 165 83: } 166 167 84:  168 169 85:170 171 86: binder_get_ref_for_node(target_proc, node); 172 173 87:174 175 88: fp->type = BINDER_TYPE_HANDLE; 176 177 89:178 179 90: } 180 181 91: } 182 183 92:184 185 93: // 激活点1: 186 187 94: // 唤醒进程(见“阻塞点2”) 188 189 95: // (对于在ServiceManager阶段会激活service_manager的“阻塞点1”) 190 191 96: wake_up_interruptible (target_wait); 192 193 97: } // binder_transaction 194 195 98: } 196 197 99: } // binder_thread_write 198 199 100:200 201 101: binder_thread_read() 202 203 102: { 204 205 103: … 读取数据 206 207 104: … 处理 208 209 105: if (t->buffer->target_node) { 210 211 106: 212 213 107: tr.target.ptr = target_node->ptr; 214 215 108: tr.cookie = target_node->cookie; //本地对象指针 216 217 109: … 相应处理中会在ptr所指buffer中将cmd设置为 218 219 110: BR_TRANSACTION 220 221 111: } 222 223 112: } 224 225 113: if (读得数据) 226 227 114: wake_up_interruptible(&proc->wait); //激活等数据的用户进程 228 229 115: } 230 231 116:232 233 117: // 反馈给用户空间 234 235 118: copy_to_usr(ubuf, &bwr, sizeof(bwr)); 236 237 119: } 238 239 120: }

2.8 IPC处理和监听线程 

以下Surface相关服务的进程入口(cmds/surfaceflinger/main_surfaceflinger.cpp):

1 1: int main() 2 3 2: { 4 5 3:6 7 4: SurfaceFlinger::instantiate() 8 9 5: { /* 实例化SurfaceFlinger服务 */ 10 11 6: sm = defaultServiceManager() 12 13 7: { 14 15 8: if (gDefaultServiceManager != NULL) return gDefaultServiceManager; 16 17 9:18 19 10: // 在当前进程中首次调用 20 21 11: 22 23 12: co = ProcessState::self()->getContextObject(NULL) 24 25 13: { 26 27 14: if (supportsProcess()) { /* Android支持此分支 */ 28 29 15: return getStrongProxyForHandle(0) 30 31 16: { 32 33 17: 具体流程类似2.4节介绍,生成一个新的BpBinder对象 34 35 18: (ServiceManager的实际对象作为Context,功能实体在启 36 37 19: 动时已经产生,即2.3介绍的BServiceManager,所以此 38 39 20: 处不在需要生成Bn对象) 40 41 21: } 42 43 22: } else44 45 23: } 46 47 24: gDefaultServiceManager = interaface_cast(co) 48 49 25: { 50 51 26: …具体流程类似2.4节介绍,新建一个BpServiceManager对象 52 53 27: 上述BpBinder对象作为其mRemote 54 55 28: } 56 57 29: return gDefaultServiceManager; 58 59 30: } 60 61 31: sm->addService() 62 63 32: { 64 65 33: 远程调用,完成服务(SurfaceFlinger)的加载 66 67 34: } 68 69 35: } 70 71 36: 72 73 37: … 其他服务创建 … 74 75 38: ProcessState::self()->startThreadPool() 76 77 39: { 78 79 40:80 81 41: spawnPoolThread(true) 82 83 42: { 84 85 43: 创建线程运行IPCThreadState::self()->joinThreadPool(true) 86 87 44: } 88 89 45: } 90 91 46:  92 93 47: IPCThreadState::self()->joinThreadPool() 94 95 48: { 96 97 49:98 99 50: do { 100 101 51: …处理输入信息 102 103 52: talkWithDriver() 104 105 53: { 106 107 54: 通过ioctl和binder设备交换信息(见前几节介绍), 108 109 55: 数据未到时挂起(阻塞点2110 111 56: } 112 113 57:114 115 58: cmd = mIn.readInt32(); 116 117 59: executeCommand(cmd) 118 119 60: { 120 121 61: switch(cmd) 122 123 62: { 124 125 63:126 127 64: case BR_TRANSACTION: 128 129 65: binder_transaction_data tr; 130 131 66: mIn.Read(&tr, sizeof(tr)); 132 133 67:134 135 68: if (tr.target.ptr) 136 137 69: { 138 139 70: sp b = ((BBinder*)tr.cookie; // 本地对象指针 140 141 71: b->transact(tr.code, buffer, &reply, 0) 142 143 72: { 144 145 73: BnSurface:: onTransact() 146 147 74: { 148 149 75: switch(code) 150 151 76: { 152 153 77:154 155 78: case POST_BUFFER: 156 157 79:158 159 80: offset = data.readInt32(); 160 161 81: postBuffer(offset); 162 163 82:164 165 83: } 166 167 84:168 169 85: } 170 171 86: } 172 173 87: } 174 175 88:176 177 89: } 178 179 90: } 180 181 91: } while (未完结); 182 183 92:184 185 93: } 186 187 94: }

以下是媒体相关服务进程入口:

1 1: int main() 2 3 2: { 4 5 3:6 7 4: MediaPlayerService::instantiate() { 见上一段代码 } 8 9 5: … 其他服务创建 … 10 11 6: ProcessState::self()->startThreadPool() { 见上一段代码 } 12 13 7: IPCThreadState::self()->joinThreadPool() { 见上一段代码 } 14 15 8: }

2.9 Surface总体流程 

根据上述的Bp和Bn两侧生成过程原理分析SurfaceFlinger相关代码,可以发现: 
通过ISurfaceFlinger::createConnection,两侧生成ISurfaceFlingerClient; 
通过ISurfaceFlingerClient:: createSurface,两侧生成ISurface。 
而服务SurfaceFlinger的Bp端最初通过获取服务取得,如下:

1 1: _get_surface_manager() 2 3 2: { 4 5 3: if (gSurfaceManager != 0) return gSurfaceManager; 6 7 4:  8 9 5: sm = defaultServiceManager() { 详见2.8} 10 11 6:  12 13 7:14 15 8: // 获得SurfaceFlinger服务(Bp侧句柄),其原理前面章节(如2.3节) 16 17 9: binder = sm->getService(String16("SurfaceFlinger")); 18 19 10:20 21 11:  22 23 12: // 实际产生 24 25 13: sp sc = interface_cast (binder) 26 27 14: { 详见2.4节,sc实为BpSurfaceComposer } 28 29 15:  30 31 16: if (gSurfaceManager == 0) gSurfaceManager = sc; 32 33 17:  34 35 18: return gSurfaceManager; 36 37 19: }

加上前述Surface的分析,Surface的总体服务流程如图2所示,这些操作使得最终在客户应用中得到BpSurfaceComposer, BpSurfaceFlingerClient和BpSurface三个对象。而发起这些创建的是客户就是SurfaceFlingerClient,它在SurfaceSession(Java对象)中维护,可见SurfaceSession是创建Surface的关键对象。

clip_image002[7] 

**
2.10 MediaPlayerService服务总流程**

1 1: android_media_MediaPlayer_setDataSource() /* JNI */ 2 3 2: { 4 5 3: sp mp = getMediaPlayer() 6 7 4: { 8 9 5: 获得Java对象中引用的MediaPlayer对象, 10 11 6: 它曾在android_media_MediaPlayer_native_setup中设置 12 13 7: 即一个新建的MediaPlayer对象。 14 15 8: 虽然它是BnMediaPlayer,但是接下来调用setDataSource将它绑定到一个远端 16 17 9: 的MediaPlayer上 18 19 10: } 20 21 11: MediaPlayer::setDataSource(url) 22 23 12: { 24 25 13:26 27 14: sp &service = MediaPlayer::getMediaPlayerService() 28 29 15: { 30 31 16: sp sm = defaultServiceManager() {} 32 33 17:34 35 18: binder = sm->getService("media.player") {} 36 37 19:38 39 20: sMediaPlayerService = interface_cast(binder) 40 41 21: { … 得到一个BpMediaPlayerService } 42 43 22:44 45 23: return sMediaPlayerService; 46 47 24: } 48 49 25:50 51 26: // 通过BpMediaPlayerService远程调用创建一个播放器 52 53 27: sp player = service->create() {} 54 55 28: setDataSource(player) 56 57 29: { 58 59 30:60 61 31: mPlayer = player; // 远端的实际功能播放器 62 63 32:64 65 33: } 66 67 34:68 69 35: } 70 71 36: }

参考资料: http://hi.baidu.com/albertchen521/blog/item/30c32d3f4bee993a71cf6ca0.html 
http://www.limodev.cn/blog/archives/777

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )