Android深入浅出之Binder机制
2012-06-30 10:47:32 来源:WEB开发网核心提示:voidIPCThreadState::joinThreadPool(bool isMain){mOut.writeInt32(isMain ? BC_ENTER_LOOPER :BC_REGISTER_LOOPER);status_t result;do {int32_t cmd;result = talkWithD
voidIPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER :BC_REGISTER_LOOPER);
status_t result;
do {
int32_t cmd;
result = talkWithDriver();
result = executeCommand(cmd);
}
} while (result != -ECONNREFUSED&& result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
看到没?有loop了,但是好像是有两个线程都执行了这个啊!这里有两个消息循环?
下面看看executeCommand
status_tIPCThreadState::executeCommand(int32_t cmd)
{
BBinder*obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
caseBR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr,sizeof(tr));
//来了一个命令,解析成BR_TRANSACTION,然后读取后续的信息
Parcel reply;
if (tr.target.ptr) {
//这里用的是BBinder。
sp<BBinder>b((BBinder*)tr.cookie);
const status_t error =b->transact(tr.code, buffer, &reply, 0);
}
让我们看看BBinder的transact函数干嘛了
status_tBBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
就是调用自己的onTransact函数嘛
err= onTransact(code, data, reply, flags);
return err;
}
BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数
终于水落石出了,让我们看看BnMediaPlayerServcice的onTransact函数。
status_tBnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
//BnMediaPlayerService从BBinder和IMediaPlayerService派生,所有IMediaPlayerService
//看到下面的switch没?所有IMediaPlayerService提供的函数都通过命令类型来区分
//
switch(code) {
case CREATE_URL: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
create是一个虚函数,由MediaPlayerService来实现!!
sp<IMediaPlayer> player = create(
pid, client, url,numHeaders > 0 ? &headers : NULL);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
其实,到这里,我们就明白了。BnXXX的onTransact函数收取命令,然后派发到派生类的函数,由他们完成实际的工作。
说明:
这里有点特殊,startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。为什么要这么做呢?他们参数isMain都是true。不知道google搞什么。难道是怕一个线程工作量太多,所以搞两个线程来工作?这种解释应该也是合理的。
网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?这个...管它的,反正知道有两个线程在那处理就行了。
四 MediaPlayerClient
这节讲讲MediaPlayerClient怎么和MediaPlayerService交互。
使用MediaPlayerService的时候,先要创建它的BpMediaPlayerService。我们看看一个例子
IMediaDeathNotifier::getMediaPlayerService()
{
sp<IServiceManager> sm =defaultServiceManager();
sp<IBinder> binder;
do {
//向SM查询对应服务的信息,返回binder
binder =sm->getService(String16("media.player"));
if (binder != 0) {
break;
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER :BC_REGISTER_LOOPER);
status_t result;
do {
int32_t cmd;
result = talkWithDriver();
result = executeCommand(cmd);
}
} while (result != -ECONNREFUSED&& result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
看到没?有loop了,但是好像是有两个线程都执行了这个啊!这里有两个消息循环?
下面看看executeCommand
status_tIPCThreadState::executeCommand(int32_t cmd)
{
BBinder*obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
caseBR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr,sizeof(tr));
//来了一个命令,解析成BR_TRANSACTION,然后读取后续的信息
Parcel reply;
if (tr.target.ptr) {
//这里用的是BBinder。
sp<BBinder>b((BBinder*)tr.cookie);
const status_t error =b->transact(tr.code, buffer, &reply, 0);
}
让我们看看BBinder的transact函数干嘛了
status_tBBinder::transact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
就是调用自己的onTransact函数嘛
err= onTransact(code, data, reply, flags);
return err;
}
BnMediaPlayerService从BBinder派生,所以会调用到它的onTransact函数
终于水落石出了,让我们看看BnMediaPlayerServcice的onTransact函数。
status_tBnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{
//BnMediaPlayerService从BBinder和IMediaPlayerService派生,所有IMediaPlayerService
//看到下面的switch没?所有IMediaPlayerService提供的函数都通过命令类型来区分
//
switch(code) {
case CREATE_URL: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
create是一个虚函数,由MediaPlayerService来实现!!
sp<IMediaPlayer> player = create(
pid, client, url,numHeaders > 0 ? &headers : NULL);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
其实,到这里,我们就明白了。BnXXX的onTransact函数收取命令,然后派发到派生类的函数,由他们完成实际的工作。
说明:
这里有点特殊,startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。为什么要这么做呢?他们参数isMain都是true。不知道google搞什么。难道是怕一个线程工作量太多,所以搞两个线程来工作?这种解释应该也是合理的。
网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?这个...管它的,反正知道有两个线程在那处理就行了。
四 MediaPlayerClient
这节讲讲MediaPlayerClient怎么和MediaPlayerService交互。
使用MediaPlayerService的时候,先要创建它的BpMediaPlayerService。我们看看一个例子
IMediaDeathNotifier::getMediaPlayerService()
{
sp<IServiceManager> sm =defaultServiceManager();
sp<IBinder> binder;
do {
//向SM查询对应服务的信息,返回binder
binder =sm->getService(String16("media.player"));
if (binder != 0) {
break;
更多精彩
赞助商链接