I. Android系统Binder机制之一(Service Manager篇)

本文转载整理自:http://my.unix-center.net/~Simon_fu/?p=875


一、前言

Android虽然构建在Linux上面,但是在IPC(进程间)机制方面,没有利用Linux提供IPC机制,而是自己实现了一套轻量级的IPC机制——binder机制。并且Android Binder机制之上,Android框架提供了一套封装,可以实现对象代理(在本地进程中代理远程进程的对象)。本文简单分析一下Android Binder机制。

二、Binder情景分析

一个IPC通讯我们可以理解成客户端-服务器模式,因此我们先在这里分析一下典型的Binder应用模式:

1、客户端通过某种方式(后文会详细介绍)得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。它可以像其他本地对象一样调用其方法,访问其变量。

2、客户端通过调用服务器代理对象的方法向服务器端发送请求。

3、代理对象把用户请求通过Android内核(Linux内核)的Binder驱动发送到服务器进程。

4、服务器进程处理用户请求,并通过Android内核(Linux内核)的Binder驱动返回处理结果给客户端的服务器代理对象。

5、客户端收到服务器端的返回结果。

如果你对COM或者Corba熟悉的话,以上的情景是否会让你联想到什么呢?没错!都是对象代理。以上的情景,在Android中经常会被用到。如果你还没有注意到这点儿,那么本文非常适合你。

三、Binder机制的组成

1、Binder驱动

binder是内核中的一个字符驱动设备位于:/dev/binder。这个设备是Android系统IPC的核心部分,客户端的服务代理用来通过它向服务器(server)发送请求,服务器也是通过它把处理结果返回给客户端的服务代理对象。我们只需要知道它的功能就可以了,本文我们的重点不在这里,所以后面不会专门介绍这部分。如果想深入了解的话,请研究内核源码中的binder.c。

2、Service Manager

负责管理服务。对应于第一步中,客户端需要向Service Manager来查询和获得所需要服务。服务器也需要向Service Manager注册自己提供的服务。可以看出Service Manager是服务的大管家。

3、服务(Server)

需要强调的是这里服务是指的是System Server,而不是SDK server,请参考《(转)高焕堂——Android框架底层结构知多少?》关于两种Server的介绍(其实应该是三种,丢掉了init调用的server,在init.rc中配置)。

4、客户端

一般是指Android系统上面的应用程序。它可以请求Server中的服务。

5、对象代理

是指在客户端应用程序中生成的Server代理(proxy)。从应用程序角度看代理对象和本地对象没有差别,都可以调用其方法,方法都是同步的,并且返回相应的结果。

四、大内总管——Service Manager

Android系统Binder机制的总管是Service Manager,所有的Server(System Server)都需要向他注册,应用程序需要向其查询相应的服务。可见其作用是多么的重要,所以本文首先介绍Service Manager。

通过上面介绍我们知道Service Manager非常重要,责任重大。那么怎样才能成为Service Manager呢?是不是谁都可以成为Service Manager呢?怎样处理server的注册和应用程序的查询和获取服务呢?为了回答这些问题先查看,Android中Service Manager的源码,其源码位于:

frameworks\base\cmds\servicemanager\service_manager.c

我们发现了main函数,说明他自己就是一个进程,在init.rc中我们发现:

service servicemanager /system/bin/servicemanageruser systemcriticalonrestart restart zygoteonrestart restart media


说明其是Android核心程序,开机就会自动运行。

下面我们在研究一下它的代码,main函数很简单:

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;}


我们看到它先调用binder_open打开binder设备(/dev/binder),其次它调用了binder_become_context_manager函数,这个函数使他自己变为了“Server大总管”,其代码如下:

int binder_become_context_manager(struct binder_state *bs){    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}


也就是通过ioctl向binder设备声明“我就是server大总管”。

Service Manager作为一个Server大总管,本身也是一个server。既然是一个server就要时刻准备为客户端提供服务。最后Service Manager调用binder_loop进入到循环状态,并提供了一个回调函数,等待用户的请求。注意他的Service Manager的客户端既包括应用程序(查询和获取服务),也包括Server(注册服务)。

