《Android系统进程间通信Binder机制在应用程序框架层的Ja.docx》由会员分享,可在线阅读,更多相关《Android系统进程间通信Binder机制在应用程序框架层的Ja.docx(37页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 在前面几篇文章中,我们详细介绍了Android系统进程间通信机制Binder的原理,并且深入分析了系统提供的Binder运行库和驱动程序的源代码。细心的读者会发现,这几篇文章分析的Binder接口都是基于C/C+语言来实现的,但是我们在编写应用程序都是基于Java语言的,那么,我们如何使用Java语言来使用系统的Binder机制来进行进程间通信呢?这就是本文要介绍的Android系统应用程序框架层的用Java语言来实现的Binder接口了。 熟悉Android系统的读者,应该能想到应用程序框架中的基于Java语言的Binder接口是通过JNI来调用基于C/C+语言的Binder运行库来为Ja
2、va应用程序提供进程间通信服务的了。JNI在Android系统中用得相当普遍,SDK中的Java接口API很多只是简单地通过JNI来调用底层的C/C+运行库从而为应用程序服务的。 这里,我们仍然是通过具体的例子来说明Binder机制在应用程序框架层中的Java接口,主要就是Service Manager、Server和Client这三个角色的实现了。通常,在应用程序中,我们都是把Server实现为Service的形式,并且通过IServiceManager.addService接口来把这个Service添加到Service Manager,Client也是通过IServiceManager.g
3、etService接口来获得Service接口,接着就可以使用这个Service提供的功能了,这个与运行时库的Binder接口是一致的。 前面我们学习Android硬件抽象层时,曾经在应用程序框架层中提供了一个硬件访问服务HelloService,这个Service运行在一个独立的进程中充当Server的角色,使用这个Service的Client运行在另一个进程中,它们之间就是通过Binder机制来通信的了。这里,我们就使用HelloService这个例子来分析Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码。所以希望读者在阅读下面的内容之前,先了解一下前面在U
4、buntu上为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远程接
5、口 我们要获取的Service Manager的Java远程接口是一个ServiceManagerProxy对象的IServiceManager接口。我们现在就来看看ServiceManagerProxy类是长什么样子的: 这里可以看出,ServiceManagerProxy类实现了IServiceManager接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。从ServiceManagerProxy类的构造函数可以看出,它需要一个BinderProxy对象的IBinder接口来作为参数。因此,要获取Service M
6、anager的Java远程接口ServiceManagerProxy,首先要有一个BinderProxy对象。下面将会看到这个BinderProxy对象是如何获得的。 再来看一下是通过什么路径来获取Service Manager的Java远程接口ServiceManagerProxy的。这个主角就是ServiceManager了,我们也先看一下ServiceManager是长什么样子的: ServiceManager类有一个静态成员函数getIServiceManager,它的作用就是用来获取Service Manager的Java远程接口了,而这个函数又是通过ServiceManagerNa
7、tive来获取Service Manager的Java远程接口的。 接下来,我们就看一下ServiceManager.getIServiceManager这个函数的实现,这个函数定义在frameworks/base/core/java/android/os/ServiceManager.java文件中:view plain1. publicfinalclassServiceManager2. .3. privatestaticIServiceManagersServiceManager;4. .5. privatestaticIServiceManagergetIServiceManager(
8、)6. if(sServiceManager!=null)7. returnsServiceManager;8. 9. 10. /Findtheservicemanager11. sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject();12. returnsServiceManager;13. 14. .15. 如果其静态成员变量sServiceManager尚未创建,那么就调用ServiceManagerNative.asInterface函数来创建。在调用ServiceManage
9、rNative.asInterface函数之前,首先要通过BinderInternal.getContextObject函数来获得一个BinderProxy对象。 我们来看一下BinderInternal.getContextObject的实现,这个函数定义在frameworks/base/core/java/com/android/internal/os/BinderInternal.java文件中:view plain1. publicclassBinderInternal2. .3. /*4. *Returntheglobalcontextobjectofthesystem.Thisis
10、usually5. *animplementationofIServiceManager,whichyoucanusetofind6. *otherservices.7. */8. publicstaticfinalnativeIBindergetContextObject();9. 10. .11. 这里可以看出,BinderInternal.getContextObject是一个JNI方法,它实现在frameworks/base/core/jni/android_util_Binder.cpp文件中:view plain1. staticjobjectandroid_os_BinderIn
11、ternal_getContextObject(JNIEnv*env,jobjectclazz)2. 3. spb=ProcessState:self()-getContextObject(NULL);4. returnjavaObjectForIBinder(env,b);5. 这里看到我们熟悉的ProcessState:self()-getContextObject函数,具体可以参考浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文。ProcessState:self()-getContextObject函
12、数返回一个BpBinder对象,它的句柄值是0,即下面语句:view plain1. spb=ProcessState:self()-getContextObject(NULL); 相当于是:view plain1. spb=newBpBinder(0); 接着调用javaObjectForIBinder把这个BpBinder对象转换成一个BinderProxy对象:view plain1. jobjectjavaObjectForIBinder(JNIEnv*env,constsp&val)2. 3. if(val=NULL)returnNULL;4. 5. if(val-checkSubc
13、lass(&gBinderOffsets)6. /Oneofourown!7. jobjectobject=static_cast(val.get()-object();8. /printf(objectForBinder%p:itsourown%p!n,val.get(),object);9. returnobject;10. 11. 12. /Fortherestofthefunctionwewillholdthislock,toserialize13. /looking/creationofJavaproxiesfornativeBinderproxies.14. AutoMutex_l
14、(mProxyLock);15. 16. /Someoneelses.doweknowaboutit?17. jobjectobject=(jobject)val-findObject(&gBinderProxyOffsets);18. if(object!=NULL)19. jobjectres=env-CallObjectMethod(object,gWeakReferenceOffsets.mGet);20. if(res!=NULL)21. LOGV(objectForBinder%p:foundexisting%p!n,val.get(),res);22. returnres;23.
15、 24. LOGV(Proxyobject%pofIBinder%pnolongerinworkingset!,object,val.get();25. android_atomic_dec(&gNumProxyRefs);26. val-detachObject(&gBinderProxyOffsets);27. env-DeleteGlobalRef(object);28. 29. 30. object=env-NewObject(gBinderProxyOffsets.mClass,gBinderProxyOffsets.mConstructor);31. if(object!=NULL
16、)32. LOGV(objectForBinder%p:creatednew%p!n,val.get(),object);33. /Theproxyholdsareferencetothenativeobject.34. env-SetIntField(object,gBinderProxyOffsets.mObject,(int)val.get();35. val-incStrong(object);36. 37. /Thenativeobjectneedstoholdaweakreferencebacktothe38. /proxy,sowecanretrievethesameproxyi
17、fitisstillactive.39. jobjectrefObject=env-NewGlobalRef(40. env-GetObjectField(object,gBinderProxyOffsets.mSelf);41. val-attachObject(&gBinderProxyOffsets,refObject,42. jnienv_to_javavm(env),proxy_cleanup);43. 44. /Notethatanewobjectreferencehasbeencreated.45. android_atomic_inc(&gNumProxyRefs);46. i
18、ncRefsCreated(env);47. 48. 49. returnobject;50. 在介绍这个函数之前,先来看两个变量gBinderOffsets和gBinderProxyOffsets的定义。 先看gBinderOffsets的定义:view plain1. staticstructbindernative_offsets_t2. 3. /Classstate.4. jclassmClass;5. jmethodIDmExecTransact;6. 7. /Objectstate.8. jfieldIDmObject;9. 10. gBinderOffsets; 简单来说,gBi
19、nderOffsets变量是用来记录上面第二个类图中的Binder类的相关信息的,它是在注册Binder类的JNI方法的int_register_android_os_Binder函数初始化的:view plain1. constchar*constkBinderPathName=android/os/Binder;2. 3. staticintint_register_android_os_Binder(JNIEnv*env)4. 5. jclassclazz;6. 7. clazz=env-FindClass(kBinderPathName);8. LOG_FATAL_IF(clazz=N
20、ULL,Unabletofindclassandroid.os.Binder);9. 10. gBinderOffsets.mClass=(jclass)env-NewGlobalRef(clazz);11. gBinderOffsets.mExecTransact12. =env-GetMethodID(clazz,execTransact,(IIII)Z);13. assert(gBinderOffsets.mExecTransact);14. 15. gBinderOffsets.mObject16. =env-GetFieldID(clazz,mObject,I);17. assert
21、(gBinderOffsets.mObject);18. 19. returnAndroidRuntime:registerNativeMethods(20. env,kBinderPathName,21. gBinderMethods,NELEM(gBinderMethods);22. 再来看gBinderProxyOffsets的定义:view plain1. staticstructbinderproxy_offsets_t2. 3. /Classstate.4. jclassmClass;5. jmethodIDmConstructor;6. jmethodIDmSendDeathNo
22、tice;7. 8. /Objectstate.9. jfieldIDmObject;10. jfieldIDmSelf;11. 12. gBinderProxyOffsets; 简单来说,gBinderProxyOffsets是用来变量是用来记录上面第一个图中的BinderProxy类的相关信息的,它是在注册BinderProxy类的JNI方法的int_register_android_os_BinderProxy函数初始化的:view plain1. constchar*constkBinderProxyPathName=android/os/BinderProxy;2. 3. stati
23、cintint_register_android_os_BinderProxy(JNIEnv*env)4. 5. jclassclazz;6. 7. clazz=env-FindClass(java/lang/ref/WeakReference);8. LOG_FATAL_IF(clazz=NULL,Unabletofindclassjava.lang.ref.WeakReference);9. gWeakReferenceOffsets.mClass=(jclass)env-NewGlobalRef(clazz);10. gWeakReferenceOffsets.mGet11. =env-
24、GetMethodID(clazz,get,()Ljava/lang/Object;);12. assert(gWeakReferenceOffsets.mGet);13. 14. clazz=env-FindClass(java/lang/Error);15. LOG_FATAL_IF(clazz=NULL,Unabletofindclassjava.lang.Error);16. gErrorOffsets.mClass=(jclass)env-NewGlobalRef(clazz);17. 18. clazz=env-FindClass(kBinderProxyPathName);19.
25、 LOG_FATAL_IF(clazz=NULL,Unabletofindclassandroid.os.BinderProxy);20. 21. gBinderProxyOffsets.mClass=(jclass)env-NewGlobalRef(clazz);22. gBinderProxyOffsets.mConstructor23. =env-GetMethodID(clazz,()V);24. assert(gBinderProxyOffsets.mConstructor);25. gBinderProxyOffsets.mSendDeathNotice26. =env-GetSt
26、aticMethodID(clazz,sendDeathNotice,(Landroid/os/IBinder$DeathRecipient;)V);27. assert(gBinderProxyOffsets.mSendDeathNotice);28. 29. gBinderProxyOffsets.mObject30. =env-GetFieldID(clazz,mObject,I);31. assert(gBinderProxyOffsets.mObject);32. gBinderProxyOffsets.mSelf33. =env-GetFieldID(clazz,mSelf,Lja
27、va/lang/ref/WeakReference;);34. assert(gBinderProxyOffsets.mSelf);35. 36. returnAndroidRuntime:registerNativeMethods(37. env,kBinderProxyPathName,38. gBinderProxyMethods,NELEM(gBinderProxyMethods);39. 回到前面的javaObjectForIBinder函数中,下面这段代码:view plain1. if(val-checkSubclass(&gBinderOffsets)2. /Oneofouro
28、wn!3. jobjectobject=static_cast(val.get()-object();4. /printf(objectForBinder%p:itsourown%p!n,val.get(),object);5. returnobject;6. 前面说过,这里传进来的参数是一个BpBinder的指针,而BpBinder:checkSubclass继承于父类IBinder:checkSubclass,它什么也不做就返回false。 于是函数继续往下执行:view plain1. jobjectobject=(jobject)val-findObject(&gBinderProxy
29、Offsets); 由于这个BpBinder对象是第一创建,它里面什么对象也没有,因此,这里返回的object为NULL。 于是函数又继续往下执行:view plain1. object=env-NewObject(gBinderProxyOffsets.mClass,gBinderProxyOffsets.mConstructor); 这里,就创建了一个BinderProxy对象了。创建了之后,要把这个BpBinder对象和这个BinderProxy对象关联起来:view plain1. env-SetIntField(object,gBinderProxyOffsets.mObject,(
30、int)val.get(); 就是通过BinderProxy.mObject成员变量来关联的了,BinderProxy.mObject成员变量记录了这个BpBinder对象的地址。 接下去,还要把它放到BpBinder里面去,下次就要使用时,就可以在上一步调用BpBinder:findObj把它找回来了:view plain1. val-attachObject(&gBinderProxyOffsets,refObject,2. jnienv_to_javavm(env),proxy_cleanup); 最后,就把这个BinderProxy返回到android_os_BinderInterna
31、l_getContextObject函数,最终返回到最开始的ServiceManager.getIServiceManager函数中来了,于是,我们就获得一个BinderProxy对象了。 回到ServiceManager.getIServiceManager中,从下面语句返回:view plain1. sServiceManager=ServiceManagerNative.asInterface(BinderInternal.getContextObject(); 相当于是:view plain1. sServiceManager=ServiceManagerNative.asInterf
32、ace(newBinderProxy(); 接下去就是调用ServiceManagerNative.asInterface函数了,这个函数定义在frameworks/base/core/java/android/os/ServiceManagerNative.java文件中:view plain1. publicabstractclassServiceManagerNative.2. 3. .4. staticpublicIServiceManagerasInterface(IBinderobj)5. 6. if(obj=null)7. returnnull;8. 9. IServiceMan
33、agerin=10. (IServiceManager)obj.queryLocalInterface(descriptor);11. if(in!=null)12. returnin;13. 14. 15. returnnewServiceManagerProxy(obj);16. 17. .18. 这里的参数obj是一个BinderProxy对象,它的queryLocalInterface函数返回null。因此,最终以这个BinderProxy对象为参数创建一个ServiceManagerProxy对象。 返回到ServiceManager.getIServiceManager中,从下面语
34、句返回:view plain1. sServiceManager=ServiceManagerNative.asInterface(newBinderProxy(); 就相当于是:view plain1. sServiceManager=newServiceManagerProxy(newBinderProxy(); 于是,我们的目标终于完成了。 总结一下,就是在Java层,我们拥有了一个Service Manager远程接口ServiceManagerProxy,而这个ServiceManagerProxy对象在JNI层有一个句柄值为0的BpBinder对象与之通过gBinderProxyO
35、ffsets关联起来。 这样获取Service Manager的Java远程接口的过程就完成了。 二.HelloService接口的定义 前面我们在学习Android系统的硬件抽象层(HAL)时,在在Ubuntu上为Android系统的Application Frameworks层增加硬件访问服务这篇文章中,我们编写了一个硬件服务HelloService,它的服务接口定义在frameworks/base/core/java/android/os/IHelloService.aidl文件中:view plain1. packageandroid.os;2. 3. interfaceIHelloS
36、ervice4. 5. voidsetVal(intval);6. intgetVal();7. 这个服务接口很简单,只有两个函数,分别用来读写硬件寄存器。 注意,这是一个aidl文件,编译后会生成一个IHelloService.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。view plain1. /*2. *Thisfileisauto-generated.DONOTMODIFY.3. *Originalfile:frameworks/base/core/java/android/os/IHelloService.aidl4. */5. packagea
37、ndroid.os;6. publicinterfaceIHelloServiceextendsandroid.os.IInterface7. 8. /*Local-sideIPCimplementationstubclass.*/9. publicstaticabstractclassStubextendsandroid.os.Binderimplementsandroid.os.IHelloService10. 11. privatestaticfinaljava.lang.StringDESCRIPTOR=android.os.IHelloService;12. /*Constructt
38、hestubatattachittotheinterface.*/13. publicStub()14. 15. this.attachInterface(this,DESCRIPTOR);16. 17. 18. /*19. *CastanIBinderobjectintoanandroid.os.IHelloServiceinterface,20. *generatingaproxyifneeded.21. */22. publicstaticandroid.os.IHelloServiceasInterface(android.os.IBinderobj)23. 24. if(obj=nu
39、ll)25. returnnull;26. 27. android.os.IInterfaceiin=(android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);28. if(iin!=null)&(iininstanceofandroid.os.IHelloService)29. return(android.os.IHelloService)iin);30. 31. returnnewandroid.os.IHelloService.Stub.Proxy(obj);32. 33. 34. publicandroid.os.IBinderasBinder()35. 36. returnthis