浅析media.player服务如何通过IMediaPlayerService进行binder适配的
最近需要把bootsound加进去,但是需要设计一个playmp3得程序,打算使用cpp完成,
从原理上说只需要下面的几行语句就ok了
sp
mp = new MediaPlayer();
mp->setDataSource(mpath);
mp->prepare();
mp->start();
while (mp->isPlaying()) {
sleep(1);
}
但是发送了7帧数据就退出了,没办法,只能追踪进去找问题了,
如下是meidiaserver的注册和playmp3程序调用流程[luther.gliethttp]
1. mediaserver系统服务进程启动
frameworks/base/media/mediaserver/main_mediaserver.cpp
int main(int argc, char** argv)
{
sp proc(ProcessState::self());
sp sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
AudioFlinger::instantiate();
MediaPlayerService::instantiate(); // 注册"media.player"服务
CameraService::instantiate();
AudioPolicyService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
2. 注册"media.player"服务
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
// 传递new MediaPlayerService()对象地址,这样上面mediaserver进程的
// IPCThreadState::self()->joinThreadPool();函数最后在executeCommand(cmd);的case BR_TRANSACTION:中
// 将直接使用binder IPC过来sp b((BBinder*)tr.cookie);指针地址,强行转换为
// 该new MediaPlayerService()对象地址,然后调用该对象的b->transact(tr.code, buffer, &reply, 0);
// 这样MediaPlayerService类的方法onTransact(code, data, reply, flags);将被BBinder::transact调用
// 于是其他client程序与MediaPlayerService()类通过binder完成了onTransact数据的交流[luther.gliethttp]
}
3. client通过"media.player"服务对应的binder接口类IMediaPlayerService完成与"media.player"服务的binder IPC通信
// establish binder interface to service
const sp& MediaPlayer::getMediaPlayerService()
{
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService.get() == 0) {
sp sm = defaultServiceManager(); // 获取0号绝对manager
sp binder;
do {
binder = sm->getService(String16("media.player")); // 获取与"media.player"服务建立的binder
if (binder != 0)
break;
LOGW("MediaPlayerService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast(binder);
// interface_cast该操作非常重要,他将完成BpMediaPlayerService对象的创建
// BpMediaPlayerService对象将通过binder与"media.player"服务进行通信
// BpMediaPlayerService的方法实现和"media.player"服务程序提供出来的方法一一对应,
// 只不过BpMediaPlayerService是一个"media.player"和client用户之间的适配层,
// client只需要调用BpMediaPlayerService提供的相应接口,BpMediaPlayerService就会通过binder
// 转发给"media.player"服务对应的接口,因此client感觉自己直接调用了
// "media.player"服务提供的function方法函数
// 这种设计太wonderful了[luther.gliethttp]
}
LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?");
return sMediaPlayerService;
}
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
service定义
IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp I##INTERFACE::asInterface( \
const android::sp& obj) \
{ \
android::sp intr; \
if (obj != NULL) { \
intr = static_cast( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
// 我们可以看到使用asInterface(sp *obj)转换时,会创建一个新对象
// 比如我们sMediaPlayerService = interface_cast(binder);
// 那么返回的将是new BpMediaPlayerService(sp *obj);对象
// 所以sMediaPlayerService虽然定义为IMediaPlayerService类型
// static sp sMediaPlayerService;
// 但实际它将指向派生类BpMediaPlayerService生成的对象[luther.gliethttp]
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
阅读(5011) | 评论(1) | 转发(0) |