Service Manager的客户怎样才能请求其服务呢?答案是上文我们提到的情景一样。客户需要在自己进程中创建一个服务器代理。现在没有地方去查询服务,那么它的客户怎样生成他的服务代理对象呢?答案是binder设备(/dev/binder)为每一个服务维护一个句柄,调用binder_become_context_manager函数变为“Server大总管”的服务,他的句柄永远是0,是一个“众所周知”的句柄,这样每个程序都可以通过binder机制在自己的进程空间中创建一个Service Manager代理对象了。其他的服务在binder设备在设备中的句柄是不定的,需要向“Server大总管”查询才能知道。

现在我们需要研究Server怎样注册服务了,还是在其源码中,我们可以看到在其服务处理函数中(上文提到binder_loop函数注册给binder设备的回调函数svcmgr_handler)有如下代码:

case SVC_MGR_ADD_SERVICE:        s = bio_get_string16(msg, &len);        ptr = bio_get_ref(msg);        if (do_add_service(bs, s, len, ptr, txn->sender_euid))            return -1;        break;


有server向binder设备写入请求注册Service时,Service Manager的服务处理回调函数将会被调用。我们在仔细看看do_add_service函数的实现:

int do_add_service(struct binder_state *bs,                   uint16_t *s, unsigned len,                   void *ptr, unsigned uid){    struct svcinfo *si;//    LOGI("add_service('%s',%p) uid=%d\n", str8(s), ptr, uid);    if (!ptr || (len == 0) || (len > 127))        return -1;    if (!svc_can_register(uid, s)) {        LOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",             str8(s), ptr, uid);        return -1;    }    si = find_svc(s, len);    if (si) {        if (si->ptr) {            LOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED\n",                 str8(s), ptr, uid);            return -1;        }        si->ptr = ptr;    } else {        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));        if (!si) {            LOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",                 str8(s), ptr, uid);            return -1;        }        si->ptr = ptr;        si->len = len;        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));        si->name[len] = '\0';        si->death.func = svcinfo_death;        si->death.ptr = si;        si->next = svclist;        svclist = si;    }    binder_acquire(bs, ptr);    binder_link_to_death(bs, ptr, &si->death);    return 0;}


我们看到首先检查是否有权限注册service,没权限就对不起了,出错返回;然后检查是否已经注册过,注册过的service将不能再次注册。然后构造一个svcinfo对象,并加入一个全局链表中svclist中。最后通知binder设备:有一个service注册进来。si->ptr = ptr;这里的ptr应该就是注册的service的句柄。

我们再来看看客户端怎样通过Service Manager获得Service,还是在服务处理函数中(上文提到binder_loop函数注册给binder设备的回调函数)有如下代码:

 case SVC_MGR_GET_SERVICE:    case SVC_MGR_CHECK_SERVICE:        s = bio_get_string16(msg, &len);        ptr = do_find_service(bs, s, len);        if (!ptr)            break;        bio_put_ref(reply, ptr);        return 0;


我们可以看到通过do_find_service查找Service如果查找到的话,写入reply中返回给客户端。

do_find_service函数也在service_manager.c文件中,其源码如下:

void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len){    struct svcinfo *si;    si = find_svc(s, len);//    LOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);    if (si && si->ptr) {        return si->ptr;    } else {        return 0;    }}


do_find_service又调用了find_svc函数,其源码如下:

struct svcinfo *svclist = 0;struct svcinfo *find_svc(uint16_t *s16, unsigned len){    struct svcinfo *si;    for (si = svclist; si; si = si->next) {        if ((len == si->len) &&            !memcmp(s16, si->name, len * sizeof(uint16_t))) {            return si;        }    }    return 0;}

II. Android系统Binder机制之二(服务代理对象 上篇)

上文《Android系统Binder机制之一(Service Manager篇)》我们学习了Service Manager在Android Binder中的作用——服务(Service)注册,服务(Service)查询的功能。本文我们一起学习服务(Service)在客户端中的代理机制。重点介绍其核心对象BpBinder。

一、服务代理的基本原理

如下是客户端请求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的头文件,发现如下代码:

 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的代理对象。

ProcessState::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为什么那样实现,就知道我所言非虚。

III. Android系统Binder机制之三(服务代理对象 下篇)

上文《Android系统的Binder机制之二——服务代理对象(1)》我们学习了进程的C/C++层面的服务代理对象BpBinder,和Binder底层处理方式。本文我们将深入分析一下在进程的Java层面服务代理对象的创建和使用。

一、Android进程的C/C++层面和Java层

Android中程序大部分都是java开发,底层通过JNI调用C/C++的代码。这样一个程序就分为了两个层面C/C++层面和Java层面。运行状态下,我们说它们都在一个进程之中,拥有相同的进程属性(UID,GID等等)。

Binder客户程序的C/C++层面的对象和原理我们在上文《Android系统的Binder机制之二——服务代理对象(1)》已经学习。下面我们将介绍客户程序怎样在Java层面通过JNI调用底层C/C++代码的创建服务代理。

ServiceManager类型和对象

我在《Android系统的Binder机制之一——Service Manager》中介绍过,客户端要想获得服务代理,首先要向ServiceManager查询Service。在Java层面也是这样,所以我们首先分析Java层面ServiceManager类。

我们通过查看android.os.ServiceManager的源码我们发现,ServiceManager类型也是一个Singleton类型。所有的方法都是静态方法,所有静态方法都是访问它的IServiceManager类型的静态变量sServiceManager,定义如下:

private static IServiceManager sServiceManager;

所以可以理解ServiceManager就是IServiceManager对象的一个代理。为创建和访问这个变量都是通过ServiceManager的getIServiceManager方法,定义如下:

    private static IServiceManager getIServiceManager() {        if (sServiceManager != null) {            return sServiceManager;        }        // Find the service manager        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());        return sServiceManager;    }


通过上面的代码,非常清晰的告诉我们ServiceManager类型是一个Singleton类型。现在我们主要研究sServiceManager对象怎样创建的。如下代码创建IServiceManager对象:

sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());

我们首先查看BinderInternal类的getContextObject方法的代码,发现是Native代码(哈哈!有终于到达C/C++层面了,我们已经熟悉了),对应的代码为android_util_binder.cpp中的android_os_BinderInternal_getContextObject函数,代码如下:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz){    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);    return javaObjectForIBinder(env, b);}


