android binder机制之三 Server Porxy

服务代理对象

        上一篇android binder机制之--(我是Service Manager)我们学习了Service Manager(服务管家)在Android Binder中的作用——服务(Service)注册,服务(Service)查询和获取等功能。

        我们知道Service Manager既是服务的管理对象,又是一个系统级的服务server(通过向驱动发送设置命令,使自己成为服务管家),它用来管理系统服务,也用于向客户端体统服务。那么Service Manager的客户端(包括我们通常所说的其它系统服务和系统服务的客户端)如何同它进行通讯呢?客户端不可能凭空发送请求吧!那么在android系统中的binder肯定有实现客户端和服务端联系的机制。

        本文我们一起学习服务(Service)在客户端中的代理机制,服务代理对象就是服务端和客户端的这个联络员。在详细介绍服务代理之前,让我们先来了解一下服务代理在应用中的模型。

(一)服务代理应用模型

        下面是客户端(这里的客户端是泛指请求服务的一方,自然有时候也包括System Server,比如当System Server向Service Manager请求添加服务的时候)通过服务代理,向服务器端请求服务的模型:

(1)首先客户端向Service manager查找相应的Service。这在前一篇文中有比较详细的介绍,这里不做赘述。

(2)Android系统的binder机制将会为客户端进程中创建一个Service代理,这个创建过程是本文的重点,下面会详细介绍。

(3)客户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后由Service代理把用户请求转发给Service本身。

(4)Service处理完成之后,把结果返回给Service代理,Service代理负责把处理结果返回给客户端。

        注意客户端对Service代理的调用都是同步调用(调用挂起,直到调用返回为止),这样客户端视角来看调用远端Service的服务和调用本地的函数没有任何区别。这就是我之前说的Binder机制的一个特点—线程迁移,这使得一个线程就像进入另一个线程执行并待会执行结果。

 

(二)MediaService

        要想说明白服务代理的创建过程,还真不是那么容易的,最好的办法就是参照android中的源码,一步步走下去,这里我们还是选择MediaService的应用为例吧(看过一些资料也是以MS为例介绍的)。

        MediaService是android系统中的一个应用程序,和其他普通的应用程序没什么不同,源码如下:

framework\base\Media\MediaServer\Main_mediaserver.cpp

int main(int argc, char** argv)
{
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}

        怎么样?看到这个文件的代码是不是很迷惑啊!那么多陌生的东东,怎么理解啊!那么多的难关,那么厚的面纱,看来,要想见到服务代理的创建,还得过五关斩六将啊!下面我们就来层层剥开她神秘的面纱。

(1)ProcessState

        在Android系统中任何进程,要想使用Binder机制,必须要创建一个ProcessState对象和IPCThreadState对象(不要急,这个对象我们将在后面介绍)。

        我们知道,一个客户端进程可能有多个Service的服务,这样就会创建多个Service代理(BpBinder对象,当然上面还会有封装的),那么这个进程就需要一个东东来管理这些服务代理。ProcessState就是这么个东东,它的作用就是维护当前进程中所有Service代理。

        ProcessState是一个singleton类型(关于这个类型,你可以查阅相关资料),一个进程只能创建一个他的对象。客户端进程中的ProcessState对象将会负责维护这些Service代理。那既然这样,Service代理是不是就是这个ProcessState创建的呢?呵呵,你猜对了,Service代理正是在这里被创建的,不过我可没打算现在就来分析服务代理的创建过程,你的一步一步脚踏实地地才能走向“光明”哦!

       上面的main函数中的第一句是什么?不就是这个ProcessState嘛,这里我们暂且记住一点,她就是一个管理服务代理的对象就好。先来看看她的创建过程,那就看看她的构造函数,咦,怎会回事?这个构造函数是私有成员那!

private:
  ProcessState();

        嗯,你没有看错,它的确是被声明成私有成员了,那就意味着在类的外部无法直接通过其构造函数,生成自己的一个对象,所以上面Main函数里面用了另一个公有成员函数ProcessState::self(),来调用其构造函数,生成ProcessState对象:

sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;//如果已经创建了,//则直接返回这个全局的ProcessState对象
    AutoMutex _l(gProcessMutex);
//如果第一次创建,调用其构造函数
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

还记得Main函数中的第一句:

sp<ProcessState> proc(ProcessState::self());

        不是说不能在外部直接调用其构造函数的吗?其实这也不是我们讨论的重点,不过既然说了,就解释一下吧。熟悉C++的朋友应该都知道,当你定义的类中,没有显示定义一个复制构造函数的话,系统会帮你添加一个默认的复制构造函数,上面的就是调用这个复制构造函数。

ProcessState::ProcessState()定义如下:
ProcessState::ProcessState()
    : mDriverFD(open_driver())   /*太高强了,竟然在初始化列表中,直接调用函数,初始化成员变量,真是不容易看到啊*/
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    ……
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);//映射内存
        ……
}

        这样就生成了一个ProcessState对象proc,用来管理本进程中所有的服务代理,当程序运行结束,proc会自动delete内部的内容,自动释放了先前分配的资源。

这里ProcessState对象打开了/dev/binder设备,并保留了文件描述符,那么打开设备文件,自然是要用它进行通讯了,不过在ProcessState中你还真的很难找到,使用这个文件描述符进行通讯的代码。那么它在什么地方使用呢?我们会在后面介绍IPCThreadState时候在有说明。

(2)defaultServiceManager()

    ……
sp<IServiceManager> sm = defaultServiceManager();

        这里生成了一个IserviceManager的对象sm,IserviceManager是什么?还记得上一篇文中的内容吧,serviceManager是服务管家,它负责系统服务的管理。你当然不会简单的认为有了serviceManager这个程序就万事OK了,这个守护进程做这么伟大的事,怎么可能孤军奋战,每一个成功的男人背后都有一个支持他的女人,这是谁说的,不记得了,呵呵!serviceManager也不例外,IserviceManager就提供了这样的一个机制,给了serviceManager管理服务的能力。

       那么这个sm究竟什么呢?说的明白点,上面那行代码就是生成了一个服务代理啦!不要惊奇,MS进程就是通过这个代理对象sm和Service Manager通讯的,下面我们就来重点分析这个IserviceManager对象sm的创建过程。 

Frameworks\base\libs\binder\IserviceManager.cpp

p<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) 
return gDefaultServiceManager;  //如果已经创建过,//直接返回
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        if (gDefaultServiceManager == NULL) {
          gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));     //创建代理对象
        }
    }
    return gDefaultServiceManager;
}

这个函数中调用了下面的语句:

gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));     //创建代理对象

       这是创建代理对象的地方,这句代码比较复杂一些,先来看看它的参数吧,ProcessState::self()我们现在已经很熟悉了,getContextObject()函数是干什么的:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
    if (supportsProcesses()) {
/*根据参数句柄,创建一个代理对象,这里传的参数是0,记住这一点,在后面我们会解释*/
        return getStrongProxyForHandle(0);
    } else {
        return getContextObject(String16("default"), caller);
    }
}      

       这个getStrongProxyForHandle(int32_t handle)函数才是真正创建服务代理的地方,上面都是对其的封装罢了,看看这段代码:

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);/*我们之前说过ProcessState维护了该进程的一个服务代理对象的列表,这里就是根据handle句柄,在当前进程的服务代理链表中查找指定的服务代理对象,并返回一个handle_entry 指针*/
    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); /*看这里,服务代理就是在这被创建的,对,没错,BpBinder才是真正的服务代理,在上层生成的BpIServiceMananger对象是对她的封装,后面再做介绍*/
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();//增加引用计数
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}

   

        当前进程首先调用lookupHandleLocked函数去查看当前进程维护的Service代理对象的列表,该待创建Service代理对象是否已经在当前进程中创建,如果已经创建过了,则直接返回其引用就可以了。否则将会在Service代理对象的列表增加相应的位置,保存将要创建的代理对象。lookupHandleLocked的源码这里就不贴出来了,自己查阅吧!

        如果Service代理对象已经创建过了,直接增加引用计数就行了。若没有创建过,则需要创建一个新的Service代理对象。下面是BpBinder的构造函数:

BpBinder::BpBinder(int32_t handle)
    : mHandle(handle)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(NULL)
{
    LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
 
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    IPCThreadState::self()->incWeakHandle(handle);

        注意:上面创建服务代理对象时,传递的是handle,handle是一个表示符,用来标志不同的服务类型,这里的handle其实是0,上面已经有所说明,可以回头看看。Binder机制中,binder驱动每个服务维护一个服务句柄(这是Windows中的概念),上层创建服务代理对象时,传入一个唯一标志服务句柄handle,就可以获得这个特定服务句柄的代理对象。0号服务句柄就是Service Mananger服务的,这是著名句柄,众所周知的。

       这里多少两句,我们刚才应该看到了,代码生产了一个BpBinder对象,并赋给了sp<IBinder>指针,说明BpBinder是Ibinder的一个继承类。Ibinder类是android系统对binder机制的一个抽象定义,其实就是一个抽象类,所有要实现binder机制的客户,服务端都要继承这个抽象类。 这时程序又返回到了这里:

   gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));     //创建代理对象

        这个调用ProcessState::self()->getContextObject(NULL)返回的是sp<IBinder>类型,而gDefaultServiceManager是一个sp<IServiceManager>对象,这两者有嘛关系啊,为何能够转换呢?先不管这些,先来看看这个interface_cast<XXX>如何定义的吧!

Framework\base\include\binder\Iiterface.h

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

       这是个模版类,C++特有的东东,刚才的我们看到的是用IserviceManager来对模版进行实例化的,那我们还原一下代码:

template<typename IserviceManager>
inline sp< IserviceManager > interface_cast(const sp<IBinder>& obj)
{
    return IserviceManager::asInterface(obj);
}

        那么这个IserviceManager::asInterface()在哪儿呢?我找遍源码也没发现它定义的地方,后来发现不是那么回事,要想理清这层关系还要从IserviceManager类说起,下面是它的定义:

Framework\base\include\binder\IserviceManager.h

class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager);
……
    virtual status_t  addService( const String16& name,
                                            const sp<IBinder>& service) = 0;
……
};

  

        这个类继承了IIterface类,并出现一个貌似宏的东东DECLARE_META_INTERFACE(ServiceManager);这是什么玩意呢?不太喜欢这个东东,所以一开始看代码时就没太注意这东西,可后来才发现这是类型转换的关键所在,看看定义:

Framework\base\include\binder\Iiterface.h

#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const String16 descriptor;                                   \
    static sp<I##INTERFACE> asInterface(const sp<IBinder>& obj);        \
    virtual const String16& getInterfaceDescriptor() const;             \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \

       这里可没有注释啊,那些“\”玩意都是控制换行连接的,这个定义一大堆的,都什么玩意,看的头痛,咱也不管它是什么,我们先来个顺藤摸瓜,既然上面IserviceManager类定义时,传递了一个ServiceManager参数,那就给他兑换出来看看得了,我把“\”去掉,就当是一个函数了,方便观察。

