一、服务代理的基本原理

    如下是客户端请求service服务的场景:

1、首先客户端向Service manager查找相应的Service。关于此,上文《Android系统Binder机制之一(Service Manager篇)》已有比较详细的介绍。注意客户端和Service可能在两个不同的进程中。 

2、Android系统将会为客户端进程中创建一个Service代理。关于此,下文将详细介绍。 

3、客户端视角只有Service代理,他所有对Service的请求都发往Service代理,然后有Service代理把用户请求转发给Service本身。Service处理完成之后,把结果返回给Service代理,Service代理负责把处理结果返回给客户端。注意客户端对Service代理的调用都是同步调用(调用挂住,直到调用返回为止),这样客户端视角来看调用远端Service的服务和调用本地的函数没有任何区别。这也是Binder机制的一个特点。

二、Android进程环境——ProcessState类型和对象

    在Android系统中任进程何,要想使用Binder机制,必须要创建一个ProcessState对象和IPCThreadState对象。当然如果Android进程不使用Binder机制,那么这两个对象是不用创建的。这种情况很少见,因为Binder机制是整个Android框架的基础,可以说影响到Android方方面面。所以说了解这两个对象的作用非常重要。

    台湾的高焕堂先生一片文章《认识ProcessState类型和对象》,可以在我的博文《(转)高焕堂——Android框架底层结构知多少?》中找到。可以先通过这篇文章对ProcessState进行一个大概了解。

    ProcessState是一个singleton类型,一个进程只能创建一个他的对象。他的作用是维护当前进程中所有Service代理(BpBinder对象)。一个客户端进程可能需要多个Service的服务,这样可能会创建多个Service代理(BpBinder对象),客户端进程中的ProcessState对象将会负责维护这些Service代理。

我们研究一下创建一个Service代理的代码:

frameworks\base\libs\binder\ProcessState.cpp中
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
    const size_t N=mHandleToObject.size();
    if (N <= (size_t)handle) {
        handle_entry e;
        e.binder = NULL;
        e.refs = NULL;
        status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
        if (err < NO_ERROR) return NULL;
    }
    return &mHandleToObject.editItemAt(handle);
}
 

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);
    if (e != NULL) {
        // We need to create a new BpBinder if there isn't currently one, OR we
        // are unable to acquire a weak reference on this current one.  See comment
        // in getWeakProxyForHandle() for more info about this.
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}



 getWeakProxyForHandle函数的作用是根据一个binder句柄(上文《Android系统的Binder机制之一——Service Manager》提到Binder驱动为每个Service维护一个Binder句柄,客户端可以通过句柄来和Service通讯)创建对应的Service代理对象。



    当前进程首先调用lookupHandleLocked函数去查看当前进程维护的Service代理对象的列表,该待创建Service代理对象是否已经在当前进程中创建,如果已经创建过了,则直接返回其引用就可以了。否则将会在Service代理对象的列表增加相应的位置(注意系统为了减少分配开销,可能会多分配一些空间,策略是“以空间换时间”),保存将要创建的代理对象。具体代码请参考lookupHandleLocked的源码。

    后面代码就好理解了,如果Service代理对象已经创建过了且当前弱引用数大于0(该值是通过attemptIncWeak返回),直接引用就行了。否则,则需要创建一个新的Service代理对象。

三、Android进程环境——IPCThreadState类型和对象

    Android进程中可以创建一个ProcessState对象,该对象创建过程中会打开/dev/binder设备,并保存其句柄。并初始化该设备。代码如下:

static int open_driver()
{
    int fd = open("/dev/binder", O_RDWR);
    if (fd >= 0) {
        fcntl(fd, F_SETFD, FD_CLOEXEC);
        int vers;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
            LOGE("Binder driver protocol does not match user space protocol!");
            close(fd);
            fd = -1;
        }
        size_t maxThreads = 15;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
    }
    return fd;
}
ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // XXX Ideally, there should be a specific define for whether we
        // have mmap (or whether we could possibly have the kernel module
        // availabla).
