Binder应用实例
前一篇文章我们从进程的C/C++层面讲解了binder机制的服务代理对象BpBinder的获取,和Binder底层处理方法。整个服务代理的获取过程也是binder机制的的核心内容,它涉及到了客户请求,请求的传递和处理,服务代理的生成和转换(封装)过程。当客户端获取到对应服务的代理后,就可以通过这个服务代理和服务端通讯了。
本文我们将以binder机制在android中的应用实例,来分析客户端与服务器端的通讯整个流程。不过,在介绍实例前,我们还要花点时间来分析一下binder机制在进程的Java层面服务代理对象的创建和使用。
(一)binder机制中的Java层
我们知道Android中的应用程序基本上都是java开发,对Android的框架了解的朋友都知道,Java的本地实现都是通过JNI层的接口来调用C++/C代码的,这里也不例外。在android的binder机制中,Java层面的binder机制的应用,你可以简单看作是底层binder机制的封装。
Binder客户程序的C/C++层面的对象和原理我们在前面我们已经学习过,下面我们将介绍客户程序怎样在Java层面通过JNI调用底层C/C++代码的创建服务代理的。
(1)ServiceManager类型和对象
我们都知道,作为客户端要想获得服务代理,首先要向ServiceManager查询Service,然后创建并返回服务代理对象,再通过代理对象和Service通讯。当然,在Java层面也是这样,所以客户端首先也要获取ServiceManager这个系统服务的服务代理,再同这个代理来查询并请求服务,所以我们首先分析Java层面ServiceManager类。
Framework\base\core\android\os\ServiceManager.java
public final class ServiceManager {
private static final String TAG = "ServiceManager";
private static IServiceManager sServiceManager;
……
}
上面是ServiceManager类定义,可以看出来ServiceManager也是一个Singleton类型。(成员函数代码暂不贴出来,可以参考源码)所有的方法都是静态方法,包括上面的sServiceManager成员变量(这意味着所有的ServiceManager对象,共享这个变量)。而所有静态方法都是通过调用它的IServiceManager类型的静态变量sServiceManager来实现的。
所以可以理解ServiceManager就是IServiceManager对象的一个代理,它就是一个对sServiceManager封装的一个类。因为创建和访问这个变量都是通过ServiceManager的getIServiceManager方法,定义如下:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
sServiceManager是一个IserviceManager类型,如果它已经创建,就直接返回,否则,创建并返回。当然第一次进入这个函数,是要创建的了,下面就来看看它的具体创建过程吧!
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
还是老规矩,首先分析asInterface的参数BinderInternal.getContextObject(),哇,好长的参数,必须把丫解了。看到BinderInternal没有,这是什么呢?呵呵,用鼠标就知道了(用source insight的都知道)。
Framework\base\core\com\java\android\os\BinderInternal.java
public class BinderInternal {
……
/**
* Return the global "context object" of the system. This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();
……
}
这里可以看到BinderInternal类的getContextObject方法的代码,惊奇的发现是Native代码,这不就是Java的本地接口嘛!这下好了,它通过调用JNI层的某个文件的代码(而且是C++的代码),来和底层的C++/C实现挂钩。至于它怎么和JNI层的的函数对应的调用的,我相信你早已心知肚明了,这里不做介绍。
BinderInternal类中的本地接口的JNI实现文件,就是android_util_binder.cpp文件,getContextObject方法在该文件中对应的函数是android_os_BinderInternal_getContextObject函数,代码如下:
Framework\base\core\jni\android_util_binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
还记得这个ProcessState对象吗?就是那个管理整个进程的服务代理对象的那个玩意,一个进程只能有一个该类对象的。既然它管理服务代理对象,那这个服务代理对象创建也应该跟她有关系了,事实上,从前文的分析已经看出来的却是这样。虽然前文已经有所述,这里再加强下记忆吧,我们再去查看ProcessState对象的getContextObject方法,代码如下:
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
就是这里,我们看到在当前进程的ProcessState对象,其实是调用getStrongProxyForHandle方法,来创建binder句柄为0的服务代理对象——BpBinder对象的,我们知道ServiceManager的binder句柄就是这个个闻名句柄0。
哦,这里不又是回到前文的内容里了嘛!再说一边就没有意思了,如果忘记了,可以回头看看,呵呵,还是要“经常回头看看自己走过的路。”
我们可以看出Java调用C/C++,创建一个服务代理对象BpBinder,在查看BpBinder的定义我们发现继承自IBinder接口,然后在android_util_binder.cpp中的方法android_os_BinderInternal_getContextObject中,把C/C++层面的IBinder对象封装成Java层面的IBinder对象。
至此我们已经清楚BinderInternal.getContextObject(),返回的是ServiceManager的服务代理对象——BpBinder对象。那么ServiceManagerNative类的静态方法asInterface做什么用呢?这个貌似和我们前面讲过的内容不太一样。还记得在C/C++层面的获取服务代理的流程吧,在创建了一个BpBinder代理对象后,是不是通过一个类型转换函数将这个代理对象转换成了IserviceManager对象(当然,这里是C++类的对象),我们还重点分析了那个转换函数,其实你知道的,那是个宏定义:
gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL)); //创建代理对象
就是这段代码,既然也走到了这里,他们的参数一样,唯一不同的就是这个主体函数喽!那么我们Java层面的这段代码:
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
是不是也