终于看到我们上文《Android系统的Binder机制之二——服务代理对象(1)》介绍过的ProcessState对象了,我们再去查看ProcessState对象的getContextObject方法,代码如下:

C语言的sprintf函数跟printf在用法上几乎一样,只是两者打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出

sprintf是个变参函数,定义如下:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller){    return getStrongProxyForHandle(0);}


我们看到在当前进程的ProcessState对象其实是调用getStrongProxyForHandle方法来创建binder句柄为0的服务代理对象——BpBinder对象,我们在《Android系统的Binder机制之一——Service Manager》提到过ServiceManager的binder句柄是一个闻名句柄0。上文《Android系统的Binder机制之二——服务代理对象(1)》已经介绍过ProcessState对象的getStrongProxyForHandle方法,这里就不多说了。

我们可以看出Java调用C/C++,创建一个服务代理对象BpBinder,在查看BpBinder的定义我们发现继承自IBinder接口,然后在android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把C/C++层面的IBinder对象封装成Java层面的IBinder对象。具体实现可以查看上文的android_os_BinderInternal_getContextObject方法。

至此我们已经清楚BinderInternal.getContextObject(),返回的是ServiceManager的服务代理对象——BpBinder对象。那么ServiceManagerNative类的静态方法asInterface做什么用呢?我们还是通过代码来分析,在ServiceManagerNative.java中,asInterface的代码如下:

static public IServiceManager asInterface(IBinder obj)    {        if (obj == null) {            return null;        }        IServiceManager in =            (IServiceManager)obj.queryLocalInterface(descriptor);        if (in != null) {            return in;        }                return new ServiceManagerProxy(obj);    }

将会用IBinder对象创建一个ServiceManagerProxy对象,ServiceManagerProxy类型实现了IServiceManager接口,所以asInterface方法最终目的是用一个IBinder对象创建一个IServiceManager对象。

