前面的几节中我们介绍了Native层Binder通讯的原理和用法,那么在Java层如何使用Binder通讯呢?其原理又与Native层的Binder有什么关系呢?
与Native层的ServiceManager类似,Android在Java层也有一个ServiceManager用于处理Java层Service的注册、申请。只不过,Java层的这个ServiceManager,其实是在Java层建立的ServiceManager的代理,他把Java层客户端的各项请求传递到Native层的ServiceManager进行处理。
而对于其他Java层的Service来说,客户端得到的Service远程代理对象,就是Native层得到的BpXXXService对象。
接下来我们分四部分来介绍Java层Binder机制:
1、ServiceManager的结构;
2、如何注册一个Service;
3、如何得到一个Service;
4、Service代理对象方法的过程;
一、ServiceManager的结构
我们来看一下ServiceManager类的代码:- @ServiceManager.java(google-code\frameworks\base\core\java\android\os\ServiceManager.java)
- public final class ServiceManager {
- private static IServiceManager getIServiceManager() {
- }
- public static IBinder getService(String name) {
- }
- public static void addService(String name, IBinder service) {
- }
- public static void addService(String name, IBinder service, boolean allowIsolated) {
- }
- public static IBinder checkService(String name) {
- }
- public static String[] listServices() throws RemoteException {
- }
- public static void initServiceCache(Map<String, IBinder> cache) {
- }
- }
这个类比较简单,而且我们看到,ServiceManager没有继承任何的类,那么他是如何实现“管理员”的角色呢?
二、如何在Java层通过ServiceManager注册一个Service
Android启动时,将会在SystemServer中的ServerThread线程中将一些重要的Java层Service注册并启动,我们在这里挑选负责状态栏管理的StatusBarManagerService来分析。- @SystemServer.java(google-code\frameworks\base\services\java\com\android\server\SystemServer.java)
- class ServerThread extends Thread {
- @Override
- public void run() {
- try {
- statusBar = new StatusBarManagerService(context, wm);
- //调用ServiceManager注册服务
- ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
- } catch (Throwable e) {
- reportWtf("starting StatusBarManagerService", e);
- }
- }
- }
我们来看ServiceManager的addService()方法:
- @ServiceManager.java
- public static void addService(String name, IBinder service) {
- try {
- getIServiceManager().addService(name, service, false);
- } catch (RemoteException e) {
- Log.e(TAG, "error in addService", e);
- }
- }
- private static IServiceManager sServiceManager;
- private static IServiceManager getIServiceManager() {
- if (sServiceManager != null) {
- //单例模式
- return sServiceManager;
- }
- //得到ServiceManager的Java层代理对象
- sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
- return sServiceManager;
- }
其实 我们通过getIServiceManager()得到的就是Java层中的ServiceManager的代理对象ServiceManagerProxy 。为了得到这个对象,我们需要经过两步的准备:
1、通过Native层的调用得到ServiceManager的远程对象BpBinder
----也就是BinderInternal.getContextObject()的操作
2、把ServiceManager的BpBinder封装为Java层可用的ServiceManagerProxy对象
----也就是ServiceManagerNative().asInterface()的操作
下面我们来详细分析这两个步骤
2.1、得到ServiceManager的BpBinder对象过程
这一步中我们将会看到, 如何通过BinderInternal.getContextObject()得到ServiceManager的BpBinder()对象 ,下面我们来看这个方法的声明:- @BinderInternal.java(google-code\frameworks\base\core\java\com\android\internal\os\BinderInternal.java)
- public static final native IBinder getContextObject();
我们简单来说一下流程。
在Java虚拟机启动时,将会注册一系列的native方法
- @AndroidRuntime.cpp(google-code\frameworks\base\core\jni\AndroidRuntime.cpp)
- void AndroidRuntime::start(const char* className, const char* options) {
- //开始注册方法
- if (startReg(env) < 0) {
- return;
- }
- }
- int AndroidRuntime::startReg(JNIEnv* env) {
- //注册gRegJNI列表中的jni方法
- if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
- env->PopLocalFrame(NULL);
- return -1;
- }
- return 0;
- }
- static const RegJNIRec gRegJNI[] = {
- REG_JNI(register_android_os_Binder),
- };
- @android_util_Binder.cpp(google-code\frameworks\base\core\jni\android_util_Binder.cpp)
- int register_android_os_Binder(JNIEnv* env) {
- //注册BinderInternal中的jni
- if (int_register_android_os_BinderInternal(env) < 0)
- return -1;
- return 0;
- }
- static int int_register_android_os_BinderInternal(JNIEnv* env) {
- jclass clazz;
- //根据路径找到类
- clazz = env->FindClass(kBinderInternalPathName);
- gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
- gBinderInternalOffsets.mForceGc = env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
- //注册gBinderInternalMethods中的jni
- return AndroidRuntime::registerNativeMethods(
- env, kBinderInternalPathName,
- gBinderInternalMethods, NELEM(gBinderInternalMethods));
- }
- static const JNINativeMethod gBinderInternalMethods[] = {
- { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
- { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
- { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
- { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
- };
- static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) {
- //得到BpBinder(0)对象
- sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
- //将BpBinder对象转换为Java对象
- return javaObjectForIBinder(env, b);
- }
1、通过ProcessState的getContextObject(NULL)得到了ServiceManager的BpBinder(0)对象 (详细过程在《Binder源码分析之Native层》中做过详细介绍)。
2、通过javaObjectForIBinder()方法把得到的BpBinder对象封装成Java层可用的类型 。
至此,我们就拿到了Java层可用的ServiceManager的BpBinder对象, 下面要做的就是把该对象转换为Java层可用的ServiceManager代理对象 。
2.2、用BpBinder得到ServiceManagerProxy对象过程
我们在第二节刚开始的地方介绍过,Service注册自己的时候需要在ServiceManager中通过getIServiceManager()方法得到ServiceManager在Java层的代理对象,然后调用该对象的addService()方法完成注册:- private static IServiceManager getIServiceManager() {
- if (sServiceManager != null) {
- //单例模式
- return sServiceManager;
- }
- //得到ServiceManager的Java层代理对象
- sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
- return sServiceManager;
- }
也就是说,当前的getIServiceManager()相当于:
- private static IServiceManager getIServiceManager() {
- //得到ServiceManager的Java层代理对象
- sServiceManager = ServiceManagerNative.asInterface(BpBinder(0));
- return sServiceManager;
- }
- @ServiceManagerNative.java(google-code\frameworks\base\core\java\android\os\ServiceManagerNative.java)
- 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);
- }
也就是说, 通过getIServiceManager()得到的sServiceManager对象,其实是ServiceManagerProxy对象 。
2.3、ServiceManagerProxy对象
我们先来看一下其继承结构:- class ServiceManagerProxy implements IServiceManager {}
然后再来看其构造函数,在2.2中介绍过,创建ServiceManagerProxy对象时,是用ServiceManager的BpBinder对象作为参数的:
- public ServiceManagerProxy(IBinder remote) {
- mRemote = remote;
- }
下面我们来看ServiceManagerProxy中的方法:
- class ServiceManagerProxy implements IServiceManager {
- public ServiceManagerProxy(IBinder remote) {
- }
- public IBinder asBinder() {
- }
- public IBinder getService(String name) throws RemoteException {
- }
- public IBinder checkService(String name) throws RemoteException {
- }
- public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
- }
- public String[] listServices() throws RemoteException {
- }
- public void setPermissionController(IPermissionController controller) throws RemoteException {
- }
- }
2.4、注册Service的过程
经过以上的分析,我们知道通过getIServiceManager()的调用,我们得到的是ServiceManagerProxy对象,那么当注册Service时调用的addService()方法就会调用到ServiceManagerProxy中:- public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- data.writeStrongBinder(service);
- data.writeInt(allowIsolated ? 1 : 0);
- mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
- reply.recycle();
- data.recycle();
- }
- @BpBinder.cpp
- status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- if (mAlive) {
- //进入IPCThreadState继续调用
- status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);
- if (status == DEAD_OBJECT) mAlive = 0;
- return status;
- }
- return DEAD_OBJECT;
- }
经过以上的分析,我们对Java层ServiceManager有了全新的认识, 简单来说,Java层的ServiceManager就是Native层ServiceManager的一个Client,而对于Java层其他Service来说,Java层的ServiceManager又是一个Service,负责把其他Client的请求转发给Native层的ServiceManager去处理 。
而ServiceManagerProxy又是Java层ServiceManager的代理,其负责将Java层其他客户端对ServiceManager的调用传递给Native层的ServiceManager。
下面用一张图来示意Java层ServiceManager和Native层ServiceManager的关系:
三、客户端如何得到一个Service
前面分析了如何在Java层注册一个Service,下面我们来分析,如何在Java层得到某个Service服务。这一次我们挑选simphonebook这个Service来分析,先简单来看一下其注册成为Service的过程:
- @IccPhoneBookInterfaceManagerProxy.java(google-code\frameworks\opt\telephony\src\java\com\android\Internal\telephony\)
- public IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager iccPhoneBookInterfaceManager) {
- mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
- if(ServiceManager.getService("simphonebook") == null) {
- ServiceManager.addService("simphonebook", this);
- }
- }
我们来看IccPhoneBookInterfaceManagerProxy这个类的继承关系:
- public class IccPhoneBookInterfaceManagerProxy extends IIccPhoneBook.Stub {}
我们在代码中找不到IIccPhoneBook.Stub的文件或类,但是找到了IIccPhoneBook.aidl文件,这个文件的作用又是什么呢?
原来,这里的 AIDL文件是Android中定义的接口语言(Android Interface Definition Language)。开发者只要按照指定的格式创建AIDL文件,系统就会自动为该文件生成一个对应的Java文件 。
假如我们创建一个IMyService.aidl文件,其内容为:
- @IMyService.aidl
- package com.pack;
- interface IMyService{
- String getValue();
- }
- @IMyService.java
- package com.pack;
- public interface IMyService extends android.os.IInterface {
- //Stub继承自Binder,并且实现了IMyService的接口
- public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {
- }
- }
- @Binder.java(google-code\frameworks\base\core\java\android\os\)
- public class Binder implements IBinder{}
- @IccProvider.java(google-code\frameworks\opt\telephony\src\java\com\android\internal\telephony\)
- private boolean addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {
- boolean success = false;
- try {
- //得到simphonebook的Service
- IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
- if (iccIpb != null) {
- //添加SIM卡联系人
- success = iccIpb.updateAdnRecordsInEfBySearch(efType, "", "", name, number, pin2);
- }
- } catch (RemoteException ex) {
- } catch (SecurityException ex) {
- }
- return success;
- }
下面我们将上述动作分解为3步来分析:
1、通过ServiceManager得到simphonebook的BpBinder对象
2、通过asInterface()方法得到simphonebook这个Service的Java层代理对象
3.1、通过ServiceManager得到simphonebook的BpBinder对象
在这一步中,我们来分析ServiceManager.getService("simphonebook")的过程。我们先来看ServiceManager的getService()方法:
- @ServiceManager.java
- public static IBinder getService(String name) {
- try {
- IBinder service = sCache.get(name);
- if (service != null) {
- return service;
- } else {
- //调用的是getIServiceManager()对象的getService()方法
- return getIServiceManager().getService(name);
- }
- } catch (RemoteException e) {
- }
- return null;
- }
- private static IServiceManager getIServiceManager() {
- if (sServiceManager != null) {
- return sServiceManager;
- }
- //通过getIServiceManager得到的其实是ServiceManager的Java层代理对象
- sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
- return sServiceManager;
- }
那么调用该代理对象的getService()方法将会得到什么呢?
- @ServiceManagerNative.java
- class ServiceManagerProxy implements IServiceManager {
- //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就是ServiceManager的BpBinder对象
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
- }
也就是说, 经过Java层的ServiceManager.getService("simphonebook")操作,我们得到了simphonebook这个Service的BpBinder对象 。
3.2、通过asInterface()方法得到simphonebook这个Service的Java层代理对象
经过3.1的过程,我们得到了simphonebook的BpBinder对象,接下来我们将要分析,如何通过该对象得到simphonebook这个Service的Java层可用的代理对象。我们先将代码简化一下:
- IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
- IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(BpBinder("simphonebook"));
- @IMyService.java
- public interface IMyService extends android.os.IInterface {
- public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {
- public static com.pack.IMyService asInterface(android.os.IBinder obj) {
- if ((obj == null)) {
- return null;
- }
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (((iin != null) && (iin instanceof com.pack.IMyService))) {
- return ((com.pack.IMyService) iin);
- }
- //通过asInterface()得到的是Proxy对象,并且把BpBinder对象作为参数传递进去
- return new com.pack.IMyService.Stub.Proxy(obj);
- }
- //代理类Proxy继承自IMyService.aidl,需要实现里面的所有接口
- private static class Proxy implements com.pack.IMyService {
- private android.os.IBinder mRemote;
- //保存得到的BpBinder对象
- Proxy(android.os.IBinder remote) {
- mRemote = remote;
- }
- @Override
- public java.lang.String getValue() throws android.os.RemoteException {
- }
- }
- static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- }
- public java.lang.String getValue() throws android.os.RemoteException;
- }
把IMyService换成IIccPhoneBook,我们可以推测,通过IIccPhoneBook.Stub.asInterface(BpBinder)的操作,我们得到的是iccIpb.Stub的内部类Proxy对象,而且在这个类的内部拥有IIccPhoneBook.aidl文件定义的接口。 客户端可以把这个代理类当作服务端对象一样去调用AIDL中定义的所有方法 。
下面我们用图来总结一下客户端得到服务端的过程:
四、客户端调用Service方法的过程
经过3.2节的分析我们知道,通过IIccPhoneBook.Stub.asInterface()我们得到了一个服务端的代理对象:IIccPhoneBook.Stub.Proxy,我们可以直接调用IIccPhoneBook.aidl中定义的接口,那么这个代理类如何把接口的调用传递给服务端呢?服务器又是如何把数据返回给客户端的呢?现在我们先借用IMyService去分析其调用过程,最后再把过程扩大到其他的Java层Service调用过程中。
假如客户端调用了IMyService.aidl中的getValue()方法(我们的IMyService.aidl文件中只有这一个方法),那么就会调用到Proxy类的内部:
- private static class Proxy implements com.pack.IMyService {
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote) {
- mRemote = remote;
- }
- @Override
- public java.lang.String getValue() throws android.os.RemoteException {
- //准备Parcel数据
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- java.lang.String _result;
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- //调用mRemote的transact()方法发送数据,并且标记当前调用的方法为getValue
- mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);
- //提取服务端的返回值
- _reply.readException();
- _result = _reply.readString();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
- }
还记得在创建Proxy类的时候我们是把目标Service的BpBinder对象传递给了mRemote变量,那么这里的transact()就会调用到BpBinder中:
- @BpBinder.cpp
- status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- if (mAlive) {
- //向Service发送请求
- status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags);
- if (status == DEAD_OBJECT) mAlive = 0;
- return status;
- }
- return DEAD_OBJECT;
- }
而根据《Binder源码分析之Native层》中的分析,服务端在接收到客户端请求后,最终会调用到服务端父类BBinder的transact()方法:
- @Binder.cpp
- status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- status_t err = NO_ERROR;
- switch (code) {
- case PING_TRANSACTION:
- reply->writeInt32(pingBinder());
- break;
- default:
- //调用BBinder的子类去处理当前请求
- err = onTransact(code, data, reply, flags);
- break;
- }
- return err;
- }
- public interface IMyService extends android.os.IInterface {
- public static abstract class Stub extends android.os.Binder implements com.pack.IMyService {
- public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
- switch (code) {
- case INTERFACE_TRANSACTION: {
- reply.writeString(DESCRIPTOR);
- return true;
- }
- case TRANSACTION_getValue: {
- //客户端发起的getValue()的请求
- data.enforceInterface(DESCRIPTOR);
- //继续调用子类的getValue()方法
- java.lang.String _result = this.getValue();
- reply.writeNoException();
- reply.writeString(_result);
- return true;
- }
- }
- return super.onTransact(code, data, reply, flags);
- }
- static final int TRANSACTION_getValue = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- }
- public java.lang.String getValue() throws android.os.RemoteException;
- }
那么,当客户端调用的方法需要返回值时,服务端是如何把返回值传回给客户端的呢?
我们还来看getValue()的过程,这个方法当然需要服务端提供返回值,因此在onTransact()调用到子类的this.getValue()时,就会得到服务端的返回值,接下来我们看到,在TRANSACTION_getValue分支中会把返回值(_result)放入reply中,接着就结束了onTransact()的调用。
也就是说, 在服务端的onTransact()过程中,不仅完成了对服务端的调用,而且也带回来了服务端的返回值,这个返回值是通过onTransact()的参数传递出去的 。
然后当BBinder的onTransact()结束后,就返回到了BBinder的transact()操作中,接着再层层返回,并经过Native层Binder的传输,再次回到BpBinder的transact()中,然后等BpBinder的transact()返回后,我们就再次回到了IMyService.java中的getValue()方法:
- public java.lang.String getValue() throws android.os.RemoteException {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- java.lang.String _result;
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- //经历了一次漫长的跨进程调用过程
- mRemote.transact(Stub.TRANSACTION_getValue, _data, _reply, 0);
- _reply.readException();
- _result = _reply.readString();
- } finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
如果结合这IIccPhoneBook来分析,此时的调用将会从IIccPhoneBook.Stub中返回到其子类中也就是IccProvider中,从而完成了客户端的调用过程。
也就是说, 我们在IccProvider对客户端的调用经过IIccPhoneBook传递到Native层,然后又经过IccProvider传递给Service的实现者IccPhoneBookInterfaceManagerProxy。完成请求后,再经过逆过程回到IccProvider客户端中 。
这就是Java层的Binder调用过程。
最后,用一张图来示意客户端调用服务端的过程: