在前面几篇文章中,我们详细介绍了 Android 系统进程间通信机制 Binder 的原
理,并且深入分析了系统提供的 Binder 运行库和驱动程序的源代码。细心的读者会
发现,这几篇文章分析的 Binder 接口都是基于 C/C++语言来实现的,但是我们在编
写应用程序都是基于 Java 语言的,那么,我们如何使用 Java 语言来使用系统的 Binder
机制来进行进程间通信呢?这就是本文要介绍的 Android 系统应用程序框架层的用
Java 语言来实现的 Binder 接口了。
熟悉 Android 系统的读者,应该能想到应用程序框架中的基于 Java 语言的 Binder
接口是通过 JNI 来调用基于 C/C++语言的 Binder 运行库来为 Java 应用程序提供进程
间通信服务的了。JNI 在 Android 系统中用得相当普遍,SDK 中的 Java 接口 API 很
多只是简单地通过 JNI 来调用底层的 C/C++运行库从而为应用程序服务的。
这里,我们仍然是通过具体的例子来说明 Binder 机制在应用程序框架层中的
Java 接口,主要就是 Service Manager、Server 和 Client 这三个角色的实现了。通常,
在应用程序中,我们都是把 Server 实现为 Service 的形式,并且通过
接口来把这个 Service 添加到 Service Manager,Client 也
是通过 接口来获得 Service 接口,接着就可以使用这个
Service 提供的功能了,这个与运行时库的 Binder 接口是一致的。
前面我们学习 Android 硬件抽象层时,曾经在应用程序框架层中提供了一个硬
件访问服务 HelloService,这个 Service 运行在一个独立的进程中充当 Server 的角色,
使用这个 Service 的 Client 运行在另一个进程中,它们之间就是通过 Binder 机制来
通信的了。这里,我们就使用 HelloService 这个例子来分析 Android 系统进程间通
信 Binder 机制在应用程序框架层的 Java 接口源代码。所以希望读者在阅读下面的内
容之前,先了解一下前面在 Ubuntu 上为 Android 系统的 Application Frameworks 层
增加硬件访问服务这篇文章。
这篇文章通过五个情景来学习 Android 系统进程间通信 Binder 机制在应用程序
框架层的 Java 接口:1. 获取 Service Manager 的 Java 远程接口的过程;2. HelloService
接口的定义;3. HelloService 的启动过程;4. Client 获取 HelloService 的 Java 远程接
口的过程;5. Client 通过 HelloService 的 Java 远程接口来使用 HelloService 提供的
服务的过程。
一. 获取 Service Manager 的 Java 远程接口
我们要获取的 Service Manager 的 Java 远程接口是一个 ServiceManagerProxy 对
象的 IServiceManager 接口。我们现在就来看看 ServiceManagerProxy 类是长什么样
子的:
这里可以看出,ServiceManagerProxy 类实现了 IServiceManager 接口,
IServiceManager 提供了 getService 和 addService 两个成员函数来管理系统中的
Service。从 ServiceManagerProxy 类的构造函数可以看出,它需要一个 BinderProxy
对象的 IBinder 接口来作为参数。因此,要获取 Service Manager 的 Java 远程接口
ServiceManagerProxy,首先要有一个 BinderProxy 对象。下面将会看到这个
BinderProxy 对象是如何获得的。
再来看一下是通过什么路径来获取 Service Manager 的 Java 远程接口
ServiceManagerProxy 的。这个主角就是 ServiceManager 了,我们也先看一下
ServiceManager 是长什么样子的:
ServiceManager 类有一个静态成员函数 getIServiceManager,它的作用就是用来
获取 Service Manager 的 Java 远程接口了,而这个函数又是通过 ServiceManagerNative
来获取 Service Manager 的 Java 远程接口的。
接下来,我们就看一下 这个函数的实现,这
个函数定义在 frameworks/base/core/java/android/os/ 文件中:
view plain
1. public final class ServiceManager {
2. ......
3. private static IServiceManager sServiceManager;
4. ......
5. private static IServiceManager getIServiceManager() {
6. if (sServiceManager != null) {
7. return sServiceManager;
8. }
9.
10. // Find the service manager
11. sServiceManager = (());
12. return sServiceManager;
13. }
14. ......
15. }
如果其静态成员变量 sServiceManager 尚未创建,那么就调用
函数来创建。在调用
函数之前,首先要通过
函数来获得一个 BinderProxy 对象。
我们来看一下 的实现,这个函数定义在
frameworks/base/core/java/com/android/internal/os/ 文件中:
view plain
1. public class BinderInternal {
2. ......
3. /**
4. * Return the global "context object" of the system. This is usually
5. * an implementation of IServiceManager, which you can use to find
6. * other services.
7. */
8. public static final native IBinder getContextObject();
9.
10. ......
11. }
这里可以看出, 是一个 JNI 方法,它实现在
frameworks/base/core/jni/ 文件中:
view plain
1. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
2. {
3. sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
4. return javaObjectForIBinder(env, b);
5. }
这里看到我们熟悉的 ProcessState::self()->getContextObject 函数,具体可以参考
浅谈 Android 系统进程间通信(IPC)机制 Binder 中的 Server 和 Client 获得 Service
Manager 接口之路一文。ProcessState::self()->getContextObject 函数返回一个 BpBinder
对象,它的句柄值是 0,即下面语句:
view plain
1. sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
相当于是:
view plain
1. sp<IBinder> b = new BpBinder(0);
接着调用 javaObjectForIBinder 把这个 BpBinder 对象转换成一个 BinderProxy 对
象:
view plain
1. jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
2. {
3. if (val == NULL) return NULL;
4.
5. if (val->checkSubclass(&gBinderOffsets)) {
6. // One of our own!
7. jobject object = static_cast<JavaBBinder*>(())->object();
8. //printf("objectForBinder %p: it's our own %p!\n", (), object);
9. return object;
10. }
11.
12. // For the rest of the function we will hold this lock, to serialize
13. // looking/creation of Java proxies for native Binder proxies.
14. AutoMutex _l(mProxyLock);
15.
16. // Someone else's... do we know about it?
17. jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
18. if (object != NULL) {
19. jobject res = env->CallObjectMethod(object, );
20. if (res != NULL) {
21. LOGV("objectForBinder %p: found existing %p!\n", (), res);
22. return res;
23. }
24. LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, ());
25. android_atomic_dec(&gNumProxyRefs);
26. val->detachObject(&gBinderProxyOffsets);
27. env->DeleteGlobalRef(object);
28. }
29.
30. object = env->NewObject(, );
31. if (object != NULL) {
32. LOGV("objectForBinder %p: created new %p!\n", (), object);
33. // The proxy holds a reference to the native object.
34. env->SetIntField(object, , (int)());
35. val->incStrong(object);
36.
37. // The native object needs to hold a weak reference back to the
38. // proxy, so we can retrieve the same proxy if it is still active.
39. jobject refObject = env->NewGlobalRef(
40. env->GetObjectField(object, ));
41. val->attachObject(&gBinderProxyOffsets, refObject,
42. jnienv_to_javavm(env), proxy_cleanup);
43.
44. // Note that a new object reference has been created.
45. android_atomic_inc(&gNumProxyRefs);
46. incRefsCreated(env);
47. }
48.
49. return object;
50. }
在介绍这个函数之前,先来看两个变量 gBinderOffsets 和 gBinderProxyOffsets 的
定义。
先看 gBinderOffsets 的定义:
view plain
1. static struct bindernative_offsets_t
2. {
3. // Class state.
4. jclass mClass;
5. jmethodID mExecTransact;
6.
7. // Object state.
8. jfieldID mObject;
9.
10. } gBinderOffsets;
简单来说,gBinderOffsets 变量是用来记录上面第二个类图中的 Binder 类的相关
信息的,它是在注册 Binder 类的 JNI 方法的 int_register_android_os_Binder 函数初始
化的:
view plain
1. const char* const kBinderPathName = "android/os/Binder";
2.
3. static int int_register_android_os_Binder(JNIEnv* env)
4. {
5. jclass clazz;
6.
7. clazz = env->FindClass(kBinderPathName);
8. LOG_FATAL_IF(clazz == NULL, "Unable to find class ");
9.
10. = (jclass) env->NewGlobalRef(clazz);
11.
12. = env->GetMethodID(clazz, "execTransact", "(IIII)Z");
13. assert();
14.
15.
16. = env->GetFieldID(clazz, "mObject", "I");
17. assert();
18.
19. return AndroidRuntime::registerNativeMethods(
20. env, kBinderPathName,
21. gBinderMethods, NELEM(gBinderMethods));
22. }
再来看 gBinderProxyOffsets 的定义:
view plain
1. static struct binderproxy_offsets_t
2. {
3. // Class state.
4. jclass mClass;
5. jmethodID mConstructor;
6. jmethodID mSendDeathNotice;
7.
8. // Object state.
9. jfieldID mObject;
10. jfieldID mSelf;
11.
12. } gBinderProxyOffsets;
简单来说,gBinderProxyOffsets 是用来变量是用来记录上面第一个图中的
BinderProxy 类的相关信息的,它是在注册 BinderProxy 类的 JNI 方法的
int_register_android_os_BinderProxy 函数初始化的:
view plain
1. const char* const kBinderProxyPathName = "android/os/BinderProxy";
2.
3. static int int_register_android_os_BinderProxy(JNIEnv* env)
4. {
5. jclass clazz;
6.
7. clazz = env->FindClass("java/lang/ref/WeakReference");
8. LOG_FATAL_IF(clazz == NULL, "Unable to find class ");
9. = (jclass) env->NewGlobalRef(clazz);
10.
11. = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;");
12. assert();
13.
14. clazz = env->FindClass("java/lang/Error");
15. LOG_FATAL_IF(clazz == NULL, "Unable to find class ");
16. = (jclass) env->NewGlobalRef(clazz);
17.
18. clazz = env->FindClass(kBinderProxyPathName);
19. LOG_FATAL_IF(clazz == NULL, "Unable to find class ");
20.
21. = (jclass) env->NewGlobalRef(clazz);
22.
23. = env->GetMethodID(clazz, "<init>", "()V");
24. assert();
25.
26. = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
27. assert();
28.
29.
30. = env->GetFieldID(clazz, "mObject", "I");
31. assert();
32.
33. = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
34. assert();
35.
36. return AndroidRuntime::registerNativeMethods(
37. env, kBinderProxyPathName,
38. gBinderProxyMethods, NELEM(gBinderProxyMethods));
39. }
回到前面的 javaObjectForIBinder 函数中,下面这段代码:
view plain
1. if (val->checkSubclass(&gBinderOffsets)) {
2. // One of our own!
3. jobject object = static_cast<JavaBBinder*>(())->object();
4. //printf("objectForBinder %p: it's our own %p!\n", (), object);
5. return object;
6. }
前面说过,这里传进来的参数是一个 BpBinder 的指针,而
BpBinder::checkSubclass 继承于父类 IBinder::checkSubclass,它什么也不做就返回
false。
于是函数继续往下执行:
view plain
1. jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
由于这个 BpBinder 对象是第一创建,它里面什么对象也没有,因此,这里返回
的 object 为 NULL。
于是函数又继续往下执行:
view plain
1. object = env->NewObject(, );
这里,就创建了一个 BinderProxy 对象了。创建了之后,要把这个 BpBinder 对
象和这个 BinderProxy 对象关联起来:
view plain
1. env->SetIntField(object, , (int)());
就是通过 成员变量来关联的了, 成员
变量记录了这个 BpBinder 对象的地址。
接下去,还要把它放到 BpBinder 里面去,下次就要使用时,就可以在上一步调
用 BpBinder::findObj 把它找回来了:
view plain
1. val->attachObject(&gBinderProxyOffsets, refObject,
2. jnienv_to_javavm(env), proxy_cleanup);
最后,就把这个 BinderProxy 返回到 android_os_BinderInternal_getContextObject
函数,最终返回到最开始的 函数中来了,于是,
我们就获得一个 BinderProxy 对象了。
回到 中,从下面语句返回:
view plain
1. sServiceManager = (());
相当于是:
view plain
1. sServiceManager = (new BinderProxy());
接下去就是调用 函数了,这个函数定义在
frameworks/base/core/java/android/os/ 文件中:
view plain
1. public abstract class ServiceManagerNative ......
2. {
3. ......
4. static public IServiceManager asInterface(IBinder obj)
5. {
6. if (obj == null) {
7. return null;
8. }
9. IServiceManager in =
10. (IServiceManager)(descriptor);
11. if (in != null) {
12. return in;
13. }
14.
15. return new ServiceManagerProxy(obj);
16. }
17. ......
18. }
这里的参数 obj 是一个 BinderProxy 对象,它的 queryLocalInterface 函数返回
null。因此,最终以这个 BinderProxy 对象为参数创建一个 ServiceManagerProxy 对象。
返回到 中,从下面语句返回:
view plain
1. sServiceManager = (new BinderProxy());
就相当于是:
view plain
1. sServiceManager = new ServiceManagerProxy(new BinderProxy());
于是,我们的目标终于完成了。
总结一下,就是在 Java 层,我们拥有了一个 Service Manager 远程接口
ServiceManagerProxy,而这个 ServiceManagerProxy 对象在 JNI 层有一个句柄值为 0
的 BpBinder 对象与之通过 gBinderProxyOffsets 关联起来。
这样获取 Service Manager 的 Java 远程接口的过程就完成了。
二. HelloService 接口的定义
前面我们在学习 Android 系统的硬件抽象层(HAL)时,在在 Ubuntu 上为 Android
系统的 Application Frameworks 层增加硬件访问服务这篇文章中,我们编写了一个硬
件服务 HelloService,它的服务接口定义在
frameworks/base/core/java/android/os/ 文件中:
view plain
1. package ;
2.
3. interface IHelloService
4. {
5. void setVal(int val);
6. int getVal();
7. }
这个服务接口很简单,只有两个函数,分别用来读写硬件寄存器。
注意,这是一个 aidl 文件,编译后会生成一个 。我们来看一
下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。
view plain
1. /*
2. * This file is auto-generated. DO NOT MODIFY.
3. * Original file: frameworks/base/core/java/android/os/
4. */
5. package ;
6. public interface IHelloService extends
7. {
8. /** Local-side IPC implementation stub class. */
9. public static abstract class Stub extends implements
10. {
11. private static final DESCRIPTOR = "";
12. /** Construct the stub at attach it to the interface. */
13. public Stub()
14. {
15. (this, DESCRIPTOR);
16. }
17.
18. /**
19. * Cast an IBinder object into an interface,
20. * generating a proxy if needed.
21. */
22. public static asInterface( obj)
23. {
24. if ((obj==null)) {
25. return null;
26. }
27. iin = ()(DESCRIPTOR);
28. if (((iin!=null)&&(iin instanceof ))) {
29. return (()iin);
30. }
31. return new (obj);
32. }
33.
34. public asBinder()
35. {
36. return this;
37. }
38.
39. @Override
40. public boolean onTransact(int code, data, reply, int flags) thro
ws
41. {
42. switch (code)
43. {
44. case INTERFACE_TRANSACTION:
45. {
46. (DESCRIPTOR);
47. return true;
48. }
49. case TRANSACTION_setVal:
50. {
51. (DESCRIPTOR);
52. int _arg0;
53. _arg0 = ();
54. (_arg0);
55. ();
56. return true;
57. }
58. case TRANSACTION_getVal:
59. {
60. (DESCRIPTOR);
61. int _result = ();
62. ();
63. (_result);
64. return true;
65. }
66. }
67. return (code, data, reply, flags);
68. }
69.
70. private static class Proxy implements
71. {
72. private mRemote;
73.
74. Proxy( remote)
75. {
76. mRemote = remote;
77. }
78.
79. public asBinder()
80. {
81. return mRemote;
82. }
83.
84. public getInterfaceDescriptor()
85. {
86. return DESCRIPTOR;
87. }
88.
89. public void setVal(int val) throws
90. {
91. _data = ();
92. _reply = ();
93. try {
94. (DESCRIPTOR);
95. (val);
96. (_setVal, _data, _reply, 0);
97. ();
98. }
99. finally {
100. ();
101. ();
102. }
103. }
104.
105. public int getVal() throws
106. {
107. _data = ();
108. _reply = ();
109. int _result;
110. try {
111. (DESCRIPTOR);
112. (_getVal, _data, _reply, 0);
113. ();
114. _result = ();
115. }
116. finally {
117. ();
118. ();
119. }
120. return _result;
121. }
122. }
123.
124. static final int TRANSACTION_setVal = (_CALL_TRANSACTION
+ 0);
125. static final int TRANSACTION_getVal = (_CALL_TRANSACTION
+ 1);
126. }
127.
128. public void setVal(int val) throws ;
129. public int getVal() throws ;
130. }
这里我们可以看到 这个文件编译后的真面目,原来就是根据
IHelloService 接口的定义生成相应的 Stub 和 Proxy 类,这个就是我们熟悉的 Binder
机制的内容了,即实现这个 HelloService 的 Server 必须继续于这里的
类,而这个 HelloService 的远程接口就是这里的
对象获得的 IHelloService 接口。接下来的内容,我们就可以
看到 和 是怎么创建或者使用的。
三. HelloService 的启动过程
在讨论 HelloService 的启动过程之前,我们先来看一下实现 HelloService 接口
的 Server 是怎么定义的。
回忆在 Ubuntu 上为 Android 系统的 Application Frameworks 层增加硬件访问服
务一文,我们在 frameworks/base/services/java/com/android/server 目录下新增了一个
文件:
view plain
1. package ;
2.
3. import ;
4. import ;
5. import ;
6.
7. public class HelloService extends {
8. private static final String TAG = "HelloService";
9.
10. HelloService() {
11. init_native();
12. }
13.
14. public void setVal(int val) {
15. setVal_native(val);
16. }
17.
18. public int getVal() {
19. return getVal_native();
20. }
21.
22. private static native boolean init_native();
23. private static native void setVal_native(int val);
24. private static native int getVal_native();
25. }
这里,我们可以看到,HelloService 继续了 类,它通过本地方
法调用实现了 getVal 和 setVal 两个函数。我们不关心这两个函数的具体实现,有兴
趣的读者可以参考在 Ubuntu 上为 Android 系统的 Application Frameworks 层增加硬
件访问服务一文。
有了 HelloService 这个 Server 类后,下一步就是考虑怎么样把它启动起来了。
在 frameworks/base/services/java/com/android/server/ 文件中,定义
了 SystemServer 类。SystemServer 对象是在系统启动的时候创建的,它被创建的时
候会启动一个线程来创建 HelloService,并且把它添加到 Service Manager 守护进程
中去,最后进入一个循环,等待 Client 的请求。
我们来看一下这部份的代码:
view plain
1. class ServerThread extends Thread {
2. ......
3.
4. @Override
5. public void run() {
6.
7. ......
8.
9. ();
10.
11. ......
12.
13. try {
14. (TAG, "Hello Service");
15. ("hello", new HelloService());
16. } catch (Throwable e) {
17. (TAG, "Failure starting Hello Service", e);
18. }
19.
20. ......
21.
22. ();
23.
24. ......
25. }
26. }
27.
28. ......
29.
30. public class SystemServer
31. {
32. ......
33.
34. /**
35. * This method is called from Zygote to initialize the system. This will cause the native
36. * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
37. * up into init2() to start the Android services.
38. */
39. native public static void init1(String[] args);
40.
41. ......
42.
43. public static final void init2() {
44. (TAG, "Entered the Android system server!");
45. Thread thr = new ServerThread();
46. ("");
47. ();
48. }
49. ......
50. }
这里,我们可以看到,在 函数中,执行了下面代码把
HelloService 添加到 Service Manager 中去,并且通过 进入循环等待 Client
的请求。这里我们关注把 HelloService 添加到 Service Manager 中去的代码:
view plain
1. try {
2. (TAG, "Hello Service");
3. ("hello", new HelloService());
4. } catch (Throwable e) {
5. (TAG, "Failure starting Hello Service", e);
6. }
通过调用 把一个 HelloService 实例添加到 Service
Manager 中去。
我们先来看一下 HelloService 的创建过程:
view plain
1. new HelloService();
这个语句会调用 HelloService 类的构造函数,而 HelloService 类继承于
类, 类又继承了 Binder 类,因此,最后会调用
Binder 类的构造函数:
view plain
1. public class Binder implements IBinder {
2. ......
3.
4. private int mObject;
5.
6. ......
7.
8.
9. public Binder() {
10. init();
11. ......
12. }
13.
14.
15. private native final void init();
16.
17.
18. ......
19. }
这里调用了一个 JNI 方法 init 来初始化这个 Binder 对象,这个 JNI 方法定义在
frameworks/base/core/jni/ 文件中:
view plain
1. static void android_os_Binder_init(JNIEnv* env, jobject clazz)
2. {
3. JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz);
4. if (jbh == NULL) {
5. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
6. return;
7. }
8. LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh);
9. jbh->incStrong(clazz);
10. env->SetIntField(clazz, , (int)jbh);
11. }
它实际上只做了一件事情,就是创建一个 JavaBBinderHolder 对象 jbh,然后把
这个对象的地址保存在上面的 Binder 类的 mObject 成员变量中,后面我们会用到。
回到 函数中,我们再来看一下 函数
的实现:
view plain
1. public final class ServiceManager {
2. ......
3.
4. private static IServiceManager sServiceManager;
5.
6. ......
7.
8. public static void addService(String name, IBinder service) {
9. try {
10. getIServiceManager().addService(name, service);
11. } catch (RemoteException e) {
12. (TAG, "error in addService", e);
13. }
14. }
15.
16. ......
17.
18. }
这里的 getIServiceManager 函数我们在前面已经分析过了,它返回的是一个
ServiceManagerProxy 对象的 IServiceManager 接口。因此,我们进入到
中去看看:
view plain
1. class ServiceManagerProxy implements IServiceManager {
2. public ServiceManagerProxy(IBinder remote) {
3. mRemote = remote;
4. }
5.
6. ......
7.
8. public void addService(String name, IBinder service)
9. throws RemoteException {
10. Parcel data = ();
11. Parcel reply = ();
12. ();
13. (name);
14. (service);
15. (ADD_SERVICE_TRANSACTION, data, reply, 0);
16. ();
17. ();
18. }
19.
20. ......
21.
22. private IBinder mRemote;
23. }
这里的 Parcel 类是用 Java 来实现的,它跟我们前面几篇文章介绍 Binder 机制时
提到的用 C++实现的 Parcel 类的作用是一样的,即用来在两个进程之间传递数据。
这里我们关注是如何把参数 service 写到 data 这个 Parcel 对象中去的:
view plain
1. (service);
我们来看看 函数的实现:
view plain
1. public final class Parcel {
2. ......
3.
4. /**
5. * Write an object into the parcel at the current dataPosition(),
6. * growing dataCapacity() if needed.
7. */
8. public final native void writeStrongBinder(IBinder val);
9.
10. ......
11. }
这里的 writeStrongBinder 函数又是一个 JNI 方法,它定义在
frameworks/base/core/jni/ 文件中:
view plain
1. static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
2. {
3. Parcel* parcel = parcelForJavaObject(env, clazz);
4. if (parcel != NULL) {
5. const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
6. if (err != NO_ERROR) {
7. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
8. }
9. }
10. }
这里的 clazz 参数是一个 Java 语言实现的 Parcel 对象,通过 parcelForJavaObject
把它转换成 C++语言实现的 Parcel 对象。这个函数的实现我们就不看了,有兴趣的
读者可以研究一下,这个函数也是实现在
frameworks/base/core/jni/ 这个文件中。
这里的 object 参数是一个 Java 语言实现的 Binder 对象,在调用 C++语言实现
的 Parcel::writeStrongBinder 把这个对象写入到 parcel 对象时,首先通过
ibinderForJavaObject 函数把这个 Java 语言实现的 Binder 对象转换为 C++语言实现
的 JavaBBinderHolder 对象:
view plain
1. sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
2. {
3. if (obj == NULL) return NULL;
4.
5. if (env->IsInstanceOf(obj, )) {
6. JavaBBinderHolder* jbh = (JavaBBinderHolder*)
7. env->GetIntField(obj, );
8. return jbh != NULL ? jbh->get(env) : NULL;
9. }
10.
11. if (env->IsInstanceOf(obj, )) {
12. return (IBinder*)
13. env->GetIntField(obj, );
14. }
15.
16. LOGW("ibinderForJavaObject: %p is not a Binder object", obj);
17. return NULL;
18. }
我们知道,这里的 obj 参数是一个 Binder 类的实例,因此,这里会进入到第一
个 if 语句中去。
在前面创建 HelloService 对象,曾经在调用到 HelloService 的父类 Binder 中,
曾经在 JNI 层创建了一个 JavaBBinderHolder 对象,然后把这个对象的地址保存在
Binder 类的 mObject 成员变量中,因此,这里把 obj 对象的 mObject 成员变量强制
转为 JavaBBinderHolder 对象。
到了这里,这个函数的功课还未完成,还剩下最后关键的一步:
view plain
1. return jbh != NULL ? jbh->get(env) : NULL;
这里就是 jbh->get 这个语句了。
在 JavaBBinderHolder 类中,有一个成员变量 mBinder,它的类型为
JavaBBinder,而 JavaBBinder 类继承于 BBinder 类。在前面学习 Binder 机制的 C++
语言实现时,我们在 Android 系统进程间通信(IPC)机制 Binder 中的 Server 启动
过程源代码分析这篇文章中,曾经介绍过,IPCThreadState 类负责与 Binder 驱动程
序进行交互,它把从 Binder 驱动程序读出来的请求作简单的处理后,最后把这个请
求扔给 BBinder 的 onTransact 函数来进一步处理。
这里,我们就是要把 JavaBBinderHolder 里面的 JavaBBinder 类型 Binder 实体添
加到 Service Manager 中去,以便使得这个 HelloService 有 Client 来请求服务时,由
Binder 驱动程序来唤醒这个 Server 线程,进而调用这个 JavaBBinder 类型 Binder 实
体的 onTransact 函数来进一步处理,这个函数我们在后面会继续介绍。
先来看一下 JavaBBinderHolder::get 函数的实现:
view plain
1. class JavaBBinderHolder : public RefBase
2. {
3. ......
4.
5. JavaBBinderHolder(JNIEnv* env, jobject object)
6. : mObject(object)
7. {
8. ......
9. }
10.
11. ......
12.
13. sp<JavaBBinder> get(JNIEnv* env)
14. {
15. AutoMutex _l(mLock);
16. sp<JavaBBinder> b = ();
17. if (b == NULL) {
18. b = new JavaBBinder(env, mObject);
19. mBinder = b;
20. ......
21. }
22.
23. return b;
24. }
25.
26. ......
27.
28. jobject mObject;
29. wp<JavaBBinder> mBinder;
30. };
这里是第一次调用 get 函数,因此,会创建一个 JavaBBinder 对象,并且保存
在 mBinder 成员变量中。注意,这里的 mObject 就是上面创建的 HelloService 对象
了,这是一个 Java 对象。这个 HelloService 对象最终也会保存在 JavaBBinder 对象
的成员变量 mObject 中。
回到 android_os_Parcel_writeStrongBinder 函数中,下面这个语句:
view plain
1. const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
相当于是:
view plain
1. const status_t err = parcel->writeStrongBinder((JavaBBinderHodler*)());
因此,这里的效果相当于是写入了一个 JavaBBinder 类型的 Binder 实体到 parcel
中去。这与我们前面介绍的 Binder 机制的 C++实现是一致的。
接着,再回到 这个函数中,最后它通过其成员
变量 mRemote 来执行进程间通信操作。前面我们在介绍如何获取 Service Manager
远程接口时提到,这里的 mRemote 成员变量实际上是一个 BinderProxy 对象,因此,
我们再来看看 函数的实现:
view plain
1. final class BinderProxy implements IBinder {
2. ......
3.
4. public native boolean transact(int code, Parcel data, Parcel reply,
5. int flags) throws RemoteException;
6.
7. ......
8. }
这里的 transact 成员函数又是一个 JNI 方法,它定义在
frameworks/base/core/jni/ 文件中:
view plain
1. static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
2. jint code, jobject dataObj,
3. jobject replyObj, jint flags)
4. {
5. ......
6.
7. Parcel* data = parcelForJavaObject(env, dataObj);
8. if (data == NULL) {
9. return JNI_FALSE;
10. }
11. Parcel* reply = parcelForJavaObject(env, replyObj);
12. if (reply == NULL && replyObj != NULL) {
13. return JNI_FALSE;
14. }
15.
16. IBinder* target = (IBinder*)
17. env->GetIntField(obj, );
18. if (target == NULL) {
19. jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
20. return JNI_FALSE;
21. }
22.
23. ......
24.
25. status_t err = target->transact(code, *data, reply, flags);
26.
27. ......
28.
29. if (err == NO_ERROR) {
30. return JNI_TRUE;
31. } else if (err == UNKNOWN_TRANSACTION) {
32. return JNI_FALSE;
33. }
34.
35. signalExceptionForError(env, obj, err);
36. return JNI_FALSE;
37. }
这里传进来的参数 dataObj 和 replyObj 是一个 Java 接口实现的 Parcel 类,由于
这里是 JNI 层,需要把它转换为 C++实现的 Parcel 类,它们就是通过我们前面说的
parcelForJavaObject 函数进行转换的。
前面我们在分析如何获取 Service Manager 远程接口时,曾经说到,在 JNI 层中,
创建了一个 BpBinder 对象,它的句柄值为 0,它的地址保存在
中,因此,这里通过下面语句得到这个 BpBinder 对象
的 IBinder 接口:
view plain
1. IBinder* target = (IBinder*)
2. env->GetIntField(obj, );
有了这个 IBinder 接口后,就和我们前面几篇文章介绍 Binder 机制的 C/C++实
现一致了。
最后,通过 BpBinder::transact 函数进入到 Binder 驱动程序,然后 Binder 驱动程
序唤醒 Service Manager 响应这个 ADD_SERVICE_TRANSACTION 请求:
view plain
1. status_t err = target->transact(code, *data, reply, flags);
具体可以参考 Android 系统进程间通信(IPC)机制 Binder 中的 Server 启动过
程源代码分析一文。需要注意的是,这里的 data 包含了一个 JavaBBinderHolder 类型
的 Binder 实体对象,它就代表了我们上面创建的 HelloService。Service Manager 收
到这个 ADD_SERVICE_TRANSACTION 请求时,就会把这个 Binder 实体纳入到自
己内部进行管理。
这样,实现 HelloService 的 Server 的启动过程就完成了。
四. Client 获取 HelloService 的 Java 远程接口的过程
前面我们在学习 Android 系统硬件抽象层(HAL)时,在在 Ubuntu 上为 Android
系统内置 Java 应用程序测试 Application Frameworks 层的硬件服务这篇文章中,我
们创建了一个应用程序,这个应用程序作为一个 Client 角色,借助 Service Manager
这个 Java 远程接口来获得 HelloService 的远程接口,进而调用 HelloService 提供的
服务。
我们看看它是如何借助 Service Manager 这个 Java 远程接口来获得 HelloService
的远程接口的。在 Hello 这个 Activity 的 onCreate 函数,通过
函数来获得 HelloService 的远程接口:
view plain
1. public class Hello extends Activity implements OnClickListener {
2. ......
3.
4. private IHelloService helloService = null;
5.
6. ......
7.
8. @Override
9. public void onCreate(Bundle savedInstanceState) {
10.
11. helloService = (
12. ("hello"));
13. }
14.
15. ......
16. }
我们先来看 的实现。前面我们说过,这里实际上是调
用了 函数:
view plain
1. class ServiceManagerProxy implements IServiceManager {
2. public ServiceManagerProxy(IBinder remote) {
3. mRemote = remote;
4. }
5.
6. ......
7.
8. public IBinder getService(String name) throws RemoteException {
9. Parcel data = ();
10. Parcel reply = ();
11. ();
12. (name);
13. (GET_SERVICE_TRANSACTION, data, reply, 0);
14. IBinder binder = ();
15. ();
16. ();
17. return binder;
18. }
19.
20. ......
21.
22. private IBinder mRemote;
23. }
最终通过 来执行实际操作。我们在前面已经介绍过了,这里
的 mRemote 实际上是一个 BinderProxy 对象,它的 transact 成员函数是一个 JNI 方法,
实现在 frameworks/base/core/jni/ 文件中的
android_os_BinderProxy_transact 函数中。
这个函数前面我们已经看到了,这里就不再列出来了。不过,当这个函数从:
view plain
1. status_t err = target->transact(code, *data, reply, flags);
这里的 reply 变量里面就包括了一个 HelloService 的引用了。注意,这里的 reply
变量就是我们在 函数里面传进来的参数 reply,它是
一个 Parcel 对象。
回到 函数中,从下面语句返回:
view plain
1. (GET_SERVICE_TRANSACTION, data, reply, 0);
接着,就通过下面语句将这个 HelloService 的引用读出来:
view plain
1. IBinder binder = ();
我们看看 的实现:
view plain
1. public final class Parcel {
2. ......
3.
4. /**
5. * Read an object from the parcel at the current dataPosition().
6. */
7. public final native IBinder readStrongBinder();
8.
9. ......
10. }
它也是一个 JNI 方法,实现在 frameworks/base/core/jni/
文件中:
view plain
1. static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
2. {
3. Parcel* parcel = parcelForJavaObject(env, clazz);
4. if (parcel != NULL) {
5. return javaObjectForIBinder(env, parcel->readStrongBinder());
6. }
7. return NULL;
8. }
这里首先把 Java 语言实现的 Parcel 对象 class 转换成 C++语言实现的 Parcel 对
象 parcel,接着,通过 parcel->readStrongBinder 函数来获得一个 Binder 引用。
我们在前面学习 Binder 机制时,在 Android 系统进程间通信(IPC)机制 Binder
中的 Client 获得 Server 远程接口过程源代码分析这篇文章中,曾经分析过这个函数,
它最终返回来的是一个 BpBinder 对象,因此,下面的语句:
view plain
1. return javaObjectForIBinder(env, parcel->readStrongBinder());
就相当于是:
view plain
1. return javaObjectForIBinder(env, new BpBinder(handle));
这里的 handle 就是 HelloService 这个 Binder 实体在 Client 进程中的句柄了,它
是由 Binder 驱动程序设置的,上层不用关心它的值具体是多少。至于
javaObjectForIBinder 这个函数,我们前面介绍如何获取 Service Manager 的 Java 远程
接口时已经有详细介绍,这里就不累述了,它的作用就是创建一个 BinderProxy 对象,
并且把刚才获得的 BpBinder 对象的地址保存在这个 BinderProxy 对象的 mObject 成
员变量中。
最后返回到 函数中,从下面语句返回:
view plain
1. helloService = (
2. ("hello"));
就相当于是:
view plain
1. helloService = (new BinderProxy()));
回忆一下前面介绍 IHelloService 接口的定义时, 是
这样定义的:
view plain
1. public interface IHelloService extends
2. {
3. /** Local-side IPC implementation stub class. */
4. public static abstract class Stub extends implements
5. {
6. ......
7.
8. public static asInterface( obj)
9. {
10. if ((obj==null)) {
11. return null;
12. }
13. iin = ()(DESCRIPTOR);
14. if (((iin!=null)&&(iin instanceof ))) {
15. return (()iin);
16. }
17. return new (obj);
18. }
19.
20. ......
21. }
22. }
这里的 obj 是一个 BinderProxy 对象,它的 queryLocalInterface 返回 null,于是
调用下面语句获得 HelloService 的远程接口:
view plain
1. return new (obj);
相当于是:
view plain
1. return new (new BinderProxy());
这样,我们就获得了 HelloService 的远程接口了,它实质上是一个实现了
IHelloService 接口的 对象。
五. Client 通过 HelloService 的 Java 远程接口来使用 HelloService 提供的服务的
过程
上面介绍的 Hello 这个 Activity 获得了 HelloService 的远程接口后,就可以使用
它的服务了。
我们以使用 函数为例详细说明。在 Hello::onClick 函数中调
用了 函数:
view plain
1. public class Hello extends Activity implements OnClickListener {
2. ......
3.
4. @Override
5. public void onClick(View v) {
6. if((readButton)) {
7. int val = ();
8. ......
9. }
10. else if((writeButton)) {
11. ......
12. }
13. else if((clearButton)) {
14. ......
15. }
16. }
17.
18. ......
19. }
通知前面的分析,我们知道,这里的 helloService 接口实际上是一个
对象,因此,我们进入到 类的 getVal
函数中:
view plain
1. public interface IHelloService extends
2. {
3. /** Local-side IPC implementation stub class. */
4. public static abstract class Stub extends implements
5. {
6.
7. ......
8.
9. private static class Proxy implements
10. {
11. private mRemote;
12.
13. ......
14.
15. public int getVal() throws
16. {
17. _data = ();
18. _reply = ();
19. int _result;
20. try {
21. (DESCRIPTOR);
22. (_getVal, _data, _reply, 0);
23. ();
24. _result = ();
25. }
26. finally {
27. ();
28. ();
29. }
30. return _result;
31. }
32. }
33.
34. ......
35. static final int TRANSACTION_getVal = (_CALL_TRANSACTION +
1);
36. }
37.
38. ......
39. }
这里我们可以看出,实际上是通过 来请求 HelloService 执行
TRANSACTION_getVal 操作。这里的 mRemote 是一个 BinderProxy 对象,这是我们
在前面获取 HelloService 的 Java 远程接口的过程中创建的。
函数是一个 JNI 方法,我们在前面已经介绍过了,这里不
再累述。最过调用到 Binder 驱动程序,Binder 驱动程序唤醒 HelloService 这个
Server。前面我们在介绍 HelloService 的启动过程时,曾经提到,HelloService 这个
Server 线程被唤醒之后,就会调用 JavaBBinder 类的 onTransact 函数:
view plain
1. class JavaBBinder : public BBinder
2. {
3. JavaBBinder(JNIEnv* env, jobject object)
4. : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
5. {
6. ......
7. }
8.
9. ......
10.
11. virtual status_t onTransact(
12. uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
13. {
14. JNIEnv* env = javavm_to_jnienv(mVM);
15.
16. ......
17.
18. jboolean res = env->CallBooleanMethod(mObject, ,
19. code, (int32_t)&data, (int32_t)reply, flags);
20.
21. ......
22.
23. return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
24. }
25.
26. ......
27.
28. JavaVM* const mVM;
29. jobject const mObject;
30. };
前面我们在介绍 HelloService 的启动过程时,曾经介绍过,JavaBBinder 类里
面的成员变量 mObject 就是 HelloService 类的一个实例对象了。因此,这里通过语
句:
view plain
1. jboolean res = env->CallBooleanMethod(mObject, ,
2. code, (int32_t)&data, (int32_t)reply, flags);
就调用了 函数,而 函数继
承了 Binder 类的 execTransact 函数:
view plain
1. public class Binder implements IBinder {
2. ......
3.
4. // Entry point from 's onTransact
5. private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
6. Parcel data = (dataObj);
7. Parcel reply = (replyObj);
8. // theoretically, we should call transact, which will call onTransact,
9. // but all that does is rewind it, and we just got these from an IPC,
10. // so we'll just call it directly.
11. boolean res;
12. try {
13. res = onTransact(code, data, reply, flags);
14. } catch (RemoteException e) {
15. (e);
16. res = true;
17. } catch (RuntimeException e) {
18. (e);
19. res = true;
20. } catch (OutOfMemoryError e) {
21. RuntimeException re = new RuntimeException("Out of memory", e);
22. (re);
23. res = true;
24. }
25. ();
26. ();
27. return res;
28. }
29. }
这里又调用了 onTransact 函数来作进一步处理。由于 HelloService 类继承了
类,而 类实现了 onTransact 函数,HelloService
类没有实现,因此,最终调用了 函数:
view plain
1. public interface IHelloService extends
2. {
3. /** Local-side IPC implementation stub class. */
4. public static abstract class Stub extends implements
5. {
6. ......
7.
8. @Override
9. public boolean onTransact(int code, data, reply, int flags) thro
ws
10. {
11. switch (code)
12. {
13. ......
14. case TRANSACTION_getVal:
15. {
16. (DESCRIPTOR);
17. int _result = ();
18. ();
19. (_result);
20. return true;
21. }
22. }
23. return (code, data, reply, flags);
24. }
25.
26. ......
27.
28. }
29. }
函数最终又调用了 函数:
view plain
1. public class HelloService extends {
2. ......
3.
4. public int getVal() {
5. return getVal_native();
6. }
7.
8. ......
9. private static native int getVal_native();
10. }
最终,经过层层返回,就回到 函数中来了,从
下面语句返回:
view plain
1. (_getVal, _data, _reply, 0);
并将结果读出来:
view plain
1. _result = ();
最后将这个结果返回到 函数中。
这样,Client 通过 HelloService 的 Java 远程接口来使用 HelloService 提供的服务
的过程就介绍完了。
至此,Android 系统进程间通信 Binder 机制在应用程序框架层的 Java 接口源代
码分析也完成了,整个 Binder 机制的学习就结束了。
重新学习Android系统进程间通信Binder机制,请回到Android进程间通信(IPC)
机制 Binder 简要介绍和学习计划一文。