Service与Android系统设计(4)-- ServiceManager

特别声明:本系列文章LiAnLab.org著作权所有,转载请注明出处。作者系LiAnLab.org资深Android技术顾问吴赫老师。本系列文章交流与讨论:@宋宝华Barry

System Service的驱动形式 --- ServiceManager

对于ServiceManager的使用,我们在应用程序编程时也会经常使用到,比如我们需要使用Sensor时,我们一般会做如下的调用:

[java]  view plain copy
  1. mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);  
  2. mSensorManager.registerListener(this, mAccelerometer,SensorManager.SENSOR_DELAY_UI);  
  3.        @Override  
  4.        public void onSensorChanged(SensorEvent event) {  
  5.            if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER)  
  6.                 return;  
  7.            ...  
  8.        }  

这样的编程模式,API说明会告诉我们,每次系统里加速度计Sensor发生状态变化时,就会触发onSensorChanged()回调方法被执行来处理Sensor的变动信息。这里就很好地说明了在系统范围内使用Service的另一种模式,就是通过getSystemService(),取回一个System Service的引用实例,然后便可以调用Service实现的方法,比如我们例子里的mSensorManager.registerListener()方法。

我们可以继承跟踪代码的实现,getSystemService()也并没有什么神奇的,它本质上只是创建一个Service列表的Cache而已,把ContextImpl.java与getSystemService()相关的实现抽出来,于是我们可以得到:

[java]  view plain copy
  1. class ContextImpl extends Context {  
  2.    ...  
  3.     static class ServiceFetcher {             4  
  4.        int mContextCacheIndex = -1;    
  5.        public Object getService(ContextImpl ctx) {      5  
  6.            ArrayList<Object> cache = ctx.mServiceCache;  
  7.            Object service;  
  8.            synchronized (cache) {  
  9.                 if (cache.size() == 0) {        
  10.                     for (int i =0; i <sNextPerContextServiceCacheIndex; i++) {  
  11.                         cache.add(null);  
  12.                     }  
  13.                 } else {  
  14.                     service =cache.get(mContextCacheIndex);  
  15.                     if (service != null) {  
  16.                         return service;  
  17.                     }  
  18.                 }  
  19.                 service = createService(ctx);  
  20.                 cache.set(mContextCacheIndex,service);  
  21.                 return service;  
  22.            }  
  23.        }         
  24.        public Object createService(ContextImpl ctx) {     6  
  25.            throw new RuntimeException("Notimplemented");  
  26.        }  
  27.     }  
  28.      
  29.     private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP  =  
  30.     new HashMap<String,ServiceFetcher>(); 2  
  31.      
  32.     private static int sNextPerContextServiceCacheIndex = 0;  
  33.     private static void registerService(String serviceName, ServiceFetcher fetcher) {           3  
  34.        if(!(fetcher instanceof StaticServiceFetcher)) {  
  35.            fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;  
  36.        }  
  37.        SYSTEM_SERVICE_MAP.put(serviceName, fetcher);  
  38.     }  
  39.      
  40.     static {  
  41.        registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {   7  
  42.            public Object getService(ContextImpl ctx) {  
  43.                returnAccessibilityManager.getInstance(ctx);  
  44.            }});  
  45.        registerService(ACTIVITY_SERVICE, new ServiceFetcher() {    8  
  46.            public Object createService(ContextImpl ctx) {  
  47.                 return newActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());  
  48. }});  
  49.        registerService(ALARM_SERVICE, new StaticServiceFetcher() {   9  
  50.            public Object createStaticService() {  
  51.                 IBinder b = ServiceManager.getService(ALARM_SERVICE);  
  52.                 IAlarmManager service =IAlarmManager.Stub.asInterface(b);  
  53.                 return new AlarmManager(service);  
  54.            }});  
  55.        ...  
  56.     }  
  57.      
  58.    @Override  
  59.     public Object getSystemService(String name) {  1  
  60.        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);  
  61.        return fetcher == null ? null : fetcher.getService(this);  
  62.     }  
  63.    ...  
  64. }}  

  1. getSystemService()的实现。所有通过继承Context类来创建自己的执行片段,都会调用getSystemService()来取得SystemService的引用。在这一方法里,就是通过SYSTEM_SERVICE_MAP来取得Service所对应的Proxy对象。
  2. SYSTEM_SERVICE_MAP,也只不过是通过String标识出来的ServiceFetcher对象而已,为了加速查找,使用了HashMap模板。
  3. 在Context对象里,会通过registerService()方法,将ServiceFetcher对象填充到SYSTEM_SERVICE_MAP里。
  4. ServiceFetcher类。这只是Context对象内,为了更好地组织Service而提供的一种中间类型,Service本身通过ServiceFetcher引用,于是可以灵活地替换其getService()或是createService()方法。
  5. 标准的getService()实现。在正常情况下,getService()只是从Cache中查找是否已经创建好所需要的Service对象,如果有则直接返回这一对象,如果没有,则创建所需要的Service对象,再返回。
  6. 标准的createService()实现。跟抽象类的实现类似,如果该ServiceFetcher上承载的Service没有覆盖createService()方法,则基本上可以认定是出错了,此抛出异常。所以ServiceFetcher在注册时,要么需要覆盖getService()方法,否则必须要覆盖更底层的createService()方法。
  7. 覆盖getService()方法。因为上层只会通过getService()方法来往下进行访问,于是覆盖了getService()方法之后,则不需要再提供createService()了。这时我们就可以理解ServiceFetcher类的作用了,在系统实现上,Service有可能会通过getService()返回其实例,比如在SingleTon模式下构建的Service。我们不需要基于Service重构,而只需要在使用它的时候通过覆盖getService()来进行灵活地重构,比如这里的AccessibilityManager.getInstance()。
  8. 覆盖createService()方法。这是更普遍的做法,每一个System Service,都会通过registerService()将createService()构造方法注册到Context环境里,这样当应用程序调用getSystemService()时,在内部实际上会通过createService()来创建一个与Service对应的Proxy对象。我们前面分析过framework的构成,这样的Proxy对象会是XXXManager的形式,于是我们实际上在createService()里会创建ActivityManager之类的对象。
  9. 覆盖createService()的另一种方法。对于System Service而言,虽然都在系统运行过程中一直存在,但有的会很忙,像Media、Audio、Graphic等,只要有Proxy,便可以响应其调用请求,有一部分则可能长期驻留后台,只是偶尔响应一下请求,比如像我们例子里看到AlarmManager。对于响应度不高的SystemService,一般都会在一个叫servicemanager的守护进程的监管之下,所以我们这里会使用Stub.asInterface()接口方法申请对象,从而保证这一Service不被调用时则可以进入休眠。

