android binder 机制三(匿名Service)
什么是匿名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就建立起来了。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就一样了。