android基础部分再学习---Binder

参考文章:http://blog.csdn.net/coding_glacier/article/details/7520199

1.binder通信概述

    binder通信是一种client-server的通信结构,
    1.从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;
    2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;
    3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;
    4.代理接口将该Parcel发送给内核中的binder driver.
    5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
    6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

 

android基础部分再学习---Binder_第1张图片 

 

2.service manager

Service Manager是一个linux级的进程,顾名思义,就是service的管理器。这里的service是什么概念呢?这里的service的概念和init过程中init.rc中的service是不同,init.rc中的service是都是linux进程,但是这里的service它并不一定是一个进程,也就是说可能一个或多个service属于同一个linux进程。在这篇文章中不加特殊说明均指android native端的service。

任何service在被使用之前,均要向SM(Service Manager)注册,同时客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。
    
    SM的入口函数在service_manager.c中,下面是SM的代码部分
int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)/n", strerror(errno));
        return -1;
    }

    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}

这个进程的主要工作如下:
    1.初始化binder,打开/dev/binder设备;在内存中为binder映射128K字节空间;
    2.指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要创建一个handle为0的代理binder,这里的代理binder其实就是第一节中描述的那个代理接口;

3.通知binder driver(BD)使SM成为BD的context manager;
4.维护一个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容;即是否有对service的操作要求, 如果有,则调用svcmgr_handler回调来处理请求的操作。

5.SM维护了一个svclist列表来存储service的信息。

 

android基础部分再学习---Binder_第2张图片

这里需要声明一下,当service在向SM注册时,该service就是一个client,而SM则作为了server。而某个进程需要与service通信时,此时这个进程为client,service才作为server。因此service不一定为server,有时它也是作为client存在的。

 

由于下面几节会介绍一些与binder通信相关的几个概念,所以将SM的功能介绍放在了后面的部分来讲。

应用和service之间的通信会涉及到2次binder通信。

1.应用向SM查询service是否存在,如果存在获得该service的代理binder,此为一次binder通信;
2.应用通过代理binder调用service的方法,此为第二次binder通信。

3.ProcessState

ProcessState是以单例模式设计的。每个进程在使用binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在binder通信时的binder状态。
    ProcessState有如下2个主要功能:
    1.创建一个thread,该线程负责与内核中的binder模块进行通信,称该线程为Pool thread;
    2.为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

 

3.1 Pool thread

            在Binder IPC中,所有进程均会启动一个thread来负责与BD来直接通信,也就是不停的读写BD,这个线程的实现主体是一个IPCThreadState对象,下面会介绍这个类型。

            下面是 Pool thread的启动方式:

ProcessState::self()->startThreadPool();

3.2 BpBinder获取

BpBinder主要功能是负责client向BD发送调用请求的数据。它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据,它的构造函数如下:

BpBinder(int32_t handle);
    通过BpBinder的构造函数发现,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标。

ProcessState通过如下方式来获取BpBinder对象:

ProcessState::self()->getContextObject(handle);

在这个过程中,ProcessState会维护一个BpBinder的vector mHandleToObject,每当ProcessState创建一个BpBinder的实例时,回去查询mHandleToObject,如果对应的handle已经有binder指针,那么不再创建,否则创建binder并插入到mHandleToObject中。
    ProcessState创建的BpBinder实例,一般情况下会作为参数构建一个client端的代理接口,这个代理接口的形式为BpINTERFACE,例如在与SM通信时,client会创建一个代理接口BpServiceManager.
    
   

4.IPCThreadState

IPCThreadState也是以单例模式设计的。由于每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Pool thread,也就是说每一个进程只会启动一个Pool thread,因此每个进程则只需要一个IPCThreadState即可。
    Pool thread的实际内容则为:
    IPCThreadState::self()->joinThreadPool();

 

ProcessState中有2个Parcel成员,mIn和mOut,Pool thread会不停的查询BD中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中,总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在了mOut中。

ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。

 

IPCThreadState有两个重要的函数,talkWithDriver函数负责从BD读写数据,executeCommand函数负责解析并执行mIn中的数据。

android基础部分再学习---Binder_第3张图片

5.主要基类

5.1基类IInterface

为server端提供接口,它的子类声明了service能够实现的所有的方法;


5.2基类IBinder
    BBinder与BpBinder均为IBinder的子类,因此可以看出IBinder定义了binder IPC的通信协议,BBinder与BpBinder在这个协议框架内进行的收和发操作,构建了基本的binder IPC机制。
5.3基类BpRefBase
    client端在查询SM获得所需的的BpBinder后,BpRefBase负责管理当前获得的BpBinder实例。

 

 

6.两个接口类

6.1 BpINTERFACE

如果client想要使用binder IPC来通信,那么首先会从SM出查询并获得server端service的BpBinder,在client端,这个对象被认为是server端的远程代理。为了能够使client能够想本地调用一样调用一个远程server,server端需要向client提供一个接口,client在在这个接口的基础上创建一个BpINTERFACE,使用这个对象,client的应用能够想本地调用一样直接调用server端的方法。而不用去关心具体的binder IPC实现。
下面看一下BpINTERFACE的原型:
    class BpINTERFACE : public BpInterface<IINTERFACE>

    顺着继承关系再往上看
    template<typename INTERFACE>
    class BpInterface : public INTERFACE, public BpRefBase

    BpINTERFACE分别继承自INTERFACE,和BpRefBase;
● BpINTERFACE既实现了service中各方法的本地操作,将每个方法的参数以Parcel的形式发送给BD。
例如BpServiceManager的
    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
        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;
    }
● 同时又将BpBinder作为了自己的成员来管理,将BpBinder存储在mRemote中,BpServiceManager通过调用BpRefBase的remote()来获得BpBinder指针。

 

6.2 BnINTERFACE

在定义android native端的service时,每个service均继承自BnINTERFACE(INTERFACE为service name)。BnINTERFACE类型定义了一个onTransact函数,这个函数负责解包收到的Parcel并执行client端的请求的方法。

    顺着BnINTERFACE的继承关系再往上看,
        class BnINTERFACE: public BnInterface<IINTERFACE>

    IINTERFACE为client端的代理接口BpINTERFACE和server端的BnINTERFACE的共同接口类,这个共同接口类的目的就是保证service方法在C-S两端的一致性。

    再往上看
        class BnInterface : public INTERFACE, public BBinder

    同时我们发现了BBinder类型,这个类型又是干什么用的呢?既然每个service均可视为一个binder,那么真正的server端的binder的操作及状态的维护就是通过继承自BBinder来实现的。可见BBinder是service作为binder的本质所在。

    那么BBinder与BpBinder的区别又是什么呢?

    其实它们的区别很简单,BpBinder是client端创建的用于消息发送的代理,而BBinder是server端用于接收消息的通道。查看各自的代码就会发现,虽然两个类型均有transact的方法,但是两者的作用不同,BpBinder的transact方法是向IPCThreadState实例发送消息,通知其有消息要发送给BD;而BBinder则是当IPCThreadState实例收到BD消息时,通过BBinder的transact的方法将其传递给它的子类BnSERVICE的onTransact函数执行server端的操作。

 

7. Parcel

Parcel是binder IPC中的最基本的通信单元,它存储C-S间函数调用的参数.但是Parcel只能存储基本的数据类型,如果是复杂的数据类型的话,在存储时,需要将其拆分为基本的数据类型来存储。

    简单的Parcel读写不再介绍,下面着重介绍一下2个函数

 

7.1 writeStrongBinder

当client需要将一个binder向server发送时,可以调用此函数。例如
        virtual status_t addService(const String16& name, const sp<IBinder>& service)
        {
            Parcel data, reply;
            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;
        }


看一下writeStrongBinder的实体
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

接着往里看flatten_binder
status_t flatten_binder(const sp<ProcessState>& proc,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;
    
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    if (binder != NULL) {
        IBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                LOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.handle = handle;
            obj.cookie = NULL;
        } else {
            obj.type = BINDER_TYPE_BINDER;
            obj.binder = local->getWeakRefs();
            obj.cookie = local;
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = NULL;
        obj.cookie = NULL;
    }
    
    return finish_flatten_binder(binder, obj, out);
}

    还是拿addService为例,它的参数为一个BnINTERFACE类型指针,BnINTERFACE又继承自BBinder,
    BBinder* BBinder::localBinder()
    {
        return this;
    }
    所以写入到Parcel的binder类型为BINDER_TYPE_BINDER,同时你在阅读SM的代码时会发现如果SM收到的service的binder类型不为BINDER_TYPE_HANDLE时,SM将不会将此service添加到svclist,但是很显然每个service的添加都是成功的,addService在开始传递的binder类型为BINDER_TYPE_BINDER,SM收到的binder类型为BINDER_TYPE_HANDLE,那么这个过程当中究竟发生了什么?
    为了搞明白这个问题,花费我很多的事件,最终发现了问题的所在,原来在BD中做了如下操作(drivers/staging/android/Binder.c):


static void binder_transaction(struct binder_proc *proc,
                   struct binder_thread *thread,
                   struct binder_transaction_data *tr, int reply)
{
..........................................

    if (fp->type == BINDER_TYPE_BINDER)
        fp->type = BINDER_TYPE_HANDLE;
    else
        fp->type = BINDER_TYPE_WEAK_HANDLE;
    fp->handle = ref->desc;
..........................................
}

 


阅读完addService的代码,你会发现SM只是保存了service binder的handle和service的name,那么当client需要和某个service通信了,如何获得service的binder呢?看下一个函数

7.2 readStrongBinder

当server端收到client的调用请求之后,如果需要返回一个binder时,可以向BD发送这个binder,当IPCThreadState实例收到这个返回的Parcel时,client可以通过这个函数将这个被server返回的binder读出。


sp<IBinder> Parcel::readStrongBinder() const
{
    sp<IBinder> val;
    unflatten_binder(ProcessState::self(), *this, &val);
    return val;
}


往里查看unflatten_binder