在这个整体的执行流程里,比较绕,而且深入代码分析时,我们也会看到在实现时的不一致,风格并非很严谨。但通过中间插入的这层ServiceFetcher,可以让应用程序(或是某种需要使用getSystemService()方法的系统组件)很快找到合适的ServiceProxy端的初始化方法,快速建立起跟RemoteService的通信。

除了getSystemService()方法与bindService()不同以外,在这时我们看不到两者的任何区别。当然,我们在bindService()里也会使用到onServiceConnected()回调方法异步地返回一个IBinder引用,但这也只是出于Service的生命周期考虑的结果。bindService()只是通过Intent找到合适的Service,而具体远程Service的Binder引用,则是通过onServiceConnected()。所以本质上getSystemService()与bindService()只是形式上的区别,本质上是一回事,成功调用之后便可以进行一样的RPC操作请求了。

我们可以注意到getService()与bindService()的一个重要区别,bindService()与unbindService()成对,而getService()只是单独出现。于是,bindService()这种调用机制上的Service,总是在Bounded生命周期里才能对外提供服务,可以做到按需启动,不再需要时便会在合适的时间点被关闭。而getService()所操作的Service则没有什么生命周期,永远在系统里运行并提供服务,这里也需要有种实体可以管理这些Service,当这些Service无人使用时,承载该Service的进程便会进入休眠中,这便是ServiceManager的Stub端所完成的功能。

ServiceManager在Java和Native环境里各有其实现,但在Java端实际上只有Proxy端,而Native环境里实现的servicemanager才具有完整的Proxy与Stub实现。

我们可以先来看ServiceManager.java的实现:

