Binder_Native:MediaPlayerService和它的Client(针对getService流程)
2016-07-15 15:25
447 查看
MediaPlayerService和它的Client
因为service_manager并不是从BnServiceManager中派生的,因此数据是如何从通信层到业务层传递的,在以上实例中并没有分析,接下来,以MediaPlayerService和它的Client作为分析对象,继续分析
一个Client想要得到某个service的信息,需要先和service_manager通信,调用getService获取service信息。
(实际上这是对于一般常见的非匿名service才采用的策略,对于匿名service是不需要获取服务的)
@1 这里以getMediaPlayerService()为基础,代码如下所示:
@@1.2 如果要使用返回的BpMediaPlayerService获取业务函数,均需要把请求数据打包发送给binder驱动,并且由BpBinder中的handle值找到对应的处理者来处理,处理过程:通信层收到请求,递交给业务层处理。MediaPlayerService中有2个线程在talkWithDriver,假设其中一个线程收到请求消息,会通过之前的executeCommand调用来处理该请求,代码实现如下所示:
图4 MeidaPlayerService家谱
@2 BnMediaPlayerService实现了onTransact函数,它根据code调用对应业务逻辑方法。
业务逻辑由MediaPlayerService来实现的,BnMediaPlayerService是继承BBinder的,因此,调用BnMediaPlayerService的transact方法,实际上就是调用BBinder的transact方法BBinder的传输代码分析如下所示:
这里的onTransact方法实际上是调用子类的,分析BnMediaPlayerService的关键方法onTransact,实现如下所示:
因为service_manager并不是从BnServiceManager中派生的,因此数据是如何从通信层到业务层传递的,在以上实例中并没有分析,接下来,以MediaPlayerService和它的Client作为分析对象,继续分析
一个Client想要得到某个service的信息,需要先和service_manager通信,调用getService获取service信息。
(实际上这是对于一般常见的非匿名service才采用的策略,对于匿名service是不需要获取服务的)
@1 这里以getMediaPlayerService()为基础,代码如下所示:
const sp<IMediaPlayerService>& IMediaDeathNotifier::getMediaPlayerService() { Mutex::Autolock _l(sServiceLock); if (sMediaPlayerService == 0) { sp<IServiceManager> sm = defaultServiceManager(); //获取一个BpServiceManager对象 sp<IBinder> binder; do { binder = sm->getService(String16("media.player"));//查询服务,获取一个BpBinder对象与handle if (binder != 0) { break; } usleep(500000); // 0.5 s,如果ServiceManager上还没有注册的服务,则需要等待,直到对应服务注册 } while (true); if (sDeathNotifier == NULL) { sDeathNotifier = new DeathNotifier(); } binder->linkToDeath(sDeathNotifier); /* 通过binder对象获取一个BpMediaPlayerService对象 */ sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); } //有了BpMediaPlayerService对象,就可以使用其提供的业务逻辑函数,如creatMediaRecorder等 return sMediaPlayerService; }@@1.1 获取binder对象的流程。这里,通过getService获取binder对象,代码实现如下所示:
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; ALOGI("Waiting for service %s...\n", String8(name).string()); sleep(1); } return NULL; }这里通过checkService来获取binder对象,代码实现如下所示:
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(); }这里BpServiceManager发送请求,自后通过reply来获取binder对象。
@@1.2 如果要使用返回的BpMediaPlayerService获取业务函数,均需要把请求数据打包发送给binder驱动,并且由BpBinder中的handle值找到对应的处理者来处理,处理过程:通信层收到请求,递交给业务层处理。MediaPlayerService中有2个线程在talkWithDriver,假设其中一个线程收到请求消息,会通过之前的executeCommand调用来处理该请求,代码实现如下所示:
status_t IPCThreadState::executeCommand(int32_t cmd) { BBinder* obj; ... switch (cmd) { case BR_ERROR: ... case BR_TRANSACTION: { binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr)); ALOG_ASSERT(result == NO_ERROR,"Not enough command data for brTRANSACTION"); if (result != NO_ERROR) break; Parcel buffer; buffer.ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t), freeBuffer, this); const pid_t origPid = mCallingPid; const uid_t origUid = mCallingUid; mCallingPid = tr.sender_pid; mCallingUid = tr.sender_euid; int curPrio = getpriority(PRIO_PROCESS, mMyThreadId); if (gDisableBackgroundScheduling) { if (curPrio > ANDROID_PRIORITY_NORMAL) { setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL); } } else { if (curPrio >= ANDROID_PRIORITY_BACKGROUND) { set_sched_policy(mMyThreadId, SP_BACKGROUND); } } Parcel reply; if (tr.target.ptr) { /* BnServiceXXX从BBiner派生,这里的b是实现BnServiceXXX的对象,即直接定位业务层对象 */ sp<BBinder> b((BBinder*)tr.cookie); const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); if (error < NO_ERROR) reply.setError(error); } else { /* the_context_object是IPCThreadState中的一个全局变量, 可以通过setTheContextObject函数来设置 */ const status_t error = the_context_object->transact (tr.code, buffer, &reply, tr.flags); if (error < NO_ERROR) reply.setError(error); } if ((tr.flags & TF_ONE_WAY) == 0) { sendReply(reply, 0); } mCallingPid = origPid; mCallingUid = origUid; } break; ... return result; }BBinder与业务层之间的关系,如下图所示:
图4 MeidaPlayerService家谱
@2 BnMediaPlayerService实现了onTransact函数,它根据code调用对应业务逻辑方法。
业务逻辑由MediaPlayerService来实现的,BnMediaPlayerService是继承BBinder的,因此,调用BnMediaPlayerService的transact方法,实际上就是调用BBinder的transact方法BBinder的传输代码分析如下所示:
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { data.setDataPosition(0); status_t err = NO_ERROR; switch (code) { case PING_TRANSACTION: reply->writeInt32(pingBinder()); break; default: /* 调用子类的onTransact,这是一个虚函数 */ err = onTransact(code, data, reply, flags); break; } if (reply != NULL) { reply->setDataPosition(0); } return err; }
这里的onTransact方法实际上是调用子类的,分析BnMediaPlayerService的关键方法onTransact,实现如下所示:
status_t BnMediaPlayerService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case CREATE: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaPlayerClient> client=interface_cast<IMediaPlayerClient>(data.readStrongBinder()); int audioSessionId = data.readInt32(); sp<IMediaPlayer> player = create(client, audioSessionId); reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break; ... case CREATE_MEDIA_RECORDER: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaRecorder> recorder = createMediaRecorder(); reply->writeStrongBinder(recorder->asBinder()); return NO_ERROR; } break; case CREATE_METADATA_RETRIEVER: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaMetadataRetriever> retriever = createMetadataRetriever(); reply->writeStrongBinder(retriever->asBinder()); return NO_ERROR; } break; ... default: /* 如果是子类的请求,则走这条分支 */ return BBinder::onTransact(code, data, reply, flags); } }
相关文章推荐
- Iphone手机各屏幕尺寸
- c++动态加载
- C/C++ 笔试、面试题目大汇总
- AbstractQueuedSynchronizer(十三)——应用之Futures
- “\”与“/”斜杠与反斜杠的区别
- CSS3 选择器
- 简单的表单布局
- 利用ant 和 Junit 生成测试报告
- spring源码分析之spring-core-env
- 深入理解计算机系统chapter5
- jquery.ajaxfileupload.js
- 李洪强iOS开发之XMPP
- java基础数据类型(你还记得几个)
- Android的后台任务IntentService
- 移动客户端开发快速上手ReactNative的学习路线
- NSScanner类的使用
- 归并-插入混合排序算法
- ajax 提交数组 泛型集合(二)
- 原码, 反码, 补码 详解
- opencv—显示图像