MediaPlayer(三)--C++ binder框架

在看这篇文章前,建议先阅读
C++ Binder机制学习(转载)
只是介绍c++层binder通讯的使用流程,并未涉及binder原理机制

结构框架

上一篇文章MediaPlayer--MediaPlayer基本框架没有将C++的mediaplayer binder通讯展开,这篇文章主要展开这一部分。
大概画了下C++ MediaPlayer的uml图,不是很满意,请高手指教

10190436-c2f82e58f48d0e39.png
MediaPlayerBinder.png

这里面主要的client和service实现类是以下两个文件(Android8.1 路径)
frameworks/av/media/libmedia/mediaplayer.cpp
frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

这里面涉及了三对IPC的通讯,即
IMediaPlayerClient
IMediaPlayerService
IMediaPlayer

其中 IMediaPlayerService , IMediaPlayer 的服务端在MediaPlayerService.cpp, 客户端在mediaplayer.cpp。IMediaPlayerClient 的服务端在mediaplayer.cpp, 客户端在MediaPlayerService.cpp, 这是MediaPlayerService回调mediaplayer使用的。 IMediaPlayerService会创建IMediaPlayer的实例

流程

MediaPlayer 同MediaPlayerService通讯 是通过变量 sp<IMediaPlayer> mPlayer, mPlayer赋值是在setDataSource

status_t MediaPlayer::setDataSource(
        const sp<IMediaHTTPService> &httpService,
        const char *url, const KeyedVector<String8, String8> *headers)
{
    ALOGV("setDataSource(%s)", url);
    status_t err = BAD_VALUE;
    if (url != NULL) {
        const sp<IMediaPlayerService> service(getMediaPlayerService());
        if (service != 0) {
            sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
            if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
                (NO_ERROR != player->setDataSource(httpService, url, headers))) {
                player.clear();
            }
            err = attachNewPlayer(player);
        }
    }
    return err;
}

关于创建mPlayer这块主要分3步:
1 const sp<IMediaPlayerService> service(getMediaPlayerService()); 这一步其实是获取了BpMediaPlayerService
2 sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); 这一步是通过BpMediaPlayerService 的create方法返回了BpMediaPlayer
3 attachNewPlayer 将player赋值给mPlayer
看一下 1 和 2 的两个函数的实现

/*static*/const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
    ALOGV("getMediaPlayerService");
    Mutex::Autolock _l(sServiceLock);
    if (sMediaPlayerService == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16("media.player"));
            if (binder != 0) {
                break;
            }
            ALOGW("Media player service not published, waiting...");
            usleep(500000); // 0.5 s
        } while (true);

        if (sDeathNotifier == NULL) {
            sDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(sDeathNotifier);
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    }
    ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    return sMediaPlayerService;
}

这里简单讲一下
1 sp<IServiceManager> sm = defaultServiceManager(); 获取到ServiceManager
2 sm->getService(String16("media.player")); 通过ServiceManager获取到 MediaPlayerService,MediaPlayerService在android初始化时就向ServiceManager注册了
3 interface_cast<IMediaPlayerService>(binder); 这里实际是new BpMediaPlayerService(binder)

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
    virtual sp<IMediaPlayer> create(
            const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(client));
        data.writeInt32(audioSessionId);

        remote()->transact(CREATE, data, &reply);
        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
    }

create方法做了两件事
1 remote()->transact(CREATE, data, &reply) 通过 IMediaPlayerService binder通讯,将IMediaPlayerClient的IBinder传给了MediaPlayerService, MediaPlayerServcie后面可以通过IMediaPlayerClient 回调MediaPlayer
2 interface_cast<IMediaPlayer>(reply.readStrongBinder()); 上一步binder通讯MeidaPlayer的binder对象, 同过binder是创建了 BpMediaPlayer 实例

Binder可分为实名binder和匿名binder, 实名binder是在ServiceManager注册的servce,可以通过ServiceManager的getService获取,而匿名binder没在ServiceManager中注册,没法通过ServiceManager获取,需要想办法获取service的binder实例才能通讯。对于MediaPlayer的结构,MediaPlayerServcie 属于实名binder, IMediaPlayer 和 IMediaPlayerClient 属于匿名binder。MediaPlayer 通过 MediaPlayerServcie实名binder, 将IMediaPlayerClient binder 传递给MediaPlayerServcie,同时MediaPlayerServcie将IMediaPlayer binder返回MediaPlayer。 这样MediaPlayer 就能通过 IMediaPlayer 调用 MediaPlayerServcie::client接口, MediaPlayerServcie可以通过IMediaPlayerClient调用MediaPlayer接口


10190436-6695e2e3e80f49dc.png
MediaPlayerBinderSeque.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值