status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    const flat_binder_object* flat = in.readObject(false);
    
    if (flat) {
        switch (flat->type) {
            case BINDER_TYPE_BINDER:
                *out = static_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(NULL, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }        
    }
    return BAD_TYPE;
}


发现如果server返回的binder类型为BINDER_TYPE_BINDER的话,也就是返回一个binder引用的话,直接获取这个binder;如果server返回的binder类型为BINDER_TYPE_HANDLE时,也就是server返回的仅仅是binder的handle,那么需要重新创建一个BpBinder返回给client。


    有上面的代码可以看出,SM保存的service的binder仅仅是一个handle,而client则是通过向SM获得这个handle,从而重新构建代理binder与server通信。


    这里顺带提一下一种特殊的情况,binder通信的双方即可作为client,也可以作为server.也就是说此时的binder通信是一个半双工的通信。那么在这种情况下,操作的过程会比单工的情况复杂,但是基本的原理是一样的,有兴趣可以分析一下MediaPlayer和MediaPlayerService的例子。

 

8. 经典桥段分析

main_ mediaserver.cpp
int main(int argc, char** argv)
{

//创建进程mediaserver的ProcessState实例
    sp<ProcessState> proc(ProcessState::self());

//获得SM的BpServiceManager
    sp<IServiceManager> sm = defaultServiceManager();
    LOGI("ServiceManager: %p", sm.get());

//添加mediaserver中支持的service。
    AudioFlinger::instantiate();
    MediaPlayerService::instantiate();
    CameraService::instantiate();
    AudioPolicyService::instantiate();

//启动ProcessState的pool thread
    ProcessState::self()->startThreadPool();

//这一步有重复之嫌,加不加无关紧要。
    IPCThreadState::self()->joinThreadPool();
}

 

9. Java 层的binder机制

了解了native通信机制后,再去分析JAVA层的binder机制,它只是对native的binder做了一个封装。



Binder的java层框架

Binder的Java框架层包含以下类(frameworks/base/core/java/android/os):IBinder,Binder,IInterface,ServiceManagerNative,ServiceManager,BinderInternal,IServiceManager,ServiceManagerProxy。

Binder的Java框架层部分方法的实现在本地代码里,源码位于frameworks/base/core/jni。

与Binder本地框架类似,声明的binder service接口必须继承自IInterface,这里ICloudManager继承自IInterface。与Binder 本地框架层不相同的是,Java层的IBinder接口直接继承自IInterface,而本地的IBinder类继承自RefBase。本地的IBinder有两个子类,BBinder和BpBinder,Java层的IBinder接口也有两个子类,Binder和BinderProxy。Java层服务端的CloudManager (binder service实体类) 直接继承自Binder类,并实现了binder service接口ICloudManager,而客户端的CloudManagerProxy类只需实现binder service接口ICloudManager即可。

Binder java层框架相关 Jni源码

Binder Java层框架类有不少方法是native的,意味着这些native方法是jni方法。Java层框架中的类Binder,BinderProxy,BinderInternal的native方法的实现是在源码frameworks/base/core/jni/android_util_Binder.cpp里,Java层框架中Parcel类native方法的实现是在frameworks/base/core/jni/android_os_Parcel.cpp里。接下来我们将详细分析android_util_Binder.cpp。

重要数据结构

  • 1) gBinderOffsets,代表android.os.Binder 类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    static struct bindernative_offsets_t
    {
        // 指向class对象android.os.Binder 
        jclass mClass;
        //指向 android.os.Binder的execTransact方法
        jmethodID mExecTransact;
     
        //指向android.os.Binder的mObject字段,
        //将用于保存指向JavaBBinderHolder对象的指针
        jfieldID mObject;
     
    } gBinderOffsets;
  • 2) gBinderInternalOffsets,代表com.android.internal.os.BinderInternal类

    1
    2
    3
    4
    5
    6
    7
    8
    
    static struct binderinternal_offsets_t
    {
        //指向 class对象com.android.internal.os.BinderInternal
        jclass mClass;
        //指向BinderInternal的forceGc方法
        jmethodID mForceGc;
     
    } gBinderInternalOffsets;
  • 3) binderproxy_offsets_t,代表android.os.BinderProxy类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    static struct binderproxy_offsets_t
    {
        //指向 class对象android.os.BinderProxy
        jclass mClass;
        //指向 BinderProxy的构造方法
        jmethodID mConstructor;
        //指向 BinderProxy的sendDeathNotice方法
        jmethodID mSendDeathNotice;
     
        //指向 BinderProxy的mObject字段
        jfieldID mObject;
        //指向 BinderProxy的mSelf字段
        jfieldID mSelf;
        //指向 BinderProxy的mOrgue字段
        jfieldID mOrgue;
     
    } gBinderProxyOffsets;
  • 4) JavaBBinder和JavaBBinderHolder

    JavaBBinder和JavaBBinderHolder相关类类图如下所示(若看不清,请点击看大图),JavaBBinder继承自本地框架的BBinder,代表binder service服务端实体,而JavaBBinderHolder保存JavaBBinder指针,Java层Binder的mObject保存的是JavaBBinderHolder指针的值,故此这里用聚合关系表示。BinderProxy的mObject保存的是BpBinder对象指针的值,故此这里用聚合关系表示。

    android基础部分再学习---Binder_第4张图片

