您的位置:首页 > 其它

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()为基础,代码如下所示:
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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: