首页 > 代码库 > android binder 机制三(匿名Service)

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端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就一样了。