[java]  view plain copy
  1. public finalclass ServiceManager {  
  2.     private staticfinal String TAG = "ServiceManager";  
  3.     private static IServiceManagersServiceManager;  
  4.     private static IServiceManagergetIServiceManager() {  
  5.        if(sServiceManager != null) {  
  6.            return sServiceManager;  
  7.        }  
  8.        sServiceManager =ServiceManagerNative.asInterface(BinderInternal.getContextObject()); 2  
  9.        return sServiceManager;  
  10.     }  
  11.     public static IBindergetService(String name) {  
  12.        try {  
  13.            IBinder service = sCache.get(name);  
  14.             if (service != null) {  
  15.                 return service;  
  16.            } else {  
  17.                 returngetIServiceManager().getService(name); 1  
  18.            }  
  19.        } catch (RemoteException e) {  
  20.            Log.e(TAG, "error in getService", e);  
  21.        }  
  22.        return null;  
  23.     }  

  1. 每次通过ServiceManager的getService()方法取得一个SystemService的引用,实际上只是通过getIServiceManager()取回一个Proxy对象,然后再调用这个Proxy对象的getService()方法。
  2. getIServiceManager(),实际上则是通过IServiceManager接口,访问到一个ServiceManagerNative对象。

代码如此简洁,于是我们可以跟踪ServiceManagerNative的实现。从ServiceManagerNative类的实现上,我们也可以看到基于Binder收发两端的实现,但实际上接收端没有意义,也不会被执行到。代码如下:

[java]  view plain copy
  1. package android.os;  
  2. import java.util.ArrayList;  
  3. public abstractclass ServiceManagerNative extends Binder implements IServiceManager   1  
  4. {  
  5.     static public IServiceManagerasInterface(IBinder obj)  
  6.     {  
  7.        if(obj == null) {  
  8.            return null;  
  9.        }  
  10.        IServiceManager in =  
  11.            (IServiceManager)obj.queryLocalInterface(descriptor);  
  12.        if(in != null) {  
  13.            return in;  
  14.        }  
  15.          
  16.        return new ServiceManagerProxy(obj);   2  
  17.     }  
  18.      
  19.     publicServiceManagerNative()  
  20.     {  
  21.        attachInterface(this, descriptor);  
  22.     }  
  23.      
  24.     public boolean onTransact(int code, Parcel data,Parcel reply,int flags)  
  25.     {  
  26.           ...  
  27.     }  
  28.    
  29.     public IBinderasBinder()  
  30.     {  
  31.        return this;  
  32.     }  
  33. }  
  34.    
  35. class ServiceManagerProxy implements IServiceManager {  
  36.     publicServiceManagerProxy(IBinder remote) {  
  37.        mRemote = remote;  
  38.     }  
  39.      
  40.     public IBinderasBinder() {  
  41.        return mRemote;  
  42.     }  
  43.      
  44.     public IBindergetService(String name) throws RemoteException {  3  
  45.        Parcel data = Parcel.obtain();  
  46.        Parcel reply = Parcel.obtain();  
  47.        data.writeInterfaceToken(IServiceManager.descriptor);  
  48.        data.writeString(name);  
  49.        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);  
  50.        IBinder binder = reply.readStrongBinder();  
  51.        reply.recycle();  
  52.        data.recycle();  
  53.        return binder;  
  54.     }  
  55.    
  56.     public IBindercheckService(String name)throws RemoteException {  
  57.        …  
  58.        return binder;  
  59.     }  
  60.    
  61.     public void addService(Stringname, IBinder service,boolean allowIsolated)  
  62.            throws RemoteException {  
  63.        …  
  64.     }  
  65.      
  66.     public String[]listServices() throws RemoteException {  
  67.        ArrayList<String> services = new ArrayList<String>();  
  68.        int n = 0;  
  69.        while (true) {  
  70. …  
  71. }  
  72.        return array;  
  73.     }  
  74.    
  75.     public voidsetPermissionController(IPermissionController controller)  
  76.            throws RemoteException {  
  77.          …  
  78.     }  
  79.    
  80.     private IBindermRemote;  
  81. }  

  1. 从ServiceManagerNative,可以看到,它也是一个抽象类,继承Binder,实现IServiceManager接口。于是它必然会实现asInterface()、asBinder()等Binder所需要的接口方法。但因为它本质上只是起到Proxy作用,作为一个抽象类,它并不可能被实例化,除非有一个非抽象类继承它并实现它所缺少的方法。这种实现在代码层面上没有意义,我们从后面的分析servicemanager的Native实现时也可以看得出来,于是我们虽然看到了onTransact()实现,但实际上它不起作用。
  2. 这是整个ServiceManagerNative类实现的最有意义的一行。虽然这一行与其他基于IBinder实现的远程类没什么不同,但这一行提供了Proxy接口,这个Proxy接口,则是其他System Service所需要的访问接口。在ServiceManagerNative类的asInterface()方法里,我们会创建并返回一个Proxy对象ServiceManagerPoxy。
  3. ServiceManagerProxy对象里实现就没什么特殊之处了。跟会通过Binder访问到Remote Service的其他远程方法一样,会将本地需要调用的方法,将方法名与参数打包,将得到的命令通过Binder发送出去,然后再等着远程执行的返回。