#define DECLARE_META_INTERFACE(serviceManager)
{                               
    static const String16 descriptor;                                   
    static sp<IserviceManager> asInterface(const sp<IBinder>& obj);        
    virtual const String16& getInterfaceDescriptor() const;             
    IserviceManager();                                                     
    virtual ~IserviceManager();     
}                                       

        呵呵,这下就一目了然了吧,不就是声明了一个字符串描述符和一个返回描述符的接口函数,还有构造和析构函数嘛! 当然,这里出现了我们想要的东西asInterface()的定义,那这样我们上面的函数调用就有着落啦!嗯,现在是看看它定义的时候了!

       既然它声明这么横空,那定义怎么着也得打扮一下吧!瞧瞧,在IserviceManager.cpp文件中有这么一句代码:

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

      真是双胞胎啊,长的那么像,看看这个孪生胞弟:

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const String16 I##INTERFACE::descriptor(NAME);                      \
    const String16& I##INTERFACE::getInterfaceDescriptor() const {      \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& obj)  \
    {                                                                   \
        sp<I##INTERFACE> intr;                                          \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                

       还是看不下去了,先兑现先:

#define IMPLEMENT_META_INTERFACE(serviceManager, "android.os.IServiceManager")                       
    const String16 IserviceManager::descriptor("android.os.IServiceManager");      
                
    const String16& IserviceManager::getInterfaceDescriptor() const {      
        return IserviceManager::descriptor;                                
    }     
                                                              
    sp<IserviceManager> IserviceManager::asInterface(const sp<IBinder>& obj)  
    {                                                                   
        sp<IserviceManager> intr;                                          
        if (obj != NULL) {                                              
            intr = static_cast<IserviceManager*>(                          
                obj->queryLocalInterface(IserviceManager::descriptor).get());               
            if (intr == NULL) {                                         
                intr = new BpserviceManager (obj); /*原来在这里,通过Ibinder对象创建了一个BpserviceManager对象,然后返回给MS进程*/                         
            }                                                           
        }                                                               
        return intr;                                                    
    }             
                                                      
    I##INTERFACE::IserviceManager () { }              
                      
    I##INTERFACE::~IserviceManager () { }                                

        这下终于清楚了,最后就是将一个BpServiceManager对象返回给sm,那么你也看出来了,BpServiceManager是IserviceManager的一个继承类,而这个对象sm就是MS进程获得的Service Manager服务的代理了,MS就可以通过sm这个代理对象发送添加服务等请求了。

        代码走到这里,服务代理对象的生成过程就结束了,总之一句话,defaultServiceManager()函数返回了一个Service Manager的服务代理对象,提供给本进程的其他服务器端或客户端访问Service Manager的接口。

(三)服务器端初始化

framework\base\Media\MediaServer\Main_mediaserver.cpp

int main(int argc, char** argv)
{
    ……
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();
    ……
}

        这四行代码就是android系统中,SM进程驱动的四个系统服务的初始化代码。每个服务都调用自己的instantiate()实例化函数,向Service Manager注册自己,以为之前做过Camera模块,比较熟悉点,呵呵,所以我们以CameraServce::instantiate()为例来说明服务器端实例化的过程:

Framework\base\camera\libcameraservice\cameraservice.cpp

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

 

        其实就是这么简单,首先创建一个自己的实例,然后调用defaultServiceManager()函数,获得Service Manager的服务代理对象,再通过这个代理对象调用添加服务函数,将自己注册到服务管理器,这个过程中的每一步,前面我们都已经分析过了,可以回头看看。其他的服务实例化过程和这个过程相同。

(四)ThreadState:: startThreadPool()

Void Main()   
{
……
……
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}

       上面的代码已经说过了,这里就不列出来了,当MS执行到这里时,本进程完成了如下工作:

(1) 创建了ProcessState对象,用来管理本进程中获取的服务代理对象。注意:每一个进程只能创建一个该对象。

(2) 获取了Service Manager的服务代理对象,可以通过这个对象和服务管家通讯了。

(3) 实例化了一些服务,并向服务管家成功添加了这些服务。

       既然服务端准备好了,就应该进入循环状态,以便接收来自客户端的请求,没错,那么,下面我们继续分析上面两句代码:

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

  

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        ……
        sp<Thread> t = new PoolThread(isMain);
//创建线程池,然后跑起来
        t->run(buf);
    }
}

         PoolThread继承自Thread,这里的PoolThread()构造函数,其实什么都没做,就连run()函数都没有重载,创建该对象后直接调用run()函数。真正的线程创建在其父类Thread的run()中被创建:

status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
   ……
    if (mCanCallJava) {
        res = createThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
   //这里创建了一个_threadLoop线程函数,这时候线程运行起来
    } else {
        res = androidCreateRawThreadEtc(_threadLoop,
                this, name, priority, stack, &mThread);
    }
    ……
}

 

int Thread::_threadLoop(void* user)
{
    Thread* const self = static_cast<Thread*>(user);
 
    do {
            if (first) {
            first = false;
            self->mStatus = self->readyToRun();
            ……         
        } else {
            result = self->threadLoop();//调用PoolThread的threadLoop()
        }
 
        ……
      } while(strong != 0);
    
    return 0;
}

 

