Android源码分析--MediaServer源码分析(二)

在上一篇博客中Android源码分析–MediaServer源码分析(一),我们知道了ProcessState和defaultServiceManager,在分析源码的过程中,我们被Android的Binder通信机制中的各种复杂的类关系搞的眼花缭乱,接下来我们就以MediaPlayerService为例来分析一下Binder的通信机制。首先来回顾一下:

  • BpBinder和BBinder都是Android中Binder通信的代表类,其中BpBinder是客户端用来与Server交互的代理类,p代表的就是proxy,而BBinder则是交互的目的端;
  • BpBinder和BBinder是相互对应的,Binder系统会通过handle来标识对应的BBinder。

Android的通信机制基本上可以看做是Client、Server和ServiceManager三者之间的交互:

  • Server首先要注册一些Service到ServiceManager;
  • 如果某个Client要使用Service,则首先到ServiceManager中获得该Service的相关信息;
  • Client得到Service信息,然后和该Service所在的Server进程建立通信之后使用Service。

注册MediaPlayerService

我们知道若要使用一个Service的话首先要进行注册,所有首先让我们来看看MediaService是如何注册的,文件位置:frameworks\base\media\libmediaplayerservice\MediaPlayerService.cpp

void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}

defaultServiceManager返回的其实是一个BpServiceManager对象,在这里我看到了注册的函数addService:

    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
    //将Descriptor作为令牌
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
}

Parcel类可以看作一个数据块,在该类的内部主要封装了一些数据操作的方法。在写入数据之后remote()->transact方法,remote()方法返回的值是mRemote,在上一篇中我们知道它是一个BpBinder对象,之后我们的通信工作就交由了BpBinder的transact方法:

status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Binder一旦死去将永远不能复活.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

BpBinder完全将工作交给了IPCThreadState,接下来的任务也全部转移到了IPCThreadState类中。

IPCThreadState类分析

IPCThreadState也是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个 Pool thread,也就是说每一个进程只会启动一个Pool thread,因此每个进程则只需要一个IPCThreadState即可。首先让我们来看看这个self方法,文件位置:frameworks\base\libs\binder\IPCThreadState.cpp

IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }

    if (gShutdown) return NULL;

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {
        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

TLS是Thread Local Storage的缩写,表示线程本地存储,类似于Java中的ThreadLocal机制)pthread_getspecific和)pthread_setspecific方法分别提供了设置变量和获取变量的方法。

在这里我们看到了get方法,有get方法就一定有对应的set方法,set的设置就在构造函数中:

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mMyThreadId(androidGetTid()),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值