此时,如果系统里有某种实现,在标签同是“android.os.IServiceManager”的Binder通信管道上监听,并响应getService()等方法的调用请求,这时整个基于ServiceManager的模型便完美了。我们可以继续使用ActivityManagerService实现时同样的技巧,继承ServiceManagerNative并且实现一个onTransact()所需要的响应方法,但这样的方式性能不够好,不利于频繁调用。

Java语言环境本身只是一种虚拟机环境,Java虚拟机在实现上强调的是对底层的封装,并不会提供针对操作系统的某种功能,如果我们想实现对底层的访问,则必须使用JNI来访问。比如访问Binder,如果把这样的机制通过指令或是IO拓展的方式直接嵌入到Java语言里,则会引发Android系统与Java语言的更大分裂。于是Binder本身是通过JNI拓展到Java语言里的,这样同时还达到一个高效的目的,虽然Java语言里可以访问到Binder的相应操作接口,但在底层实际上是通过C++实现的更高效的版本。既然Binder已经是C++实现,再通过JNI引入到Java环境里,我们的ServiceManager的Stub实现就没有必要到Java环境里再重复一次了,可以直接在底层将IServiceManager接口所需要的远程方法实现即可。这种方式更符合Java语法习惯、Native实现可以得到更高效ServiceManager,另外还提供了进一步实现NativeSerivce的可能性。既然底层是C++实现的,于是可以将Service的逻辑用C++写出来,再通过Binder直接暴露到应用程序层即可。

 System Service的Stub端 ---  servicemanager进程

作为IServerManager的Stub端,它所需要完成的功能是提供getService()、addService()等方法,并通过这些远程方法来控制什么状态下进程应该处于活跃状态,而什么时间点促使进进入休眠。到目前为此,它只需要给Java环境里的ServiceManager类提供服务,但稍后面我们就会看到,它也需要提供同样的服务接口给Native环境里的用C++语言编写的ServiceManager类。出于这样需求,于是干脆这一代码就用C语言来实现,以区别于使用服务的Java环境和C++环境里的对象。

ServiceManager会是一个在init.rc里定义的一个系统进程,在系统运行时全局有效。在Android系统里,唯一会与底层Binder驱动直接交互的,便是servicemanager进程(系统里其他部分,都是通过libbinder封装之后使用统一的访问模型来进行)。监听在Binder驱动 之上的servicemanager进程,相当于Android世界里的“大内总管”。一方面,系统内存在的Service,并非全局都知道,只有通过servicemanager才能查询到;另一方面,所谓的System Service也需要有一种类似于RemoteService的收发自如的执行能力,被调用时便投入运行,而没有被调用到时,虽不能被杀死掉,但也不会盲目的“空转”执行。出于这样的需求,便有servicemanager的实现框架。

无论出于什么样的设计需求,servicemanager都需要承当起service的管理功能,从一般的设计上来考察,或许这一实现会很复杂,但事实上并非如此。整个servicemanager的实现非常精练,加上binder通信的处理过程,总共不超过一千行代码,而且是使用C语言写出来的精练代码。Servicemanager的源代码位于frameworks/base/cmds/servicemanager里,通过service_manager.c实现主控部分,通过binder.c来实现与binder的通信处理过程。

既然是C语言代码,我们可以先从main()方法分析起。

[java]  view plain copy
  1. int main(int argc,char **argv)  
  2. {  
  3.     struct binder_state*bs;  
  4.     void *svcmgr =BINDER_SERVICE_MANAGER;  
  5.    
  6.     bs= binder_open(128*1024); 1  
  7.    
  8.     if(binder_become_context_manager(bs)) {    2  
  9.        ALOGE("cannot becomecontext manager (%s)\n", strerror(errno));  
  10.        return -1;  
  11.     }  
  12.    
  13.    svcmgr_handle = svcmgr;  
  14.    binder_loop(bs, svcmgr_handler);  3  
  15.     return 0;  
  16. }  

从这一个main()函数实现,我们可以看出servicemanager在实现上的简洁性。本质上,只进行了三步操作:

  1. binder_open(),在这一函数里打开了binder驱动,然后通过mmap()系统调用直接映射了binder驱动提供的128 * 1024共128K字节空间。这段空间用户态编程时并不会用到,只是一种“偷”内存的技巧,binder驱动将使用这段用户态内存,这样使用binder驱动并不占用任何系统内存,而Binder IPC所需要的内存,都存在于使用它的进程空间里,一旦进程退出,而内存随之被回收。
  2. binder_become_context_manager(),通过binder操作,标明自己是ContextManager。系统里只有有唯一的Context Manager,而成为Context Manager则拥有了调度System Service执行的能力。
  3. binder_loop()。在这一步里,就跟Java里实现的onTransact()一样,从Binder通信里取出Binder命令,并响应其请求。

