標籤:android binder ipc mediaplayer 通訊
什麼是匿名Service?凡是沒有到ServiceManager上註冊的Service,都是匿名Service。
還是拿上一篇的例子來舉例,看代碼:
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length){ status_t err = UNKNOWN_ERROR; const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); if ((NO_ERROR != doSetRetransmitEndpoint(player)) || (NO_ERROR != player->setDataSource(fd, offset, length))) { player.clear(); } err = attachNewPlayer(player); } return err;}
在BpMediaPlayerService中,create的實現如下:
virtual sp<IMediaPlayer> create( const sp<IMediaPlayerClient>& client, int audioSessionId) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeStrongBinder(client->asBinder()); data.writeInt32(audioSessionId); remote()->transact(CREATE, data, &reply); return interface_cast<IMediaPlayer>(reply.readStrongBinder());}直接跳到服務端MediaPlayerService,看create的真正實現:
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client, int audioSessionId){ pid_t pid = IPCThreadState::self()->getCallingPid(); int32_t connId = android_atomic_inc(&mNextConnId); sp<Client> c = new Client( this, pid, connId, client, audioSessionId, IPCThreadState::self()->getCallingUid()); ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid, IPCThreadState::self()->getCallingUid()); /* add by Gary. start {{----------------------------------- */ c->setScreen(mScreen); /* add by Gary. end -----------------------------------}} */ c->setSubGate(mGlobalSubGate); // 2012-03-12, add the global interfaces to control the subtitle gate wp<Client> w = c; { Mutex::Autolock lock(mLock); mClients.add(w); } return c;}
從代碼中,我們可以看出,service->create(this, mAudioSessionId)是返回了一個參數為Client類型的BpMediaPlayer對象,其中Client為MediaPlayerService的私人內部類,其聲明為:class Client : publicBnMediaPlayer。這樣,Binder通訊的服務端和用戶端就建立起來了。Client端BpMediaPlayer由MediaPlayer使用,Server端BnMediaPlayer由MediaPlayerService使用。
BpMediaPlayer是如何獲得BnMediaPlayer的handle值的呢?答案在MediaPlayerService返回這個binder的引用的時候,binder驅動儲存了這個binder實體的各種資料,建立了節點,看下面的代碼:
status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ switch (code) { case CREATE: { CHECK_INTERFACE(IMediaPlayerService, data, reply); sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); int audioSessionId = data.readInt32(); sp<IMediaPlayer> player = create(client, audioSessionId); reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break;……}}
答案就在這句話中:reply->writeStrongBinder(player->asBinder());
當這個reply寫到Binder驅動時,驅動會特殊處理這種IBinder類型的資料,為Bbinder建立一個handle。
通訊的通路建立後,就可以進行通訊了:player->setDataSource(fd, offset, length)
之後的實現,和上一篇講的普通Service就一樣了。