重要函数

  • 1) javaObjectForIBinder 将本地IBinder对象转为Java层的IBinder对象,实际类型是BinderProxy

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    
    jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
    {
        if (val == NULL) return NULL;
     
        //如果是 binder 服务端进程调用javaObjectForIBinder 
        //将调用JavaBBinder的object方法返回jobject,
        //这里jobject的实际Java类型是Binder
        if (val->checkSubclass(&gBinderOffsets)) {
            // One of our own!
            jobject object = static_cast<JavaBBinder*>(val.get())->object();
            LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(),
                     object);
            return object;
        }
        //如果是binder客户端进程,则需要返回Java层的BinderProxy对象
     
        // For the rest of the function we will hold this lock, to serialize
        // looking/creation of Java proxies for native Binder proxies.
        AutoMutex _l(mProxyLock);
     
        // 如果已有用Java层WeakReference保存的BinderProxy对象,则返回该对象
        jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
        if (object != NULL) {
            jobject res = env->CallObjectMethod(object, 
                              gWeakReferenceOffsets.mGet);
            if (res != NULL) {
                ALOGV("objectForBinder %p: found existing %p!\n", val.get(),
                       res);
                return res;
            }
            LOGDEATH("Proxy object %p of IBinder %p no longer 
                      in working set!!!", object, val.get());
            android_atomic_dec(&gNumProxyRefs);
            val->detachObject(&gBinderProxyOffsets);
            env->DeleteGlobalRef(object);
        }
     
        //创建BinderProxy对象
        object = env->NewObject(gBinderProxyOffsets.mClass, 
                     gBinderProxyOffsets.mConstructor);
        if (object != NULL) {
            LOGDEATH("objectForBinder %p: created new proxy %p !\n",
                val.get(), object);
            // The proxy holds a reference to the native object.
            //设置BinderProxy对象的mObject字段为本地IBinder对象指针,
            //本地IBinder对象的实际类型是BpBinder
            env->SetIntField(object, gBinderProxyOffsets.mObject, 
                   (int)val.get());
            val->incStrong(object);
     
            // The native object needs to hold a weak reference back to the
            // proxy, so we can retrieve 
            //the same proxy if it is still active.
            jobject refObject = env->NewGlobalRef(
                    env->GetObjectField(object, gBinderProxyOffsets.mSelf));
            //关联gBinderProxyOffsets,故此第20行代码用findObject才能找到      
            val->attachObject(&gBinderProxyOffsets, refObject,
                    jnienv_to_javavm(env), proxy_cleanup);
     
            // Also remember the death recipients registered on this proxy
            sp<DeathRecipientList> drl = new DeathRecipientList;
            drl->incStrong((void*)javaObjectForIBinder);
            env->SetIntField(object, gBinderProxyOffsets.mOrgue, 
                        reinterpret_cast<jint>(drl.get()));
     
            // Note that a new object reference has been created.
            android_atomic_inc(&gNumProxyRefs);
            incRefsCreated(env);
        }
     
        return object;
    }
  • 2) ibinderForJavaObject 将Java层的IBinder对象转为本地IBinder对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
    {
        if (obj == NULL) return NULL;
     
        //如果是Java层Binder对象 
        //则将Binder对象的mObject字段转为JavaBBinderHolder指针
        //然后调用它的get方法即可转为本地IBinder对象,实际类型是JavaBBinder
        if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
            JavaBBinderHolder* jbh = (JavaBBinderHolder*)
                env->GetIntField(obj, gBinderOffsets.mObject);
            return jbh != NULL ? jbh->get(env, obj) : NULL;
        }
     
        //如果是Java层的BinderProxy对象,
        //则将BinderProxy对象的mObject字段直接转为本地的IBinder对象指针
        //实际类型是本地框架里的BpBinder
        if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
            return (IBinder*)
                env->GetIntField(obj, gBinderProxyOffsets.mObject);
        }
     
        ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
        return NULL;
    }

初始化流程

Java虚拟机启动时会调用jni方法来注册Java层binder框架的本地方法,流程如下图所示(若看不清请点击看大图):

android基础部分再学习---Binder_第5张图片
binder 的使用例子:
参考地址:http://blog.csdn.net/lilian0118/article/details/24397953

在Java Service当中,会经常使用到AIDL工具,AIDL在google官方文档的解释是:"AIDL (Android Interface Definition Language) is similar to other IDLs you might have worked with. It allows you to define the programming interface that both the client and service agree upon in order to communicate with each other using interprocess communication (IPC)"。即AIDL是一种接口描述语言,用于定义client和service共同认可的接口。听起来比较绕口,直接来看IWifiManger.aidl的大致内容:

[cpp]  view plain  copy
 
  1. interface IWifiManager  
  2. {  
  3.     List<WifiConfiguration> getConfiguredNetworks();  
  4.   
  5.     int addOrUpdateNetwork(in WifiConfiguration config);  
  6.   
  7.     boolean removeNetwork(int netId);  
  8.   
  9.     boolean enableNetwork(int netId, boolean disableOthers);  
  10.   
  11.     boolean disableNetwork(int netId);  
  12.   
  13.     boolean pingSupplicant();  
  14.   
  15.     void startScan(in WorkSource ws);  
  16.   
  17.     List<ScanResult> getScanResults(String callingPackage);  
  18.   
  19.     void disconnect();  
  20.   
  21.     void reconnect();  
  22.   
  23.     void reassociate();  

这里定义了一系列的函数接口,在AIDL中除了支持Java原始类型数据(int、long、char、boolean等),还支持String、CharSequence、list和map。进过AIDL工具的转换,就可以将上面的aidl文件生成一个Java文件,其内容大致如下:

[java]  view plain  copy
 
  1. public interface IWifiManager extends android.os.IInterface {  
  2.     public static abstract class Stub extends android.os.Binder implements  
  3.             android.net.wifi.IWifiManager {  
  4.         private static final java.lang.String DESCRIPTOR = "android.net.wifi.IWifiManager";  
  5.   
  6.         public Stub() {  
  7.             this.attachInterface(this, DESCRIPTOR);  
  8.         }  
  9.   
  10.         public static android.net.wifi.IWifiManager asInterface(  
  11.                 android.os.IBinder obj) {  
  12.             if ((obj == null)) {  
  13.                 return null;  
  14.             }  
  15.             android.os.IInterface iin = (android.os.IInterface) obj  
  16.                     .queryLocalInterface(DESCRIPTOR);  
  17.             if (((iin != null) && (iin instanceof android.net.wifi.IWifiManager))) {  
  18.                 return ((android.net.wifi.IWifiManager) iin);  
  19.             }  
  20.             return new android.net.wifi.IWifiManager.Stub.Proxy(obj);  
  21.         }  
  22.   
  23.         public android.os.IBinder asBinder() {  
  24.             return this;  
  25.         }  
  26.   
  27.         @Override  
  28.         public boolean onTransact(int code, android.os.Parcel data,  
  29.                 android.os.Parcel reply, int flags)  
  30.                 throws android.os.RemoteException {  
  31.             switch (code) {  
  32.           
  33.             }  
  34.             }  
  35.             return super.onTransact(code, data, reply, flags);  
  36.         }  
  37.   
  38.         private static class Proxy implements android.net.wifi.IWifiManager {  
  39.             private android.os.IBinder mRemote;  
  40.   
  41.             Proxy(android.os.IBinder remote) {  
  42.                 mRemote = remote;  
  43.             }  
  44.   
  45.             public android.os.IBinder asBinder() {  
  46.                 return mRemote;  
  47.             }  
  48.   
  49.             public java.lang.String getInterfaceDescriptor() {  
  50.                 return DESCRIPTOR;  
  51.             }  
  52.         }  

IWifiManager.java中主要包含三个类:IWifiManager类、IWifiManager.Stub类、IWifiManager.Stub.Proxy类,WifiSerive就是继承于IWifiManager.Stub类。前面我们已经看过它的关系了,下面来看一般获取WifiService的方法:

[java]  view plain  copy
 
  1. IBinder b = ServiceManager.getService(WIFI_SERVICE);  
  2. IWifiManager service = IWifiManager.Stub.asInterface(b);  
  3. return new WifiManager(ctx.getOuterContext(), service);  

这里调用ServiceManager的getService方法,WIFI_SERVICE就是"wifi"字串:

[cpp]  view plain  copy
 
  1. public static IBinder getService(String name) {  
  2.     try {  
  3.         IBinder service = sCache.get(name);  
  4.         if (service != null) {  
  5.             return service;  
  6.         } else {  
  7.             return getIServiceManager().getService(name);  
  8.         }  
  9.     } catch (RemoteException e) {  
  10.         Log.e(TAG, "error in getService", e);  
  11.     }  
  12.     return null;  
  13. }  

sCache用于缓存所有使用过的Java Service,它有ActivityManagerService在fork进程的时候拷贝进来,我们以后分析到AMS的时候再来看sCache,这里先假设sCache并没有我们想要的"wifi" service。然后调用getIServiceManager()的getService方法。前面分析过getIServiceManager()其实最后就是返回ServiceManagerProxy(BinderProxy),所以这里调用ServiceManagerProxy的getService方法:

[java]  view plain  copy
 
  1. public IBinder getService(String name) throws RemoteException {  
  2.     Parcel data = Parcel.obtain();  
  3.     Parcel reply = Parcel.obtain();  
  4.     data.writeInterfaceToken(IServiceManager.descriptor);  
  5.     data.writeString(name);  
  6.     mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
  7.     IBinder binder = reply.readStrongBinder();  
  8.     reply.recycle();  
  9.     data.recycle();  
  10.     return binder;  
  11. }  

首先获取两个Parcel对象,然后向data中写入Strict mode和"android.os.IServiceManager",然后再写入想要获取的service名字,即“wifi”。再调用mRemote.transact方法,这里的实现在android_util_Binder.cpp中,我们前面一章分析过,这里直接调用BpBinder(0)的transact方法,将GET_SERVICE_TRANSACTION命令发往binder驱动。我们来看Java层如何从Parcel中读取想要的Servcie:

[cpp]  view plain  copy
 
  1.     public final IBinder readStrongBinder() {  
  2.         return nativeReadStrongBinder(mNativePtr);  
  3.     }  
  4.   
  5. static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)  
  6. {  
  7.     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);  
  8.     if (parcel != NULL) {  
  9.         return javaObjectForIBinder(env, parcel->readStrongBinder());  
  10.     }  
  11.     return NULL;  
  12. }  

我们前面在分析Native Service的获取时曾经说过binder驱动首先判断ref->node->proc == target_proc,即注册的进程和现在获取MediaPlayerService的进程是否是同一个,如果是,则改写fp->type为BINDER_TYPE_BINDER,并设置fp->binder为binder->getWeakRefs(),fp->cookie等于binder->local本身。如果不是在同一个进程(这也是大多数case的状况),则首先调用binder_get_ref_for_node为获取MediaPlayerService的进程分配一个新的binder_ref结构,这里的binder id值可能不是之前注册的binder id值了(因为不在同一个进程,desc是往上增长的),然后设置fp->handle为新的desc值。首先来看Native层的Parcel的readStrongBinder方法:

[cpp]  view plain  copy
 
  1. sp<IBinder> Parcel::readStrongBinder() const  
  2. {  
  3.     sp<IBinder> val;  
  4.     unflatten_binder(ProcessState::self(), *this, &val);  
  5.     return val;  
  6. }  
  7.   
  8. status_t unflatten_binder(const sp<ProcessState>& proc,  
  9.     const Parcel& in, sp<IBinder>* out)  
  10. {  
  11.     const flat_binder_object* flat = in.readObject(false);  
  12.       
  13.     if (flat) {  
  14.         switch (flat->type) {  
  15.             case BINDER_TYPE_BINDER:  
  16.                 *out = static_cast<IBinder*>(flat->cookie);  
  17.                 return finish_unflatten_binder(NULL, *flat, in);  
  18.             case BINDER_TYPE_HANDLE:  
  19.                 *out = proc->getStrongProxyForHandle(flat->handle);  
  20.                 return finish_unflatten_binder(  
  21.                     static_cast<BpBinder*>(out->get()), *flat, in);  
  22.         }          
  23.     }  
  24.     return BAD_TYPE;  
  25. }  

这里分两种情况,一是注册WifiService的进程和获取WifiService的进程是同一个时(这个比较经常,因为注册WifiService是在systemserver当中,systemserver会注册很多其它的Service,这些Service会互相调用)。这时type就是BINDER_TYPE_BINDER,然后通过static_cast将cookie处保存的指针直接转换为前面注册的JavaBBinder;二是注册WifiSerivce的进程和获取WifiService的进程不是同一个时,这里调用getStrongProxyForHandle重新返回一个BpBinder(handle id)。回到上面的android_os_Parcel_readStrongBinder方法,这里再调用javaObjectForIBinder对IBinder对象做一层封装:

[cpp]  view plain  copy
 
  1. jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)  
  2. {  
  3.     if (val == NULL) return NULL;  
  4.   
  5.     if (val->checkSubclass(&gBinderOffsets)) {  
  6.   
  7.     }  
  8.   
  9.     AutoMutex _l(mProxyLock);  
  10.   
  11.     jobject object = (jobject)val->findObject(&gBinderProxyOffsets);  
  12.     if (object != NULL) {  
  13.         jobject res = jniGetReferent(env, object);  
  14.         if (res != NULL) {  
  15.             ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);  
  16.             return res;  
  17.         }  
  18.         LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());  
  19.         android_atomic_dec(&gNumProxyRefs);  
  20.         val->detachObject(&gBinderProxyOffsets);  
  21.         env->DeleteGlobalRef(object);  
  22.     }  
  23.   
  24.     object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);  
  25.     if (object != NULL) {  
  26.         env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());  
  27.         val->incStrong((void*)javaObjectForIBinder);  
  28.   
  29.         jobject refObject = env->NewGlobalRef(  
  30.                 env->GetObjectField(object, gBinderProxyOffsets.mSelf));  
  31.         val->attachObject(&gBinderProxyOffsets, refObject,  
  32.                 jnienv_to_javavm(env), proxy_cleanup);  
  33.   
  34.         sp<DeathRecipientList> drl = new DeathRecipientList;  
  35.         drl->incStrong((void*)javaObjectForIBinder);  
  36.         env->SetIntField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jint>(drl.get()));  
  37.   
  38.         android_atomic_inc(&gNumProxyRefs);  
  39.         incRefsCreated(env);  
  40.     }  
  41.   
  42.     return object;  
  43. }  