这种简洁的实现,就使servicemanager这个进程有能力解析binder命令,然后根据不同命令调度不同进程进入执行时的活跃状态,或是在不再被用到时进入到休眠状态。我们把上述三个步骤打开,就可以看到这一执行过程:

1 binder_open(),

打开驱动并映射128K字节空间。在后面对binder驱动的分析我们可以看到,这是android系统里唯一一次使用这样的方式来访问binder,通过这样的方式,则servicemanager可以直接操作binder驱动来分配的一段内存,而其他进程会通过ioctl的系统调用将操作请求,从用户态拷贝到servicemanager的这段内核空间的内存。通过这种方式,减少了一次内存拷贝(servicemanager直接映射使用内核空间的binder区域)。

[java]  view plain copy
  1. struct binder_state *binder_open(unsigned mapsize)  
  2. {  
  3.     struct binder_state*bs;  
  4.    
  5.     bs= malloc(sizeof(*bs));  
  6.     if (!bs) {  
  7.        errno = ENOMEM;  
  8.        return 0;  
  9.     }  
  10.    
  11.    bs->fd = open("/dev/binder", O_RDWR);  
  12.     if (bs->fd < 0) {  
  13.        fprintf(stderr,"binder:cannot open device (%s)\n",  
  14.                 strerror(errno));  
  15.        goto fail_open;  
  16.     }  
  17.    
  18.    bs->mapsize = mapsize;  
  19.    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd,0);  
  20.     if (bs->mapped ==MAP_FAILED) {  
  21.        fprintf(stderr,"binder:cannot map device (%s)\n",  
  22.                 strerror(errno));  
  23.        goto fail_map;  
  24.     }  
  25.    
  26.        /* TODO: check version */  
  27.    
  28.     return bs;  
  29.    
  30. fail_map:  
  31.    close(bs->fd);  
  32. fail_open:  
  33.    free(bs);  
  34.     return 0;  
  35. }  

2 binder_become_context_manager(),

这就只是通过ioctl来操作一次binder驱动而已。

[java]  view plain copy
  1. int binder_become_context_manager(struct binder_state *bs)  
  2. {  
  3.     returnioctl(bs->fd, BINDER_SET_CONTEXT_MGR,0);  
  4. }  

3 binder_loop(),

这一实现复杂一点,就是循环地从binder取回binder消息,然后再通过传入的回调函数循环处理binder消息。

[cpp]  view plain copy
  1. void binder_loop(struct binder_state *bs, binder_handler func)  
  2. {  
  3.     int res;  
  4.     structbinder_write_read bwr;      1  
  5.     unsigned readbuf[32];  
  6.    
  7.    bwr.write_size = 0;  
  8.    bwr.write_consumed = 0;  
  9.    bwr.write_buffer = 0;  
  10.      
  11.    readbuf[0] = BC_ENTER_LOOPER;      2  
  12.    binder_write(bs, readbuf, sizeof(unsigned));  
  13.    
  14.     for (;;) {  
  15.        bwr.read_size = sizeof(readbuf);     3  
  16.        bwr.read_consumed = 0;  
  17.        bwr.read_buffer = (unsigned) readbuf;  
  18.    
  19.        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  
  20.    
  21.        if(res < 0) {  
  22.            ALOGE("binder_loop:ioctl failed (%s)\n", strerror(errno));  
  23.            break;  
  24.        }  
  25.        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);   4  
  26.        if(res == 0){  
  27.            ALOGE("binder_loop:unexpected reply?!\n");  
  28.            break;  
  29.        }  
  30.        if(res < 0) {  
  31.            ALOGE("binder_loop:io error %d %s\n", res, strerror(errno));  
  32.            break;  
  33.        }  
  34.     }  
  35. }  

       由于binder_loop()函数实现复杂一些,于是我们更细一点的来进行分析。从实现原理来看,它所需要做的就是循环从binder驱动读回IPC信息,然后再进行处理。于是,综合得到的具体步骤是:

  1. struct binder_write_read。在一般编程时我们见不到这样的数据结构,因为一般我们在编程上都是使用libinder封装过的Binder传输。我们可以在后面的关于Binder的描述中看到,所有的Binder通信,都是会用这样的binder_write_read结构体,再通过ioctl()系统调用将这一结构体写入binder,或是读出来。
  2. 让Binder进入读循环。BC_ENTER_LOOPER,这一个命令操作到Binder驱动上,将使用Binder在当前进程得到的文件描述符fd进入到循环监听状态,这种操作类似于TCP/IP编程时使用的bind()。需要注意的是,此时我们使用的一个32字节的readbuf,但这readbuf在这里并非用于读,而只是借用过来发命令。
  3. 此时真正开始Binder信息的读取。而由于servicemanager本身所实现的RPC很简单,只有两种,于是可以假设,在通信时数据量也会很小,于是这时只是通过binder_write_read结构体将只有32字节的read_buf通知到Binder驱动,当系统里其他任何部分调用到ServiceManager,都将迫使Binder驱动将该访问信息填写到read_buf里。
  4. binder_parse()函数则会解析读取到的Binder命令信息。我们可以看到,readbuf, bwr.read_consumed, func,这三个参数将包含binder驱动里读取到的Binder命令、命令的长度,之后会跟所有C式的调用风格一样,通过func回调方法来处理这一个Binder命令。

