本例主要分析一下JNI 調用之後的libmedia and libmediaplayerservice, mediaplayer.cpp 中定義了playback 相關的c++ API, 可以使用這些接口編寫一些framework 級別的player 應用,當然似乎沒人這麼幹; mediaplayerservice 作爲mediaserver 的主要service 之一,在media playback 中起着至關重要的作用,其管理着衆多Player,同樣我們可以在mediaplayerservice 中添加我們自己的player.
mediaserver 作爲一個單獨的進程而存在,mediaplayer 又是透過怎樣的方式來獲取mediaplayerservice的服務,mediaplayerservice又是怎樣回饋信息給mediaplayer的呢?在此就不得不說binder , 非常強大的工具,站在巨人的肩膀上,使我們能夠看得更遠,以下我們將抽絲剝繭,理清楚對於BpBinder, BnBinder 的構建;
- mediaplayer 繼承自 BnMediaPlayerClient and IMediaDeathNotifier, 有繼承BnMediaPlayerClient , 那麼BpMediaPlayerClient 在哪裏構造呢? IMediaDeathNotifier表示它要對遠程對象的銷燬作出反應;
- mediaplayerservice 繼承自 BnMediaPlayerService, 那麼mediaplayer要使用mediaplayerservice 的服務,必然要構建BpMediaPlayerService, 在哪裏構建的呢? 關注mediaplayer 中時有出現的const sp<IMediaPlayerService>& service(getMediaPlayerService()); getMediaPlayerService 在IMediaDeathNotifier 中被實作,got it , 通過defaultServiceManager(), 去getService(String16("media.player")), 拿到binder, 再進一步interface_cast<IMediaPlayerService>(binder); 拿到BpMediaPlayerService;
- 獲取BpMediaPlayerService之後,我們就可以通過BpMediaPlayerService,跨進程調用到BnMediaPlayerService的子類mediaplayerservice, mediaplayer 中sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId)); 這一句開始進行create 調用,我們來到IMediaPlayerService.cpp, BpMediaPlayerService create 通過remote()->transact(CREATE, data, &reply), 觸發BnMediaPlayerService::onTransact 中的case CREATE, 首先在其中構建sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); OK , 我們構建出BpMediaPlayerClient, 以BpMediaPlayerClient爲參數進一步構建sp<IMediaPlayer> player = create(pid, client, audioSessionId); 在mediaplayerservice中我們完成了對於BnMediaPlayer的構建,並將其返回, 再回到BpMediaPlayerService create , 最後一句 return interface_cast<IMediaPlayer>(reply.readStrongBinder()); 以BnMediaPlayerService的reply成功的構建出了BpMediaPlayer, 此BpMediaPlayer被賦值於MediaPlayer中的mPlayer, 自此我們完成了BpMediaPlayer, BnMediaPlayer , BpMediaPlayerClient的構建;
- BpMediaPlayerClient位於mediaplayerservice端,其用於信息的回傳,而由於mediaplayer 繼承自BnMediaPlayerClient的緣故,對於mediaplayerservice回傳的的信息,我們會在mediaplayer notify中進行監聽,將必要的信息通過listener 進一步上傳,最後通過java 調用postEventFromNative將信息通知到apk.
- BpMediaPlayer 構建完成後,我們就可以在mediaplayer中通過BpMediaPlayer跨進程調用BnMediaPlayer即mediaplayerservice中class Client : public BnMediaPlayer的方法,在Client中進行setDataSource , prepare , play的動作;
- 在MediaPlayerService::Client中有一成員變量mClient, 實爲BpMediaPlayerClient, 兩個client的理解不一致, MediaPlayerService::Client只是相對MediaPlayerService來說,其用於處理一個instance,實際上其爲BnMediaPlayer,在這一點上理解,它是提供服務的server端; mClient 爲回傳信息而存在;
至此,我們基本理清了mediaplayer與mediaplayerservice之間的BpBinder 以及BnBinder的構建;