#if !defined(HAVE_WIN32_IPC)
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}


mDriverFD保存了/dev/binder设备的句柄,如果仔细查看ProcessState的源码会发现这个句柄不会被ProcessState对象使用。那么保存这个句柄做什么用呢?被谁使用呢?非常奇怪。经过查看ProcessState的头文件,发现如下代码:



1: friend class IPCThreadState;



    发现IPCThreadState是ProcessState的友元类,那么就可以怀疑这个句柄是被IPCThreadState的对象使用的,然后查看代码发现确实如此。



    IPCThreadState也是一个singleton的类型,一个进程中也只能有一个这样的对象。它的源码也位于frameworks\base\libs\binder目录下。我们查看一下它的talkWithDriver函数:        

if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)

            err = NO_ERROR;

        else

            err = -errno;

 IPCThreadState通过ioctl系统调用对ProcessState打开的句柄进行读写。这样我们也可以看出IPCThreadState对象的作用:

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

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

不管是客户端进程和Service进程都是需要用IPCThreadState来和binder设备通讯的。

如果是客户端进程则通过服务代理BpBinder(IBinder的一个子类)对象的transact函数调用IPCThreadState的transact函数,该函数作用就是把客户端的请求写入binder设备另一端的Service进程,具体请参阅IPCThreadState类的transact方法。

如果是Service进程,当他完成初始化工作之后,他需要他们需要进入循环状态等待客户端的请求,Service进程调用它的IPCThreadState对象的joinThreadPool方法,开始轮询binder设备,等待客户端请求的到来,后面我们讨论Service时候会进一步讨论joinThreadPool方法。有兴趣的朋友可以先通过查看代码来了解joinThreadPool方法。

四、Service代理对象BpBinder



    上文关于ProcessState的介绍提到了,客户端进程创建的Service代理对象其实就是BpBinder对象。 BpBinde其实是 IBinder的一个子类。 我们首先了解怎样创建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);
 
  

    } 
  
 
 
我们可以看出首先是通过IPCThreadState读写binder设备增加中相应binder句柄上的Service的引用计数。然后本地保存代理Service的binder句柄mHandle。
 
  
    客户进程对Service的请求都通过调用BpBinder的transact方法来完成:
 
  
IBinder的transact函数源码如下
 
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}

五、Android系统对Binder机制的抽象——IBinder

    上面我们讲解了Binder机制比较底层的机制,这些机制直接用还是比较麻烦的,比如使用binder设备的ioctl,需要记住很多ioctl的代码。

    Android为了是Binder机制容易使用,对Binder机制进行了抽象,定义了IBinder接口,该接口在C/C++和Java层都有定义。IBinder定义了一套使用Binder机制使用和实现客户程序和服务器的通讯协议。可以理解如下定义:

1、向Android注册的Service也必须是IBinder(继承扩展IBinder接口)对象。后续文章中我们讨论Service的时候我们会介绍到这方面的内容。

2、客户端得到Service代理对象也必须定义成IBinder(继承扩展IBinder接口)对象。这也是为什么BpBinder就是继承自IBinder。

3、客户端发送请求给服务器端,将Service代理对象IBinder接口的transact方法。

4、Android系统Binder机制将负责把用户的请求,调用Service对象IBinder接口的onTransact方法。具体实现我们将在以后介绍Service的时候讨论。

六、Service Manager代理对象

    我们知道Service Manager是Android Binder机制的大管家。所有需要通过Binder通讯的进程都需要先获得Service Manager的代理对象才能进行Binder通讯。Service Manager即在C/C++层面提供服务代理,又在Java层面提供服务代理,本文先介绍一下C/C++层面的服务代理,Java层面的服务代理将在后续文章中介绍。

    进程在C/C++层面上面,Android在Android命名空间中定义了一个全局的函数defaultServiceManager(定义在framework/base/libs/binder/IServiceManager.cpp),通过这个函数可以使进程在C/C++层面获得Service Manager的代理。我们先看一下该函数的定义:

sp<IServiceManager>  
     defaultServiceManager 
     ()
 
    
{
 
    
    
      if  
     (gDefaultServiceManager != NULL)  
     return 
      gDefaultServiceManager;
 
    
    {
 
    
        AutoMutex _l(gDefaultServiceManagerLock);
 
    
        
      if 
      (gDefaultServiceManager == NULL) {
 
    
            gDefaultServiceManager = interface_cast<IServiceManager>(
 
    
                ProcessState::self()->getContextObject(NULL));
 
    
        }
 
    
    }
 
    
     
     return 
      gDefaultServiceManager;
 
    
}
 
    
我们可以看到 
      defaultServiceManager 
      是调用ProcessState对象的getContextObject方法获得Service Manager的getContextObject方法获得Service Manager代理对象。我们再看一下 
      getContextObject 
      函数的定义:
 
     
sp<IBinder> ProcessState:: 
       getContextObject 
       (const sp<IBinder>& caller)
 
      
{
 
      
     
       return 
        getStrongProxyForHandle(0);
 
      
}
 
     
    我们可以看出其实是调用我们上面描述过的 
      getStrongProxyForHandle 
      方法,并以句柄0为参数来获得Service Manager的代理对象。
 
     
    P 
      rocessState::self()->getContextObject(NULL) 
      返回一个IBinder对象,怎样把它转化成一个IServiceManager的对象呢?这就是模板函数interface_cast<IServiceManager>的作用了。调用的是IServiceManager.asInterface方法。IServiceManager的asInterface方法通过DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE宏来定义,详细情况请查看IServiceManager类的定义。IMPLEMENT_META_INTERFACE宏关于asInterface的定义如下:
 
     
#define 
       IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
 
     
    const android::String16 I##INTERFACE::descriptor(NAME);             \
 
     
    const android::String16&                                            \
 
     
            I##INTERFACE::getInterfaceDescriptor() const {              \
 
     
         
      return 
       I##INTERFACE::descriptor;                                \
 
     
    }                                                                   \
 
     
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
 
     
            const android::sp<android::IBinder>& obj)                   \
 
     
    {                                                                   \
 
     
        android::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() { }                                   \  
 
     
    最终asInterface将会用一个IBinder对象创建一个BpServiceManager对象,并且BpServiceManager继承自IServiceManager,这样我们就把IBinder对象转换成了IServiceManager对象。如果你仔细查看BpServiceManager的定义,你会发现查询Service,增加Service等方法其实都是调用底层的IBinder对象来完成的。
 
     
    当我们在C/C++层面编写程序使用Binder机制的时候将会调用defaultServiceManager函数来获得Service Manager,比如:很多Android系统Service都是在C/C++层面实现的,他们就需要向Service Manager注册其服务,那么这些服务将调用defaultServiceManager获得Service Manager代理对象。我们在后续介绍Android系统Service的时候将会详细介绍。
 
    
 
      另注 
      : 
      IPCThreadState虽然也是Singleton模式(构造函数私有,通过IPCThreadState::self获取对象实例),但是IPCThreadState可不是一个进程只有一个哦! 
     
 
     

       IPCThreadState对象是放到线程私有存储(Thread Local Storage)中的,一个进程可能有多个线程,因此IPCThreadState是每个线程都可能拥有一个。TLS通过全局的key获取。TLS相当于线程中的“线程全局”变量,线程中的函数是可以直接获取的(你不能在线程函数栈中new一个IPCThreadState对象,但你能获得该线程唯一的IPCThreadState对象)。 
     
 
     

       参考多线程编程模型,再看看IPCThreadState::self为什么那样实现,就知道我所言非虚。