Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15529655
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2010-09-30 11:56:26

浅析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;                                                    \
    }                                                                   \

阅读(5029) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-09-30 15:38:49

昨天看了有关bootanimation.cpp,但是看得不是很懂,能否讲解以下在此处opengles的实现问题,我自己移植上去一个显示三角的代码 无法执行 请求讲解下代码的执行顺序