前一章里面分析过这个函数,这里会构造一个BinderProxy对象,并将当前的IBinder(可能是JavaBBinder,也可能是BpBinder)与BinderProxy绑定起来。然后将BinderProxy对象返回给获取Service的进程。接着调用IWifiManager service = IWifiManager.Stub.asInterface(b),它的实现如下:

[java]  view plain  copy
 
  1. public static android.net.wifi.IWifiManager asInterface(  
  2.         android.os.IBinder obj) {  
  3.     if ((obj == null)) {  
  4.         return null;  
  5.     }  
  6.     android.os.IInterface iin = (android.os.IInterface) obj  
  7.             .queryLocalInterface(DESCRIPTOR);  
  8.     if (((iin != null) && (iin instanceof android.net.wifi.IWifiManager))) {  
  9.         return ((android.net.wifi.IWifiManager) iin);  
  10.     }  
  11.     return new android.net.wifi.IWifiManager.Stub.Proxy(obj);  
  12. }  
这里的obj是BinderProxy对象,它的queryLocalInterface默认返回NULL,所以这里会先构造一个IWifiManager.Stub.Proxy并返回。最后通过IWifiManager.Stub.Proxy构造一个WifiManager对象给应用层使用。


Java Service的调用

我们来看一下WifiManager中一个简单的API使用:
[java]  view plain  copy
 
  1. public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {  
  2.     try {  
  3.         mService.setWifiApEnabled(wifiConfig, enabled);  
  4.         return true;  
  5.     } catch (RemoteException e) {  
  6.         return false;  
  7.     }  
  8. }  

这里的mService就是上面构造的IWifiManager.Stub.Proxy对象,来看它的setWifiApEnabled方法:
[java]  view plain  copy
 
  1. public boolean setWifiApEnabled(  
  2.         android.net.wifi.WifiConfiguration wifiConfig,  
  3.         boolean enable) throws android.os.RemoteException {  
  4.     android.os.Parcel _data = android.os.Parcel.obtain();  
  5.     android.os.Parcel _reply = android.os.Parcel.obtain();  
  6.     boolean _result;  
  7.     try {  
  8.         _data.writeInterfaceToken(DESCRIPTOR);  
  9.         if ((wifiConfig != null)) {  
  10.             _data.writeInt(1);  
  11.             wifiConfig.writeToParcel(_data, 0);  
  12.         } else {  
  13.             _data.writeInt(0);  
  14.         }  
  15.         _data.writeInt(((enable) ? (1) : (0)));  
  16.         mRemote.transact(Stub.TRANSACTION_setWifiApEnabled, _data,  
  17.                 _reply, 0);  
  18.         _reply.readException();  
  19.         _result = (0 != _reply.readInt());  
  20.     } finally {  
  21.         _reply.recycle();  
  22.         _data.recycle();  
  23.     }  
  24.     return _result;  
  25. }  

首先还是获取两个Parcel对象,一个用于存储发送到WifiService的数据;一个用于获取WifiService的回复。并向data中写入strict mode和"android.net.wifi.IWifiManager",再写入两个参数。最后调用mRemote.transact方法。我们知道这里的mRemote就是前面构造的BinderProxy对象,所以来看它的transact方法,它的实现在android_util_Binder.cpp
[java]  view plain  copy
 
  1. static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,  
  2.         jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException  
  3. {  
  4.     if (dataObj == NULL) {  
  5.   
  6.     }  
  7.   
  8.     Parcel* data = parcelForJavaObject(env, dataObj);  
  9.     if (data == NULL) {  
  10.         return JNI_FALSE;  
  11.     }  
  12.     Parcel* reply = parcelForJavaObject(env, replyObj);  
  13.     if (reply == NULL && replyObj != NULL) {  
  14.         return JNI_FALSE;  
  15.     }  
  16.   
  17.     IBinder* target = (IBinder*)  
  18.         env->GetIntField(obj, gBinderProxyOffsets.mObject);  
  19.     if (target == NULL) {  
  20.         jniThrowException(env, "java/lang/IllegalStateException""Binder has been finalized!");  
  21.         return JNI_FALSE;  
  22.     }  
  23.   
  24.     status_t err = target->transact(code, *data, reply, flags);  
  25.   
  26.     if (err == NO_ERROR) {  
  27.         return JNI_TRUE;  
  28.     } else if (err == UNKNOWN_TRANSACTION) {  
  29.         return JNI_FALSE;  
  30.     }  
  31.   
  32.     signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);  
  33.     return JNI_FALSE;  
  34. }  

这里也要分两种情况讨论,一种是在同一个进程中,这里的target就是JavaBBinder;如果在不同进程中,这里的target就是BpBinder。首先来看在同一个进程的情况,调用JavaBBinder的transact方法,因为JavaBBinder是继承于BBinder,所以直接到BBinder的transact方法中:
[cpp]  view plain  copy
 
  1. status_t BBinder::transact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  3. {  
  4.     data.setDataPosition(0);  
  5.   
  6.     status_t err = NO_ERROR;  
  7.     switch (code) {  
  8.         case PING_TRANSACTION:  
  9.             reply->writeInt32(pingBinder());  
  10.             break;  
  11.         default:  
  12.             err = onTransact(code, data, reply, flags);  
  13.             break;  
  14.     }  
  15.   
  16.     if (reply != NULL) {  
  17.         reply->setDataPosition(0);  
  18.     }  
  19.   
  20.     return err;  
  21. }  

直接调用onTransact方法,当然这里的onTransact方法是JavaBBinder重写后的。当不同同一个进程中调用时,target就是BpBinder,所以调用BpBinder的transact方法,最后通过ioctrl发送命令给注册binder驱动中的JavaBBinder(WifiService的包装),同样还是会调用到JavaBBinder的onTransact方法,只是多了一个跨进程的数据传递过程。
[cpp]  view plain  copy
 
  1. virtual status_t onTransact(  
  2.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)  
  3. {  
  4.     JNIEnv* env = javavm_to_jnienv(mVM);  
  5.   
  6.     IPCThreadState* thread_state = IPCThreadState::self();  
  7.     const int strict_policy_before = thread_state->getStrictModePolicy();  
  8.     thread_state->setLastTransactionBinderFlags(flags);  
  9.   
  10.     jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,  
  11.         code, (int32_t)&data, (int32_t)reply, flags);  
  12.     jthrowable excep = env->ExceptionOccurred();  
  13.   
  14.     const int strict_policy_after = thread_state->getStrictModePolicy();  
  15.     if (strict_policy_after != strict_policy_before) {  
  16.         thread_state->setStrictModePolicy(strict_policy_before);  
  17.         set_dalvik_blockguard_policy(env, strict_policy_before);  
  18.     }  
  19.   
  20.     jthrowable excep2 = env->ExceptionOccurred();  
  21.     if (excep2) {  
  22.         report_exception(env, excep2,  
  23.             "*** Uncaught exception in onBinderStrictModePolicyChange");  
  24.         /* clean up JNI local ref -- we don't return to Java code */  
  25.         env->DeleteLocalRef(excep2);  
  26.     }  
  27.   
  28.     if (code == SYSPROPS_TRANSACTION) {  
  29.         BBinder::onTransact(code, data, reply, flags);  
  30.     }  
  31.   
  32.     return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;  
  33. }  

这里主要就是调用Binder.java的execTransact来处理请求:
[java]  view plain  copy
 
  1.     private boolean execTransact(int code, int dataObj, int replyObj,  
  2.             int flags) {  
  3.         Parcel data = Parcel.obtain(dataObj);  
  4.         Parcel reply = Parcel.obtain(replyObj);  
  5.         boolean res;  
  6.         try {  
  7.             res = onTransact(code, data, reply, flags);  
  8.         } catch (RemoteException e) {  
  9.             if ((flags & FLAG_ONEWAY) != 0) {  
  10.                 Log.w(TAG, "Binder call failed.", e);  
  11.             }  
  12.             reply.setDataPosition(0);  
  13.             reply.writeException(e);  
  14.             res = true;  
  15.         } catch (RuntimeException e) {  
  16.             if ((flags & FLAG_ONEWAY) != 0) {  
  17.                 Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);  
  18.             }  
  19.             reply.setDataPosition(0);  
  20.             reply.writeException(e);  
  21.             res = true;  
  22.         } catch (OutOfMemoryError e) {  
  23.             Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e);  
  24.             RuntimeException re = new RuntimeException("Out of memory", e);  
  25.             reply.setDataPosition(0);  
  26.             reply.writeException(re);  
  27.             res = true;  
  28.         }  
  29.         reply.recycle();  
  30.         data.recycle();  
  31.         return res;  
  32.     }  
  33. }  

这里直接调用WIfiService的onTransact方法,它的实现在IWifiManager.Stub中:
[java]  view plain  copy
 
  1. public boolean onTransact(int code, android.os.Parcel data,  
  2.         android.os.Parcel reply, int flags)  
  3.         throws android.os.RemoteException {  
  4.     switch (code) {  
  5.   
  6.     case TRANSACTION_setWifiApEnabled: {  
  7.         data.enforceInterface(DESCRIPTOR);  
  8.         android.net.wifi.WifiConfiguration _arg0;  
  9.         if ((0 != data.readInt())) {  
  10.             _arg0 = android.net.wifi.WifiConfiguration.CREATOR  
  11.                     .createFromParcel(data);  
  12.         } else {  
  13.             _arg0 = null;  
  14.         }  
  15.         boolean _arg1;  
  16.         _arg1 = (0 != data.readInt());  
  17.         boolean _result = this.setWifiApEnabled(_arg0, _arg1);  
  18.         reply.writeNoException();  
  19.         reply.writeInt(((_result) ? (1) : (0)));  
  20.         return true;  
  21.     }  

首先从Parcel中读出WifiConfiguration和enable两个参数,然后调用WifiServcie的setWifiApEnabled方法,并把执行结果写入到reply中。如果不在同一个进程中调用,最后通过IPCThreadState的sendReply方法将结果返回给调用者。到这里,一次Java Servcie的调用就完成了。



你可能感兴趣的:(Android开发,Binder)