MediaPlayer-MediaPlayerService-MediaPlayerService::Client的三角關係
- 摘要:1.MediaPlayer 是客戶端2.MediaPlayerService和MediaPlayerService::Client是伺服器端。 2.1MediaPlayerService實現IMediaPlayerService定義的業務邏輯,其主要功能是根據 MediaPlayer::setDataSource輸入的URL呼叫create函式建立對應的 Player.2.2MediaPlayerService::Client實現IMediaPlayer定義的業務邏輯,其主要功能包括
-
1. MediaPlayer是客戶端
2. MediaPlayerService和MediaPlayerService::Client是伺服器端。
2.1 MediaPlayerService實現IMediaPlayerService定義的業務邏輯,其主要功能是根據MediaPlayer::setDataSource輸入的URL呼叫create函式建立對應的Player.
2.2 MediaPlayerService::Client實現IMediaPlayer定義的業務邏輯,其主要功能包括start, stop, pause, resume...,其實現方法是呼叫MediaPlayerService create的Player中的對應方法來實現具體功能。
2.3 它們的三角戀如下圖所示:
3. IXX是什麼東東?
在一個BnXXX或BpXXX都派生於兩個類,具體情況如下:
class BpXXX : public IXXX, public BpRefBase
class BnXXX : public IXXX, public BBinder
3.1 看到了吧,BpXXX和BnXXX都派生於IXXX,哪IXXX又是做什麼的呢? 明確地告訴你,定義業務邏輯,但在BpXXX與BnXXX中的實現方式不同:
1) 在BpXXX中,把對應的binder_transaction_data打包之後通過BpRefBase中的mRemote(BpBinder)傳送出去,並等待結果
2) 在BnXXX中,實現對應的業務邏輯,通過呼叫BnXXX派生類中的方法來實現,如MediaPlayerService::Client
懂了吧, IXXX定義業務邏輯
3.2 哪另外一個做什麼呢?
從上圖可以看出,是用來進行程序間通訊用的。
BpRefBase中有一個mRemote(BpBinder)用來與Binder驅動互動用的。
BBinder是用來從Binder驅動中接收相關請求,並進行相關處理的。
4. 不得不說的MediaPlayerService
class MediaPlayerService : public BnMediaPlayerService
它本身用來實現IMediaPlayerService中定義的業務邏輯,可以看看IMediaPlayerService到底定義了些什麼東東?
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
virtual sp createMediaRecorder(pid_t pid) = 0;
virtual sp createMetadataRetriever(pid_t pid) = 0;
virtual sp create(pid_t pid, const sp &; client, const char* url, const KeyedVector *headers = NULL) = 0;
virtual sp create(pid_t pid, const sp &; client, int fd, int64_t offset, int64_t length) = 0;
virtual sp createMediaConfig(pid_t pid ) = 0;
virtual sp decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
virtual sp getOMX() = 0;
// Take a peek at currently playing audio, for visualization purposes.
// This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
virtual sp snoop() = 0;
};從上面可以看出,還說自己是一個MediaPlayerService,而且還向大內總管ServiceManager進行了註冊,就這麼個create 和decode,能做什麼呢? 我們最熟悉的start ,stop, pause, resume...怎麼不見呢?沒有這些東東,MediaPlayer需要的功能如何實現呢?
帶著這麼多疑問,我們先看看MediaPlayerService是如何實現上述功能的,它到底做了些什麼?
還是讓程式碼自己說話吧:
sp MediaPlayerService::create(
pid_t pid, const sp &; client, const char* url,
const KeyedVector *headers)
{
int32_t connId = android_atomic_inc(&;mNextConnId);
sp c = new Client(this, pid, connId, client);
LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
if (NO_ERROR != c->setDataSource(url, headers))
{
c.clear();
return c;
}
wp w = c;
Mutex::Autolock lock(mLock);
mClients.add(w);
return c;
}原來如此,它負責建立MediaPlayer需要的對應功能,建立了Client(MediaPlayerService),MediaPlayerService::Client的定義如下:
class Client : public BnMediaPlayer, 它實現了IMediaPlayer定義的業務邏輯,哪就看看IMediaPlayer定義了些什麼:
class IMediaPlayer: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayer);
virtual void disconnect() = 0;
virtual status_t setVideoSurface(const sp &; surface) = 0;
virtual status_t setSurfaceXY(int x,int y) = 0;/*add by h00186041 add interface for surface left-up position*/
virtual status_t setSurfaceWH(int w,int h) = 0;/*add by h00186041add interface for surface size*/
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual status_t isPlaying(bool* state) = 0;
virtual status_t seekTo(int msec) = 0;
virtual status_t getCurrentPosition(int* msec) = 0;
virtual status_t getDuration(int* msec) = 0;
virtual status_t reset() = 0;
virtual status_t setAudioStreamType(int type) = 0;
virtual status_t setLooping(int loop) = 0;
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t suspend() = 0;
virtual status_t resume() = 0;
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
// @param request Parcel that must start with the media player
// interface token.
// @param[out] reply Parcel to hold the reply data. Cannot be null.
// @return OK if the invocation was made successfully.
virtual status_t invoke(const Parcel&; request, Parcel *reply) = 0;
// Set a new metadata filter.
// @param filter A set of allow and drop rules serialized in a Parcel.
// @return OK if the invocation was made successfully.
virtual status_t setMetadataFilter(const Parcel&; filter) = 0;
// Retrieve a set of metadata.
// @param update_only Include only the metadata that have changed
//since the last invocation of getMetadata.
//The set is built using the unfiltered
//notifications the native player sent to the
//MediaPlayerService during that period of
//time. If false, all the metadatas are considered.
// @param apply_filter If true, once the metadata set has been built based
// on the value update_only, the current filter is
// applied.
// @param[out] metadata On exit contains a set (possibly empty) of metadata.
//Valid only if the call returned OK.
// @return OK if the invocation was made successfully.
virtual status_t getMetadata(bool update_only,
bool apply_filter,
Parcel *metadata) = 0;
}終於找到了思念已久的start, stop, pause, resume...
所以MediaPlayer::setDataSource返回時,會建立一個與MediaPlayerService::Client對應的BpMediaPlayer,用於獲取MediaPlayerService::Client的各項功能。
4. 1 MediaPlayer又是如何找到MediaPlayerService::Client的呢? 只有MediaPlayerService才向ServiceManager進行了註冊,所以MediaPlayer必須先獲取 BpMediaPlayerService,然後通過BpMediaService的管理功能create,來建立一個 MediaPlayerService::Client.
4.2 為什麼不直接定義一個MediaPlayer向ServiceManager註冊呢?
也 許是為了系統簡化吧,MediaPlayerService包含的功能不只是Client, 還有AudioOutput,AudioCache,MediaConfigClient功能。現在明白了吧,MediaPlayerService就是 一個媒體服務的介面,它先把客人接回來,再根據客人的需求,安排不同的員工去做,就這麼簡單。