Framework\base\libs\binder\ProcessThread.cpp

virtual bool threadLoop()
{
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
}

 

        到了这里,发现很奇怪啊,也是调用的IPCThreadState::joinThreadPool()函数,好吧,既然两句都是调用这个函数,而且这里都再次引入了一个不可忽视的对象IPCThreadState,下面先来了解一下什么是IPCThreadState,然后在分析这个joinThreadPoll()函数。

 

(五)IPCThreadState

        前面我们有提过,在ProcessState中打开了一个binder设备文件,并返回了一个文件描述符,在ProcessState中并没有使用这个文件描述符的地方,那么这个文件描述符到底被谁使用了呢?对,就是IPCThreadState对象。

       IPCThreadState也是一个singleton的类型,一个进程中也只能有一个这样的对象。它在android的binder机制中扮演什么样的角色呢?到了这里,你也可能已经猜到了,IPCThreadState主要负责信息的传递,所有要到达binder驱动和驱动中出来的信息,都要由IPCThreadState来传递。IPCThreadState有一个传输函数transact():

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ……
    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        
    } else {
        err = waitForResponse(NULL, NULL);
    }
    
    return err;
}
 
 
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    int32_t cmd;
    int32_t err;
 
    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        
        cmd = mIn.readInt32();
 
        switch (cmd) {
        case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) goto finish;
            break;
          ……
    }
    
    return err;
}

 

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ……
    do {
        
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
        ……
    } while (err == -EINTR);
    
    ……
}

         这里出现ioctl()函数了,这可是binder驱动的接口啊,下面就不再跟踪了,总之,上层的信息就是通过这个途径发送的binder驱动的。这样我们再来总结一下IPCThreadState对象的作用:

(1) 维护当前进程中所有对/dev/binder的读写。换句话说当前进程通过binder机制进行跨进程调用都是通过IPCThreadState对象来完成的。

(2) IPCThreadState也可以理解成/dev/binder设备的封装,用户可以不直接通过ioctl来操作binder设备,都通过IPCThreadState对象来代理即可。

         说了半天,这里还是通过mDriverFD文件描述符,向binder设备文件写入数据。可是这个mDriverFD不是ProcessState的东东吗,怎么在这里被引用了呢?看看ProcessSate类定义就知道了。

private:
    friend class IPCThreadState; 

         哦,原来IPCThreadState是ProcessState的一个友元类,这样IPCThreadSate就可以名正言顺地使用mDriverFD了。好了,下面我们继续来分析joinThreadPool()函数吧!

 void IPCThreadState::joinThreadPool(bool isMain)
{
    
    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);
    status_t result;
    do {
        int32_t cmd;
        result = talkWithDriver();
        result = executeCommand(cmd);
        }
        
    } while (result != -ECONNREFUSED && result != -EBADF);
    
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}

        看到了吧,这里是一个循环,循环调用talkWithDriver()从binder设备文件中读取信息,然后调用executeCommand()函数处理信息。这就是系统服务的循环体,不断重复地响应客户端的请求。

        不管是客户端进程和Service进程都是需要用IPCThreadState来和binder设备通讯的。那么现在我们从客户端和服务器端分别来总结一下IPCThreadState对象的作用。

  (1)如果是客户端进程,则通过服务代理BpBinder对象,调用transact函数,该函数作用就是把客户端的请求写入binder设备另一端的Service进程,详细的内容我们放在下一篇文章介绍。

  (2)作为Service进程,当他完成初始化工作之后,他们需要进入循环状态等待客户端的请求,Service进程调用它的IPCThreadState对象的joinThreadPool方法,开始轮询binder设备,等待客户端请求的到来。

(六)总结

        本文中我们通过MS程序,分析了Service Manager服务代理的创建过程,以及服务线程启动循环监听消息的过程,当然还有服务代理的概念,服务代理的管理对象ProcessState和消息传递对象IPCThreadState。

        后面我们会从客户端请求服务端的服务的视角,来分析binder机制在android系统中的实际应用。

你可能感兴趣的:(android binder机制之三 Server Porxy)