再看binder_parse()函数,我们可以看到Binder会循环地读取read_buf,根据不同命令作不同处理。在这个方法里,我们看到全是BR_开头的命令,在后面分析Binder运行原理时可以看到,BC是Binder Command的缩写,BC_开头的命令会全都是发出操作,而BR则是Bind Return的缩写,BR_开头的命令只会用于操作结果的返回,也就是说servicemanager进行的是被动地响应。而只有两种情况会引发后续的处理:BR_TRANSACTION,会触发Binder消息的后续处理;而BR_DEAD_BINDER,则会触发Binder相关资源的回收。

[cpp]  view plain copy
  1. int binder_parse(struct binder_state *bs,struct binder_io *bio,  
  2.                  uint32_t *ptr, uint32_t size,binder_handler func)  
  3. {  
  4.     int r = 1;  
  5.    uint32_t *end = ptr + (size / 4);  
  6.    
  7.     while (ptr < end) {  
  8.        uint32_t cmd = *ptr++;  
  9.          
  10.        switch(cmd) {  
  11.        case BR_NOOP:  
  12.            break;  
  13.        case BR_TRANSACTION_COMPLETE:  
  14.            break;  
  15.        case BR_INCREFS:  
  16.        case BR_ACQUIRE:  
  17.        case BR_RELEASE:  
  18.        case BR_DECREFS:  
  19.            ptr += 2;  
  20.            break;  
  21.        case BR_TRANSACTION: {  
  22.            struct binder_txn *txn = (void *) ptr;  
  23.            if((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {  
  24.                 return -1;  
  25.            }  
  26.            binder_dump_txn(txn);  
  27.            if(func) {  
  28.                 unsigned rdata[256/4];  
  29.                 struct binder_io msg;  
  30.                 struct binder_io reply;  
  31.                 int res;  
  32.    
  33.                 bio_init(&reply, rdata, sizeof(rdata),4);  
  34.                 bio_init_from_txn(&msg,txn);  
  35.                 res = func(bs, txn, &msg,&reply);  
  36.                 binder_send_reply(bs,&reply, txn->data, res);  
  37.            }  
  38.            ptr += sizeof(*txn) / sizeof(uint32_t);  
  39.            break;  
  40.        }  
  41.        case BR_REPLY: {  
  42.            struct binder_txn *txn = (void*) ptr;  
  43.            if((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {  
  44.                 return -1;  
  45.            }  
  46.            binder_dump_txn(txn);  
  47.            if(bio) {  
  48.                 bio_init_from_txn(bio, txn);  
  49.                 bio = 0;  
  50.            }  
  51.            ptr += (sizeof(*txn) / sizeof(uint32_t));  
  52.            r = 0;  
  53.            break;  
  54.        }  
  55.        case BR_DEAD_BINDER: {  
  56.            struct binder_death *death = (void*) *ptr++;  
  57.            death->func(bs, death->ptr);  
  58.            break;  
  59.        }  
  60.        case BR_FAILED_REPLY:  
  61.            r = -1;  
  62.            break;  
  63.        case BR_DEAD_REPLY:  
  64.            r = -1;  
  65.            break;  
  66.        default:  
  67.            ALOGE("parse: OOPS%d\n", cmd);  
  68.            return -1;  
  69.        }  
  70.     }  
  71.     return r;  
  72. }  

如果在binder_parse()函数里得到的Binder消息会是BR_TRANSACTION,我们从后面对Binder驱动的描述可以看出,此时则会是通过proxy对象发过来的命令请求。我们从名字也大概可以看出一些端倪,BR_TRANSACTION,不是Binder发送时的transact发送,这必然会是onTransact(),用来处理Binder命令的接收处理。

由于Binder在传输时会使用很严整的结构以标识其IPC传输过程,于是,在servicemanager实现里,使用了两个新的结构体用于binder消息的规整化,binder_txn与binder_io,binder_txn是binder消息的包头,跟内核态使用的binder_transaction_data结构一致,而binder_io则会进一步将binder传输时使用的buffer有效段位进一步准确地描述出来。

[cpp]  view plain copy
  1. struct binder_txn  
  2. {  
  3.    void *target;    1  
  4.    void *cookie;    2  
  5.    uint32_t code;   3  
  6.    uint32_t flags;   4  
  7.    uint32_t sender_pid;   5  
  8.    uint32_t sender_euid;  6  
  9.    uint32_t data_size;    7  
  10.    uint32_t offs_size;     8  
  11.     void *data;          9  
  12.     void *offs;           10  
  13. };  

Binder传输的是如此严整的数据结构,则在进行处理时提供了多种可能的处理功能,所以从servicemanager层面来看来,也不只是简单地将数据读出来,而会是通过不同的结构来进行消息体的解析。虽然我们在后面的binder机制分析时还将看到binder_tranaction_data结构,我们这里也看一下其含义:

  1. target本身是一种union。target在本地则会是指向对象的指针,加上,而在远端则是会是指向远程对象的引用。
  2. cookie是辅助target的附加信息,比如与target结合则具备了自动回收等后续处理能力
  3. code则是binder传输时的命令
  4. flag则是传输时指定的一些属性值,像线程优先级等
  5. sender_pid是发送Binder命令的进程的pid,可用于进程是否存在的检验
  6. sender_euid,是发送Binder命令的进程执行时使用的uid,可用于验证进程的访问权限
  7. data_size,数据区的大小信息
  8. offs_size, 数据区的偏移量信息
  9. data,指向所需要操作的buffer,或是直接是内置的最多八字节buffer
  10. offs,buffer里数据的具体偏移量

有了这样数据结构,我们对BR_TRANSACTION的处理就比较容易理解了,在servicemanager里,我们会有数据的收发处理,但对底层来说,都是binder_txn结构的数据格式,而对于上层处理,都是通过binder_io结构来完成。所以,在这时会将收到的buffer,通过bio_init_from_txn()转换成binder_io,同时准备好应答的缓冲区,通过bio_init()来规整这一缓冲区。然后这两个binder_io指向的消息体会通过回调函数func()进行处理,处理完则通过binder_send_reply()将func回调函数处理得到的应答消息写回Binder,从而通知到调用servicemanager的地方。

回过头去看binder_loop()函数,会发现其实处理binder的回调函数func,是由service_manager.c里的svcmgr_handler()函数来实现的。这样实际在底层代码也完成了抽离,binder.c实现的是Binder通用处理,而servicemanager.c实现的则是专门的ServiceManager的处理逻辑。对于svcmgr_handler(),则跟Java环境里的onTransact()区别不大了:

[cpp]  view plain copy
  1. int svcmgr_handler(struct binder_state *bs,  struct binder_txn*txn,  
  2.                    struct binder_io *msg,  struct binder_io *reply)  1  
  3. {  
  4.     struct svcinfo *si;  
  5.    uint16_t *s;  
  6.     unsigned len;  
  7.     void *ptr;  
  8.    uint32_t strict_policy;  
  9.     int allow_isolated;  
  10.    
  11.     if (txn->target !=svcmgr_handle)       2  
  12.        return -1;  
  13.    
  14.    strict_policy = bio_get_uint32(msg);     3  
  15.     s= bio_get_string16(msg, &len);  
  16.     if ((len != (sizeof(svcmgr_id) /2)) ||  
  17.        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {  
  18.         fprintf(stderr,"invalid id %s\n",str8(s));  
  19.        return -1;  
  20.     }  
  21.    
  22.     switch(txn->code) {             4  
  23.     caseSVC_MGR_GET_SERVICE:  
  24.     caseSVC_MGR_CHECK_SERVICE:      5  
  25.        s = bio_get_string16(msg, &len);  
  26.        ptr = do_find_service(bs, s, len, txn->sender_euid);  
  27.        if(!ptr)  
  28.            break;  
  29.        bio_put_ref(reply, ptr);  
  30.        return 0;  
  31.    
  32.     caseSVC_MGR_ADD_SERVICE:       6  
  33.        s = bio_get_string16(msg, &len);  
  34.        ptr = bio_get_ref(msg);  
  35.        allow_isolated = bio_get_uint32(msg) ? 1 :0;  
  36.        if(do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))  
  37.            return -1;  
  38.        break;  
  39.    
  40.     caseSVC_MGR_LIST_SERVICES: {       7  
  41.        unsigned n = bio_get_uint32(msg);  
  42.    
  43.        si = svclist;  
  44.        while ((n-- > 0) && si)  
  45.            si = si->next;  
  46.        if(si) {  
  47.            bio_put_string16(reply, si->name);  
  48.            return 0;  
  49.        }  
  50.        return -1;  
  51.     }  
  52.     default:  
  53.         ALOGE("unknown code %d\n",txn->code);  
  54.        return -1;  
  55.     }  
  56.    
  57.    bio_put_uint32(reply, 0);  
  58.     return 0;  
  59. }  

  1. svcmgr_handler()函数,就跟我们Java环境里的onTransact()方法一样,但是因为是C环境,所以都是指针作为参数,写得有点不直观。这样的编程风格,就有点C语言的进行面向对象式的编程技巧,binder_state和binder_txn用于Binder处理里上下文环境判断,而两个分别用于收发的binder_io则是相当于Message封装。
  2. 如果txn->handle,不是svcmgr_handle,也就是0,则属于非法的servicemanager调用,于是直接退出。
  3. 在这里我们可以体会C语言的面向对象式技巧,这里取出要处理的binder_io里的信息,并不是直接使用字符串指针操作,而是通过bio_get_*系列的封装,类似于Java语言里的Getter/Setter。于是,在这里我们进一步对数据包的合法性进行验证。
  4. 跟onTransact()方法一样,这里会使用switch语句来判断命令是哪一种,我们可以看到servicemanager实际上很简单,只需要支持三种型的Binder命令:get|check_service、add_service、list_service。
  5. SVC_MGR_GET_SERVICE和SVC_MGR_CHECK_SERVICE。虽然他们是两个不同binder命令,但对于底层来说是一回,通过get_sevice成功,我们可以给check_service一个是否可以正常运行的应答。这一般会被使用service的部分来获得Service的引用,对于内部实现来说,它只是在自己维护的一个svcinfo的单链表里找到合适的service来响应服务请求。
  6. SVC_MGR_ADD_SERVICE。与get_service相反,这一命令则是将传过来的service信息添加到svcinfo的链表里,然后get_service就可以被访问到。
  7. SVC_MGR_LIST_SERVICE。这一命令会将自己维护的svcinfo链表遍历一次,然后将所保存的service信息返回给调用端。

通过引入servicemanager这样一种机制,在我们系统设计上就得到方便,我们不再需要系统内部的bindService(),但又提供了类似于bindService()这样按需启动的功能。我们在系统里实现的一个Remote Service,也就是SystemService,在它启动时会调用add_service()函数将自己加入到servicemanager的svcinfo链表里,然后进入休眠。虽然大部分情况下,我们都是使用Java来实现System Service,但由于在实现上是Java端发送Binder命令,Native端实现的servicemanager进程来接收并处理Binder命令,于是本质上是一回事。serviamanger维护了svcinfo链表之后,实际上service在没有被用到时,都是在休眠状态。客户端则可以通过get_service()来发送Binder消息到servicemanager,此时servicemanager会告诉客户端该service是否存在,并且在存在的情况下,返回service的IBinder引用到客户端,并同时唤醒service,于是后续的流程上,客户端就可以直接通过IBinder引用(也就是通过asInterface()方法得到的Proxy对象),直接跟service进行RPC交互了。如图所示:


在某个Service对象完成自己的初始化后,就会调用add_service(),将自己加入到Service列表,然后就会在Binder驱动上休眠。应用程序会调用get_service(),尝试跟某个SystemService建立交互,此时也在Binder驱动上休眠。当servicemanager做完合法性判断之后,则会唤醒收发两端的进程进入到交互过程里。从这个意义上来说,servicemanager虽然代码如此简单,但也起到了“大内总管”的职能,会管理System Service,并在合适点唤醒它们投入执行。

既然一个简单的Service Manager,调用频度不那么高,也会直接通过C这样的Native语言来编写,get_service()/add_service()的调用频度比Binder通信要低多了,那我们Binder通信本身也应该使用native实现了。另外,Java语言本身并不知道Binder的存在,为了支持Binder这种特殊的IPC,我们也应该使用Native编码来导入Binder IPC通信,问题在于Native的程度会有多深。出于频率上的考虑,Binder通信大部分都使用Native实现,只是给Java环境提供一层封装,供Java环境直接使用,这就是libbinder,由frameworks/base/libs/binder来实现。从Android 4.1开始,为了使NDK与Native实现兼容,这一目录已经换至frameworks/native/libs/binder,与NDK环境共享。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值