为什么要用IBinder对象创建一个IServiceManager对象呢?通过ServiceManager的代理对象——IBinder对象(BpBinder对象)应该可以直接请求ServiceManager中的服务了啊?我们在前文《Android系统的Binder机制之二(服务代理对象 上篇)》简单介绍了一下IBinder类型,客户端通过transact方法向Service发送请求,且请求通过请求代码来区分。具体请参考Android手册,也可以参照后面将介绍的ServiceManagerProxy的getService()方法。如果客户端直接用调用ServiceManager的代理对象的IBinder接口,那么客户端必须要记住所有请求的请求代码,对客户端来说不太友好。所以在ServiceManagerNative类中就把ServiceManager的代理对象——IBinder对象(BpBinder对象)封装成ServiceManagerProxy对象,暴露给客户程序一个IServiceManager接口,这样IServiceManager对象(其实是ServiceManagerProxy对象)将会代理客户程通过IBinder把请求发往服务器。客服程序只是简单的调用IServiceManager接口的方法来给ServiceManager发送请求,这样对客户程序来讲和本地的函数调用是一致的,接口非常友好。比如我们客户程序需要调用IServiceManager的getService方法来查询一个Service,ServiceManagerProxy实现代码如下:

class ServiceManagerProxy implements IServiceManager {    public ServiceManagerProxy(IBinder remote) {        mRemote = remote;    }    public IBinder asBinder() {        return mRemote;    }    public IBinder getService(String name) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IServiceManager.descriptor);        data.writeString(name);        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);        IBinder binder = reply.readStrongBinder();        reply.recycle();        data.recycle();        return binder;    }}


我们可以非常清晰的看到ServiceManagerProxy对象将客户程序的请求转换成对ServiceManager代理对象——IBinder对象(BpBinder对象)的调用。后文我们将会详细介绍怎样通过IServiceManager查询和获得一个系统Service代理对象。

到这里我们已经分析完了,ServiceManager的Singleton对象——sServiceManager的创建。如果有不清楚的地方请查看代码。

二、查询和获得Service代理对象

客户程序通过调用ServiceManagerNative的静态方法asInterface获得了IServiceManager对象,但是最终目的一般都是要查询和获得其他的Service,一般都是要调用IServiceManager的getService方法,向ServiceManager获得其他的Service。比如:

IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);

上面的代码中就是调用ServiceManager的静态方法获得网络管理服务代理对象。我们顺藤摸瓜,看看系统是怎样生成这个Service代理对象的。这里只是简单说明一下调用顺序,详细过程请查看源码。

1、调用ServiceManager.java中的ServiceManager静态方法getService。

2、调用ServiceManagerNative.java中的ServiceManagerProxy方法getService。代码如下:

public IBinder getService(String name) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IServiceManager.descriptor);        data.writeString(name);        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);        IBinder binder = reply.readStrongBinder();        reply.recycle();        data.recycle();        return binder;    }

请注意IBinder的transact方法是同步方法(本例中ServiceManager处理完成请求之后才会返回),我们可以看出调用transact之后,调用reply.readStrongBinder()来读取IBinder对象。

3、查看Parcel.java中的readStrongBinder方法,发现是Native方法,将会调用到C/C++的代码。

4、查看android_util_binder.cpp中的android_os_Parcel_readStrongBinder函数。代码如下:

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz){    Parcel* parcel = parcelForJavaObject(env, clazz);    if (parcel != NULL) {        return javaObjectForIBinder(env, parcel->readStrongBinder());    }    return NULL;}


parcel->readStrongBinder()将会产生一个IBinder对象。

5、查看Parcel.cpp中,Parcel的方法readStrongBinder。代码如下:

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


6、查看Parcel.cpp中,Parcel的方法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;}



终于看到调用我们的老朋友ProcessState对象的getStrongProxyForHandle方法了,这样将会创建一个BpBinder对象,然后该BpBinder对象将会被转换成IBinder对象返回给Java层。

7、Java层为了用使用Service方便,可以把Service代理对象——BpBinder对象(IBinder对象)封装成一个对客户程序友好的代理对象,就如前面ServiceManagerProxy所示那样。

8、用户程序就可以通过该代理对象访问相应Service了。

通过所述,我们了解了Service代理对象在Java层的创建和使用。Android系统的Binder机制博大精深,我在本文中很多方面都是蜻蜓点水,如果想深入学习请参阅Android的源码。

参考资料:

IPC框架分析 Binder,Service,Service manager

IV. Android系统的Binder机制之四(系统Service篇)

前面我们已经介绍了Android Binder机制的Service ManagerService对象代理(上)Service对象代理(下)。本文将介绍一下Android机制的另外一个重要部分——系统Service。

一、系统Service实例——Media server

首先我们先看一下Android一个实例Media Service,代码位于framework/base/media/mediaserver/main_mediaserver.cpp文件:

#include <sys/types.h>#include <unistd.h>#include <grp.h>#include <binder/IPCThreadState.h>#include <binder/ProcessState.h>#include <binder/IServiceManager.h>#include <utils/Log.h>#include <AudioFlinger.h>#include <CameraService.h>#include <MediaPlayerService.h>#include <AudioPolicyService.h>#include <private/android_filesystem_config.h>using namespace android;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();}


我们发现Media Server是一个进程,并且该程序的实现表面上也挺简单,其实并不简单,让我们慢慢分析一下Media Server。

1、第一句创建创建一个ProcessState的引用,但是这个对象后面并没有被调用到,那么为什么创建呢?回想一下《

Android系统的Binder机制之二(服务代理对象 上篇)》中介绍ProcessState对象时提到:如果一个进程要使用Binder机制,

那么他的进程中必须要创建一个ProcessState对象来负责管理Service的代理对象。

2、第二句调用defaultServiceManager获得一个Service Manager代理对象,

我在《Android系统的Binder机制之二(服务代理对象 上篇)》已经对此有了详细的介绍这里就不赘述了。


3、后面几行都是创建具体的Service,我们展开之后发现都是一些调用Service Manager的addService进行注册的函数,以AudioFlinger为例,instantiate代码如下:

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

4、最后调用ProcessState的startThreadPool方法和IPCThreadState的joinThreadPool使Media Server进入等待请求的循环当中。

我们可以看出一个进程中可以有多个Service,Media Server这个进程中就存在AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService四个Service。

二、系统Service的基础——BBinder

我们仔细查看一下Media Server中定义的四个Service我们将会发现他们都是继承自BBinder,而BBinder又继承自IBinder接口,详细情况请自行查看他们的代码。每个Service都改写了BBinder的onTransact虚函数,当用户发送请求到达Service时,框架将会调用Service的onTransact函数,后面我们将会详细的介绍这个机制。

三、Service注册

每个Service都需要向“大管家”Service Manager进行注册,调用Service Manager的addService方法注册。这样Service Manager将会运行客户端查询和获取该Service(代理对象),然后客户端就可以通过该Service的代理对象请求该Service的服务。

四、Service进入等待请求的循环

每个Service必须要进入死循环,等待客户端请求的到达,本例中最后两句就是使Service进行等待请求的循环之中。

ProcessState的startThreadPool方法的代码如下

void ProcessState::startThreadPool(){    AutoMutex _l(mLock);    if (!mThreadPoolStarted) {        mThreadPoolStarted = true;        spawnPooledThread(true);    }}void ProcessState::spawnPooledThread(bool isMain){    if (mThreadPoolStarted) {        int32_t s = android_atomic_add(1, &mThreadPoolSeq);        char buf[32];        sprintf(buf, "Binder Thread #%d", s);        LOGV("Spawning new pooled thread, name=%s\n", buf);        sp<Thread> t = new PoolThread(isMain);        t->run(buf);    }}IPCThreadState的joinThreadPool方法的代码如下:void IPCThreadState::joinThreadPool(bool isMain){    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);    // This thread may have been spawned by a thread that was in the background    // scheduling group, so first we will make sure it is in the default/foreground    // one to avoid performing an initial transaction in the background.    androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);    status_t result;    do {        int32_t cmd;        // When we've cleared the incoming command queue, process any pending derefs        if (mIn.dataPosition() >= mIn.dataSize()) {            size_t numPending = mPendingWeakDerefs.size();            if (numPending > 0) {                for (size_t i = 0; i < numPending; i++) {                    RefBase::weakref_type* refs = mPendingWeakDerefs[i];                    refs->decWeak(mProcess.get());                }                mPendingWeakDerefs.clear();            }            numPending = mPendingStrongDerefs.size();            if (numPending > 0) {                for (size_t i = 0; i < numPending; i++) {                    BBinder* obj = mPendingStrongDerefs[i];                    obj->decStrong(mProcess.get());                }                mPendingStrongDerefs.clear();            }        }        // now get the next command to be processed, waiting if necessary        result = talkWithDriver();        if (result >= NO_ERROR) {            size_t IN = mIn.dataAvail();            if (IN < sizeof(int32_t)) continue;            cmd = mIn.readInt32();            IF_LOG_COMMANDS() {                alog << "Processing top-level Command: "                    << getReturnString(cmd) << endl;            }            result = executeCommand(cmd);        }        // After executing the command, ensure that the thread is returned to the        // default cgroup before rejoining the pool.  The driver takes care of        // restoring the priority, but doesn't do anything with cgroups so we        // need to take care of that here in userspace.  Note that we do make        // sure to go in the foreground after executing a transaction, but        // there are other callbacks into user code that could have changed        // our group so we want to make absolutely sure it is put back.        androidSetThreadSchedulingGroup(mMyThreadId, ANDROID_TGROUP_DEFAULT);        // Let this thread exit the thread pool if it is no longer        // needed and it is not the main process thread.        if(result == TIMED_OUT && !isMain) {            break;        }    } while (result != -ECONNREFUSED && result != -EBADF);    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",        (void*)pthread_self(), getpid(), (void*)result);        mOut.writeInt32(BC_EXIT_LOOPER);    talkWithDriver(false);}

Service在IPCThreadState的joinThreadPool方法中,调用talkWithDriver方法和Binder驱动进行交互,读取客户端的请求。当客户端请求到达之后调用executeCommand方法进行处理。

我们再看一下Service怎样处理客户端的请求?我们们查看一下executeCommand方法的源码:


status_t IPCThreadState::executeCommand(int32_t cmd)   {       BBinder* obj;       RefBase::weakref_type* refs;       status_t result = NO_ERROR;              switch (cmd) {           ......             case BR_TRANSACTION:           {               ......               if (tr.target.ptr) {                   sp<BBinder> b((BBinder*)tr.cookie);                   const status_t error = b->transact(tr.code, buffer, &reply, 0);                   if (error < NO_ERROR) reply.setError(error);                                  }                ......                       }           break;             ......       }           if (result != NO_ERROR) {           mLastError = result;       }              return result;   }


可以看到IPCThreadState将会直接调用BBinder的transact方法来处理客户端请求,我们再看一下BBinder的transact方法:

status_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    data.setDataPosition(0);    status_t err = NO_ERROR;    switch (code) {        case PING_TRANSACTION:            reply->writeInt32(pingBinder());            break;        default:            err = onTransact(code, data, reply, flags);            break;    }    if (reply != NULL) {        reply->setDataPosition(0);    }    return err;}


我们发现他将会叫用自己的虚函数onTransact。我们前面提到所有的Service都集成自BBinder,并且都改写了onTransact虚函数。那么IPCThreadState将会调用Service定义onTransact方法来响应客户请求。

五、结论

本文简单介绍了一下系统Service的原理,台湾的高焕堂先生有一篇文章,手把手教怎样实现一个系统Service,你可以在我的博文《(转)高焕堂——Android框架底层结构知多少?》中找到。

Alfred整理发布,本篇博文的著作权信息如下:

更多相关文章

  1. Android之AIDL进程之间的通信
  2. Android多进程使用及其带来的问题
  3. /2015/6/12/ BiliBili Android 新客户端与底部导航 Tabs
  4. Android 客户端与服务器交互
  5. Android进程间通信IPC机制Binder
  6. Android应用中通过AIDL机制实现进程间的通讯实例
  7. Android studio 下的aidl编程实现Android的夸进程间通信

随机推荐

  1. 谈谈Android个人开发者的现状
  2. Android中“分享”功能的实现
  3. 一场关于Android的争论
  4. Android(安卓)连接WIF获取的信息剖析
  5. Android虚拟平台的编译和整合
  6. Android(安卓)性能优化 内存优化 How And
  7. Android中“分享”功能的实现
  8. Android的init过程详解(一)
  9. Android百度地图之位置定位和附近查找代
  10. Android(安卓)Socket 发送广播包的那些坑