首页 > Android, System > Android源码分析:Java层对Binder的封装

Android源码分析:Java层对Binder的封装

2012-02-03 22:43 星期五    浏览: 2,626    绿 发表评论 阅读评论

Java层对Binder的封装

Java层对Binder进行了封装,使Java层亦可使用Binder IPC。主要的几个Java类有:IBinder定义了接口,BinderBinderProxy类实现了该接口类。Java层的Parcel类也是对C++Parcel类的简单包裹。它们很多成员函数是通过native的方式实现的,也就是说调用到下面的JNI层。它们的JNI层实现均放在文件frameworks/core/jni/android_util_Binder.cpp中。

JNI层中,有个子类JavaBBinder,继承自BBinder,因为重载了onTransact函数,所以来自Client侧的API事务请求,最终调用到其onTransact函数,它又调用了Java中的Binder类的execTransact函数,继而JavaBinderonTransact函数被调用。因此,在Java层的Binder子类重载onTransact函数时,让其调用server侧实现的各种来自Client侧的API请求,这样,就达到了在Java层中实现server侧的事务请求的目的。

JNI层中还有个类叫JavaBBinderHolder,用于承放JavaBBinder对象,它里面包含一个JavaBBinder对象的弱指针,这个弱指针指向的是一个JavaBBinder对象。而指向这个Holder的指针则存放于JavaBinder类中的mObject整型值中。也就是说,Java层中的Binder类的私有整型成员变量mObject的值,实际用来指向JNIC++JavaBBinderHolder对象,而后者又用来存放或创建JavaBBinder对象弱指针。

又因为创建JavaBBinderHolder对象和JavaBBinder对象时,JavaBinder的实例传递给了它们的构造函数,所以C++JavaBBinder中的mObject又指向的是JavaBinder实例。下图是它们的指向关系:

 

Binder

int mObject;

 

 

 

 

 

BBinder

 

 

 

JavaBBinderHolder

wp<JavaBBinder> mBinder;

 

 

 

 

JavaBBinder

jobject const mObject;

 

 

 

 

 

Java层的BinderProxy类中也有个私有整型成员变量mObject,它存放的是IBinder类型的指针,实际指向的是C++中的BpProxy对象。具体如下:

当某侧希望读取对方的binder时(回想libbinder库:server侧直接将指针转换得到BBinder对象,client侧则是根据handle索引创建BpBinder对象作为server侧的BinderClient侧的通讯代理)。这个读取动作具体到Java层,也就是先使用C++中的Parcel读取binder设备中的某个IBinder对象时,然后将IBinder指针转化对应的在Java层中的类实例(BinderBinderProxy的类实例),也就是调用JNI层的android_os_Parcel_readStrongBinder所完成的功能:

static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)

{

Parcel* parcel = parcelForJavaObject(env, clazz);

if (parcel != NULL) {

return javaObjectForIBinder(env, parcel->readStrongBinder());

}

return NULL;

}

 

Client侧从对方读取IBinder时,也就是读取handle这个句柄索引然后创建BpBinder代理对象,并将其转换为IBinder父类指针后返回,这就是C++Parcel所做的:parcel->readStrongBinder();然后调用javaObjectForIBinder函数创建一个Java的类BinderProxy实例并返回,并将BpBinder对象这个IBinder指针值存放于JavaBinderProxy的整型成员变量mObject中。也就是说,C++中的BpProxyJava层中,以BinderProxy类这个面目出现,BinderProxymObject的值就是BpBroxy对象的指针。实际在javaObjectForIBinder函数中,上述得到BinderProxy类实例的动作,只是client侧;若是server侧,则返回的是JavaBinder的实例,因为在server侧得到是JavaBBinder对象,因而可以返回JavaBinder的实例,见JavaBBindermObject成员变量。

 

 

 

 

下面以IMediaPlaybackService这个AIDL文件,经过处理后会生成一个java文件:out/target/common/obj/APPS/Music_intermediates/src/src/com/android/music/IMediaPlaybackService.java

生成的java文件中包含了接口类IMediaPlaybackService,它继承了接口android.os.IInterface。有两个类实现了它的接口,一个是嵌套类Stub,它继承自android.os.Binder类,实现了asBinder接口。另一个是Proxy类,它又嵌套在Stub类里面,实现了IMediaPlaybackService中定义的所有接口。类似于本地(native)中的Binder,接口类IMediaPlaybackService如同native中的C++抽象类,定义了跨进程调用的函数接口;嵌套类Proxy相当于native中的BpXXXService,实际通过它向远程发起API调用,而具体的Binder通讯在client侧则是android.os.BinderProxy,相当于native实现中的BpBinder,实际上BinderProxy中的一个成员变量mObject就是BpBinder对象的指针值。android.os.Binder扮演着native中的的BBinder的角色,Stub类则扮演着native中的BnInterface这个模板类的角色。来自于Client侧的请求,经过API对应的整数枚举后,在Stub中的onTransact中分发给其子类重载的成员去执行,亦即MeidaPlaybackService中的嵌套类ServiceStub去执行。这样,就是实现了Java层的跨进程调用。

 

 

作为IInterfaceIMediaPlaybackService接口的两个实现者子类StubProxy,都实现了android.os.IInterface中定义的函数asBinderStub中返回的就是自身thisProxy中返回的是mRemote,亦即创建Proxy时传递进来的代理实例,也就是android.os.BinderProxy的实例。也就是说,android.os.Binder的子类Stubandroid.os.BinderProxy都是一种IBinder,它们分别代表着Binder IPC通讯在server侧和client侧的通讯实体。反过来,我们也可以由IBinder实体,得到对应的接口类实例(Stub类或Proxy类的实例),这就是IMediaPlaybackService中的asInterface的功能:

MediaPlaybackService中的ServiceStub子类完成来自client端的API调用请求,它实际又将这些调用转向MediaPlaybackService,后者又调用MediaPlayer这个播放器,MediaPlayer则通过JNI调用native实现。

注意,MediaPlaybackService如系统里的service是相区别的。它的作用是:当应用程序UI退出后,也就是UI对应的Activity销毁后,音乐播放能在后台执行。它是继承自SDK中的Service类(也就是android.app.Service类),提供给应用开发者一个API类。也就是说,应用开发者编写的service(继承自android.app.Service),不是系统级别的service,它与SystemServer.java中的系统级的Service是有区别的,二者不是同一个概念。SystemServer中的用Java写的service继承自android.os.BinderIXXX.Stub(如IMediaPlaybackService.Stub),相当于native中的各个service

public static com.android.music.IMediaPlaybackService asInterface(android.os.IBinder obj)

{

if ((obj==null)) {

return null;

}

android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);//若传递进来的实参obj就是android.os.Binder实例(server侧),则查询返回Stub类的this实例,即iinStub实例本身;否则obj若是android.os.BinderProxy实例,则返回空,即iin为空

if (((iin!=null)&&(iin instanceof com.android.music.IMediaPlaybackService))) {

return ((com.android.music.IMediaPlaybackService)iin);

}

return new com.android.music.IMediaPlaybackService.Stub.Proxy(obj);//obj实际是IBinder的另一个子类android.os.BinderProxy,则创建Proxy实例

}

本文链接地址: http://blog.redwolf-soft.com/?p=904

原创文章,版权©红狼博客所有, 转载随意,但请注明出处。

    分享到:

相关文章:

  • 无相关文章
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.
订阅评论
  欢迎参与讨论,请在这里发表您的看法、交流您的观点。