2、libmedia MediaPlayer至MediaPlayerService (binder)
client和service之間的通訊通過android binder機制,只是對於使用者而言是透明的。
繼續按照上面play調用流程,上面已經調用到了frameworks的mediaplayer.cpp方法start
status_t MediaPlayer::start(){ LOGV("start"); Mutex::Autolock _l(mLock); if (mCurrentState & MEDIA_PLAYER_STARTED) return NO_ERROR; if ( (mPlayer != 0) && ( mCurrentState & ( MEDIA_PLAYER_PREPARED | MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) { mPlayer->setLooping(mLoop); mPlayer->setVolume(mLeftVolume, mRightVolume); mPlayer->setAuxEffectSendLevel(mSendLevel); mCurrentState = MEDIA_PLAYER_STARTED; status_t ret = mPlayer->start(); if (ret != NO_ERROR) { mCurrentState = MEDIA_PLAYER_STATE_ERROR; } else { if (mCurrentState == MEDIA_PLAYER_PLAYBACK_COMPLETE) { LOGV("playback completed immediately following start()"); } } return ret; } LOGE("start called in state %d", mCurrentState); return INVALID_OPERATION;}
其中mPlayer是setDataSource時候建立的播放器的執行個體,調用到的方法setLooping setVolume等都是在frameworks/base/include/media的IMediaPlayer.h中聲明
以Ixx開頭的標頭檔是binder機制的介面檔案,每個這種介面檔案同級目錄下都會有對應一個.cpp檔案,這裡對應的是IMediaPlayer.cpp,
這個C++檔案定義binder的本地和代理函數,本地的是以Bn開頭,native的意思,BnMediaPlyaer;代理的是以Bp開頭,proxy的意思,BpMediaPlayer
這兩個類之間調用是通過在kernel驅動的、在dev/下產生的一個binder程式來通訊!代理端使用remote()->transact(),本地端響應請求onTransact()
代碼如下:
class BpMediaPlayer: public BpInterface<IMediaPlayer>{public://... status_t start() { Parcel data, reply; data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); remote()->transact(START, data, &reply); return reply.readInt32();}//...}status_t BnMediaPlayer::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){switch(code) {//... case START: { CHECK_INTERFACE(IMediaPlayer, data, reply); reply->writeInt32(start()); return NO_ERROR; } break;//...}//...}
播放器執行個體獲得是通過setDataSource函數建立的,而這個函數會調用MediaPlayerService
const sp<IMediaPlayerService>& service(getMediaPlayerService());
再調用MediaPlayerService的creat和setDataSource
總結下上面流程應該是:
======================================================================
|Applications Music.apk
| |
| |
|Framework MediaPlayer API
======================================================================
--JNI----------------------------------------IMediaPlayer--------------------------------------------------
| |
| |
|libmedia MediaPlayer
| |
--Binder---------------------------------------BpXXX-------------------------------------------------------
-------------------------------------------------BnXXX-------------------------------------------------------
| |
| |
|MediaServer MediaPlayerService
======================================================================
Binder在直觀上看到是直接函數對應調用,實際上是有透過kernel空間的