Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
在前面几篇文章中,我们详细介绍了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的形式,并且通过iservicemanager.addservice接口来把这个service添加到service manager,client也是通过iservicemanager.getservice接口来获得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远程接口的。
接下来,我们就看一下servicemanager.getiservicemanager这个函数的实现,这个函数定义在frameworks/base/core/java/android/os/servicemanager.java文件中:
public final class servicemanager { ...... private static iservicemanager sservicemanager; ...... private static iservicemanager getiservicemanager() { if (sservicemanager != null) { return sservicemanager; } // find the service manager sservicemanager = servicemanagernative.asinterface(binderinternal.getcontextobject()); return sservicemanager; } ...... }
如果其静态成员变量sservicemanager尚未创建,那么就调用servicemanagernative.asinterface函数来创建。在调用servicemanagernative.asinterface函数之前,首先要通过binderinternal.getcontextobject函数来获得一个binderproxy对象。
我们来看一下binderinternal.getcontextobject的实现,这个函数定义在frameworks/base/core/java/com/android/internal/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是一个jni方法,它实现在frameworks/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::self()->getcontextobject函数,具体可以参考浅谈android系统进程间通信(ipc)机制binder中的server和client获得service manager接口之路一文。processstate::self()->getcontextobject函数返回一个bpbinder对象,它的句柄值是0,即下面语句:
sp<ibinder> b = processstate::self()->getcontextobject(null);
相当于是:
sp<ibinder> b = new bpbinder(0);
接着调用javaobjectforibinder把这个bpbinder对象转换成一个binderproxy对象:
jobject javaobjectforibinder(jnienv* env, const sp<ibinder>& val) { if (val == null) return null; if (val->checksubclass(&gbinderoffsets)) { // one of our own! jobject object = static_cast<javabbinder*>(val.get())->object(); //printf("objectforbinder %p: it's our own %p!\n", val.get(), object); return object; } // for the rest of the function we will hold this lock, to serialize // looking/creation of java proxies for native binder proxies. automutex _l(mproxylock); // someone else's... do we know about it? jobject object = (jobject)val->findobject(&gbinderproxyoffsets); if (object != null) { jobject res = env->callobjectmethod(object, gweakreferenceoffsets.mget); if (res != null) { logv("objectforbinder %p: found existing %p!\n", val.get(), res); return res; } logv("proxy object %p of ibinder %p no longer in working set!!!", object, val.get()); android_atomic_dec(&gnumproxyrefs); val->detachobject(&gbinderproxyoffsets); env->deleteglobalref(object); } object = env->newobject(gbinderproxyoffsets.mclass, gbinderproxyoffsets.mconstructor); if (object != null) { logv("objectforbinder %p: created new %p!\n", val.get(), object); // the proxy holds a reference to the native object. env->setintfield(object, gbinderproxyoffsets.mobject, (int)val.get()); val->incstrong(object); // the native object needs to hold a weak reference back to the // proxy, so we can retrieve the same proxy if it is still active. jobject refobject = env->newglobalref( env->getobjectfield(object, gbinderproxyoffsets.mself)); val->attachobject(&gbinderproxyoffsets, refobject, jnienv_to_javavm(env), proxy_cleanup); // note that a new object reference has been created. android_atomic_inc(&gnumproxyrefs); increfscreated(env); } return object; }
在介绍这个函数之前,先来看两个变量gbinderoffsets和gbinderproxyoffsets的定义。
先看gbinderoffsets的定义:
static struct bindernative_offsets_t { // class state. jclass mclass; jmethodid mexectransact; // object state. jfieldid mobject; } gbinderoffsets;
简单来说,gbinderoffsets变量是用来记录上面第二个类图中的binder类的相关信息的,它是在注册binder类的jni方法的int_register_android_os_binder函数初始化的:
const char* const kbinderpathname = "android/os/binder"; static int int_register_android_os_binder(jnienv* env) { jclass clazz; clazz = env->findclass(kbinderpathname); log_fatal_if(clazz == null, "unable to find class android.os.binder"); gbinderoffsets.mclass = (jclass) env->newglobalref(clazz); gbinderoffsets.mexectransact = env->getmethodid(clazz, "exectransact", "(iiii)z"); assert(gbinderoffsets.mexectransact); gbinderoffsets.mobject = env->getfieldid(clazz, "mobject", "i"); assert(gbinderoffsets.mobject); return androidruntime::registernativemethods( env, kbinderpathname, gbindermethods, nelem(gbindermethods)); }
再来看gbinderproxyoffsets的定义:
static struct binderproxy_offsets_t { // class state. jclass mclass; jmethodid mconstructor; jmethodid msenddeathnotice; // object state. jfieldid mobject; jfieldid mself; } gbinderproxyoffsets;
简单来说,gbinderproxyoffsets是用来变量是用来记录上面第一个图中的binderproxy类的相关信息的,它是在注册binderproxy类的jni方法的int_register_android_os_binderproxy函数初始化的:
const char* const kbinderproxypathname = "android/os/binderproxy"; static int int_register_android_os_binderproxy(jnienv* env) { jclass clazz; clazz = env->findclass("java/lang/ref/weakreference"); log_fatal_if(clazz == null, "unable to find class java.lang.ref.weakreference"); gweakreferenceoffsets.mclass = (jclass) env->newglobalref(clazz); gweakreferenceoffsets.mget = env->getmethodid(clazz, "get", "()ljava/lang/object;"); assert(gweakreferenceoffsets.mget); clazz = env->findclass("java/lang/error"); log_fatal_if(clazz == null, "unable to find class java.lang.error"); gerroroffsets.mclass = (jclass) env->newglobalref(clazz); clazz = env->findclass(kbinderproxypathname); log_fatal_if(clazz == null, "unable to find class android.os.binderproxy"); gbinderproxyoffsets.mclass = (jclass) env->newglobalref(clazz); gbinderproxyoffsets.mconstructor = env->getmethodid(clazz, "<init>", "()v"); assert(gbinderproxyoffsets.mconstructor); gbinderproxyoffsets.msenddeathnotice = env->getstaticmethodid(clazz, "senddeathnotice", "(landroid/os/ibinder$deathrecipient;)v"); assert(gbinderproxyoffsets.msenddeathnotice); gbinderproxyoffsets.mobject = env->getfieldid(clazz, "mobject", "i"); assert(gbinderproxyoffsets.mobject); gbinderproxyoffsets.mself = env->getfieldid(clazz, "mself", "ljava/lang/ref/weakreference;"); assert(gbinderproxyoffsets.mself); return androidruntime::registernativemethods( env, kbinderproxypathname, gbinderproxymethods, nelem(gbinderproxymethods)); }
回到前面的javaobjectforibinder函数中,下面这段代码:
if (val->checksubclass(&gbinderoffsets)) { // one of our own! jobject object = static_cast<javabbinder*>(val.get())->object(); //printf("objectforbinder %p: it's our own %p!\n", val.get(), object); return object; }
前面说过,这里传进来的参数是一个bpbinder的指针,而bpbinder::checksubclass继承于父类ibinder::checksubclass,它什么也不做就返回false。
于是函数继续往下执行:
jobject object = (jobject)val->findobject(&gbinderproxyoffsets);
由于这个bpbinder对象是第一创建,它里面什么对象也没有,因此,这里返回的object为null。
于是函数又继续往下执行:
object = env->newobject(gbinderproxyoffsets.mclass, gbinderproxyoffsets.mconstructor);
这里,就创建了一个binderproxy对象了。创建了之后,要把这个bpbinder对象和这个binderproxy对象关联起来:
env->setintfield(object, gbinderproxyoffsets.mobject, (int)val.get());
就是通过binderproxy.mobject成员变量来关联的了,binderproxy.mobject成员变量记录了这个bpbinder对象的地址。
接下去,还要把它放到bpbinder里面去,下次就要使用时,就可以在上一步调用bpbinder::findobj把它找回来了:
val->attachobject(&gbinderproxyoffsets, refobject,
jnienv_to_javavm(env), proxy_cleanup);
最后,就把这个binderproxy返回到android_os_binderinternal_getcontextobject函数,最终返回到最开始的servicemanager.getiservicemanager函数中来了,于是,我们就获得一个binderproxy对象了。
回到servicemanager.getiservicemanager中,从下面语句返回:
sservicemanager = servicemanagernative.asinterface(binderinternal.getcontextobject());
相当于是:
sservicemanager = servicemanagernative.asinterface(new binderproxy());
接下去就是调用servicemanagernative.asinterface函数了,这个函数定义在frameworks/base/core/java/android/os/servicemanagernative.java文件中:
public abstract class servicemanagernative ...... { ...... 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); } ...... }
这里的参数obj是一个binderproxy对象,它的querylocalinterface函数返回null。因此,最终以这个binderproxy对象为参数创建一个servicemanagerproxy对象。
返回到servicemanager.getiservicemanager中,从下面语句返回:
sservicemanager = servicemanagernative.asinterface(new binderproxy());
就相当于是:
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/ihelloservice.aidl文件中:
package android.os; interface ihelloservice { void setval(int val); int getval(); }
这个服务接口很简单,只有两个函数,分别用来读写硬件寄存器。
注意,这是一个aidl文件,编译后会生成一个ihelloservice.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。
/* * this file is auto-generated. do not modify. * original file: frameworks/base/core/java/android/os/ihelloservice.aidl */ package android.os; public interface ihelloservice extends android.os.iinterface { /** local-side ipc implementation stub class. */ public static abstract class stub extends android.os.binder implements android.os.ihelloservice { private static final java.lang.string descriptor = "android.os.ihelloservice"; /** construct the stub at attach it to the interface. */ public stub() { this.attachinterface(this, descriptor); } /** * cast an ibinder object into an android.os.ihelloservice interface, * generating a proxy if needed. */ public static android.os.ihelloservice asinterface(android.os.ibinder obj) { if ((obj==null)) { return null; } android.os.iinterface iin = (android.os.iinterface)obj.querylocalinterface(descriptor); if (((iin!=null)&&(iin instanceof android.os.ihelloservice))) { return ((android.os.ihelloservice)iin); } return new android.os.ihelloservice.stub.proxy(obj); } public android.os.ibinder asbinder() { return this; } @override 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_setval: { data.enforceinterface(descriptor); int _arg0; _arg0 = data.readint(); this.setval(_arg0); reply.writenoexception(); return true; } case transaction_getval: { data.enforceinterface(descriptor); int _result = this.getval(); reply.writenoexception(); reply.writeint(_result); return true; } } return super.ontransact(code, data, reply, flags); } private static class proxy implements android.os.ihelloservice { private android.os.ibinder mremote; proxy(android.os.ibinder remote) { mremote = remote; } public android.os.ibinder asbinder() { return mremote; } public java.lang.string getinterfacedescriptor() { return descriptor; } public void setval(int val) throws android.os.remoteexception { android.os.parcel _data = android.os.parcel.obtain(); android.os.parcel _reply = android.os.parcel.obtain(); try { _data.writeinterfacetoken(descriptor); _data.writeint(val); mremote.transact(stub.transaction_setval, _data, _reply, 0); _reply.readexception(); } finally { _reply.recycle(); _data.recycle(); } } public int getval() throws android.os.remoteexception { android.os.parcel _data = android.os.parcel.obtain(); android.os.parcel _reply = android.os.parcel.obtain(); int _result; try { _data.writeinterfacetoken(descriptor); mremote.transact(stub.transaction_getval, _data, _reply, 0); _reply.readexception(); _result = _reply.readint(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int transaction_setval = (android.os.ibinder.first_call_transaction + 0); static final int transaction_getval = (android.os.ibinder.first_call_transaction + 1); } public void setval(int val) throws android.os.remoteexception; public int getval() throws android.os.remoteexception; }
这里我们可以看到ihelloservice.aidl这个文件编译后的真面目,原来就是根据ihelloservice接口的定义生成相应的stub和proxy类,这个就是我们熟悉的binder机制的内容了,即实现这个helloservice的server必须继续于这里的ihelloservice.stub类,而这个helloservice的远程接口就是这里的ihelloservice.stub.proxy对象获得的ihelloservice接口。接下来的内容,我们就可以看到ihelloservice.stub和ihelloservice.stub.proxy是怎么创建或者使用的。
三. helloservice的启动过程
在讨论helloservice的启动过程之前,我们先来看一下实现helloservice接口的server是怎么定义的。
回忆在ubuntu上为android系统的application frameworks层增加硬件访问服务一文,我们在frameworks/base/services/java/com/android/server目录下新增了一个helloservice.java文件:
package com.android.server; import android.content.context; import android.os.ihelloservice; import android.util.slog; public class helloservice extends ihelloservice.stub { private static final string tag = "helloservice"; helloservice() { init_native(); } public void setval(int val) { setval_native(val); } public int getval() { return getval_native(); } private static native boolean init_native(); private static native void setval_native(int val); private static native int getval_native(); }
这里,我们可以看到,helloservice继续了ihelloservice.stub类,它通过本地方法调用实现了getval和setval两个函数。我们不关心这两个函数的具体实现,有兴趣的读者可以参考在ubuntu上为android系统的application frameworks层增加硬件访问服务一文。
有了helloservice这个server类后,下一步就是考虑怎么样把它启动起来了。在frameworks/base/services/java/com/android/server/systemserver.java文件中,定义了systemserver类。systemserver对象是在系统启动的时候创建的,它被创建的时候会启动一个线程来创建helloservice,并且把它添加到service manager中去。
我们来看一下这部份的代码:
class serverthread extends thread { ...... @override public void run() { ...... looper.prepare(); ...... try { slog.i(tag, "hello service"); servicemanager.addservice("hello", new helloservice()); } catch (throwable e) { slog.e(tag, "failure starting hello service", e); } ...... looper.loop(); ...... } } ...... public class systemserver { ...... /** * this method is called from zygote to initialize the system. this will cause the native * services (surfaceflinger, audioflinger, etc..) to be started. after that it will call back * up into init2() to start the android services. */ native public static void init1(string[] args); ...... public static final void init2() { slog.i(tag, "entered the android system server!"); thread thr = new serverthread(); thr.setname("android.server.serverthread"); thr.start(); } ...... }
这里,我们可以看到,在serverthread.run函数中,执行了下面代码把helloservice添加到service manager中去。这里我们关注把helloservice添加到service manager中去的代码:
try { slog.i(tag, "hello service"); servicemanager.addservice("hello", new helloservice()); } catch (throwable e) { slog.e(tag, "failure starting hello service", e); }
通过调用servicemanager.addservice把一个helloservice实例添加到service manager中去。
我们先来看一下helloservice的创建过程:
new helloservice();
这个语句会调用helloservice类的构造函数,而helloservice类继承于ihelloservice.stub类,ihelloservice.stub类又继承了binder类,因此,最后会调用binder类的构造函数:
public class binder implements ibinder { ...... private int mobject; ...... public binder() { init(); ...... } private native final void init(); ...... }
这里调用了一个jni方法init来初始化这个binder对象,这个jni方法定义在frameworks/base/core/jni/android_util_binder.cpp文件中:
static void android_os_binder_init(jnienv* env, jobject clazz) { javabbinderholder* jbh = new javabbinderholder(env, clazz); if (jbh == null) { jnithrowexception(env, "java/lang/outofmemoryerror", null); return; } logv("java binder %p: acquiring first ref on holder %p", clazz, jbh); jbh->incstrong(clazz); env->setintfield(clazz, gbinderoffsets.mobject, (int)jbh); }
它实际上只做了一件事情,就是创建一个javabbinderholder对象jbh,然后把这个对象的地址保存在上面的binder类的mobject成员变量中,后面我们会用到。
回到serverthread.run函数中,我们再来看一下servicemanager.addservice函数的实现:
public final class servicemanager { ...... private static iservicemanager sservicemanager; ...... public static void addservice(string name, ibinder service) { try { getiservicemanager().addservice(name, service); } catch (remoteexception e) { log.e(tag, "error in addservice", e); } } ...... }
这里的getiservicemanager函数我们在前面已经分析过了,它返回的是一个servicemanagerproxy对象的iservicemanager接口。因此,我们进入到servicemanagerproxy.addservice中去看看:
class servicemanagerproxy implements iservicemanager { public servicemanagerproxy(ibinder remote) { mremote = remote; } ...... public void addservice(string name, ibinder service) throws remoteexception { parcel data = parcel.obtain(); parcel reply = parcel.obtain(); data.writeinterfacetoken(iservicemanager.descriptor); data.writestring(name); data.writestrongbinder(service); mremote.transact(add_service_transaction, data, reply, 0); reply.recycle(); data.recycle(); } ...... private ibinder mremote; }
这里的parcel类是用java来实现的,它跟我们前面几篇文章介绍binder机制时提到的用c++实现的parcel类的作用是一样的,即用来在两个进程之间传递数据。
这里我们关注是如何把参数service写到data这个parcel对象中去的:
data.writestrongbinder(service);
我们来看看parcel.writestrongbinder函数的实现:
public final class parcel { ...... /** * write an object into the parcel at the current dataposition(), * growing datacapacity() if needed. */ public final native void writestrongbinder(ibinder val); ...... }
这里的writestrongbinder函数又是一个jni方法,它定义在frameworks/base/core/jni/android_util_binder.cpp文件中:
static void android_os_parcel_writestrongbinder(jnienv* env, jobject clazz, jobject object) { parcel* parcel = parcelforjavaobject(env, clazz); if (parcel != null) { const status_t err = parcel->writestrongbinder(ibinderforjavaobject(env, object)); if (err != no_error) { jnithrowexception(env, "java/lang/outofmemoryerror", null); } } }
这里的clazz参数是一个java语言实现的parcel对象,通过parcelforjavaobject把它转换成c++语言实现的parcel对象。这个函数的实现我们就不看了,有兴趣的读者可以研究一下,这个函数也是实现在frameworks/base/core/jni/android_util_binder.cpp这个文件中。
这里的object参数是一个java语言实现的binder对象,在调用c++语言实现的parcel::writestrongbinder把这个对象写入到parcel对象时,首先通过ibinderforjavaobject函数把这个java语言实现的binder对象转换为c++语言实现的javabbinderholder对象:
sp<ibinder> ibinderforjavaobject(jnienv* env, jobject obj) { if (obj == null) return null; if (env->isinstanceof(obj, gbinderoffsets.mclass)) { javabbinderholder* jbh = (javabbinderholder*) env->getintfield(obj, gbinderoffsets.mobject); return jbh != null ? jbh->get(env) : null; } if (env->isinstanceof(obj, gbinderproxyoffsets.mclass)) { return (ibinder*) env->getintfield(obj, gbinderproxyoffsets.mobject); } logw("ibinderforjavaobject: %p is not a binder object", obj); return null; }
我们知道,这里的obj参数是一个binder类的实例,因此,这里会进入到第一个if语句中去。
在前面创建helloservice对象,曾经在调用到helloservice的父类binder中,曾经在jni层创建了一个javabbinderholder对象,然后把这个对象的地址保存在binder类的mobject成员变量中,因此,这里把obj对象的mobject成员变量强制转为javabbinderholder对象。
到了这里,这个函数的功课还未完成,还剩下最后关键的一步:
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函数的实现:
class javabbinderholder : public refbase { ...... javabbinderholder(jnienv* env, jobject object) : mobject(object) { ...... } ...... sp<javabbinder> get(jnienv* env) { automutex _l(mlock); sp<javabbinder> b = mbinder.promote(); if (b == null) { b = new javabbinder(env, mobject); mbinder = b; ...... } return b; } ...... jobject mobject; wp<javabbinder> mbinder; };
这里是第一次调用get函数,因此,会创建一个javabbinder对象,并且保存在mbinder成员变量中。注意,这里的mobject就是上面创建的helloservice对象了,这是一个java对象。这个helloservice对象最终也会保存在javabbinder对象的成员变量mobject中。
回到android_os_parcel_writestrongbinder函数中,下面这个语句:
const status_t err = parcel->writestrongbinder(ibinderforjavaobject(env, object));
相当于是:
const status_t err = parcel->writestrongbinder((javabbinderhodler*)(obj.mobject));
因此,这里的效果相当于是写入了一个javabbinder类型的binder实体到parcel中去。这与我们前面介绍的binder机制的c++实现是一致的。
接着,再回到servicemanagerproxy.addservice这个函数中,最后它通过其成员变量mremote来执行进程间通信操作。前面我们在介绍如何获取service manager远程接口时提到,这里的mremote成员变量实际上是一个binderproxy对象,因此,我们再来看看binderproxy.transact函数的实现:
final class binderproxy implements ibinder { ...... public native boolean transact(int code, parcel data, parcel reply, int flags) throws remoteexception; ...... }
这里的transact成员函数又是一个jni方法,它定义在frameworks/base/core/jni/android_util_binder.cpp文件中:
static jboolean android_os_binderproxy_transact(jnienv* env, jobject obj, jint code, jobject dataobj, jobject replyobj, jint flags) { ...... parcel* data = parcelforjavaobject(env, dataobj); if (data == null) { return jni_false; } parcel* reply = parcelforjavaobject(env, replyobj); if (reply == null && replyobj != null) { return jni_false; } ibinder* target = (ibinder*) env->getintfield(obj, gbinderproxyoffsets.mobject); if (target == null) { jnithrowexception(env, "java/lang/illegalstateexception", "binder has been finalized!"); return jni_false; } ...... status_t err = target->transact(code, *data, reply, flags); ...... if (err == no_error) { return jni_true; } else if (err == unknown_transaction) { return jni_false; } signalexceptionforerror(env, obj, err); return jni_false; }
这里传进来的参数dataobj和replyobj是一个java接口实现的parcel类,由于这里是jni层,需要把它转换为c++实现的parcel类,它们就是通过我们前面说的parcelforjavaobject函数进行转换的。
前面我们在分析如何获取service manager远程接口时,曾经说到,在jni层中,创建了一个bpbinder对象,它的句柄值为0,它的地址保存在gbinderproxyoffsets.mobject中,因此,这里通过下面语句得到这个bpbinder对象的ibinder接口:
ibinder* target = (ibinder*)
env->getintfield(obj, gbinderproxyoffsets.mobject);
有了这个ibinder接口后,就和我们前面几篇文章介绍binder机制的c/c++实现一致了。
最后,通过bpbinder::transact函数进入到binder驱动程序,然后binder驱动程序唤醒service manager响应这个add_service_transaction请求:
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函数,通过iservicemanager.getservice函数来获得helloservice的远程接口:
public class hello extends activity implements onclicklistener { ...... private ihelloservice helloservice = null; ...... @override public void oncreate(bundle savedinstancestate) { helloservice = ihelloservice.stub.asinterface( servicemanager.getservice("hello")); } ...... }
我们先来看servicemanager.getservice的实现。前面我们说过,这里实际上是调用了servicemanagerproxy.getservice函数:
class servicemanagerproxy implements iservicemanager { public servicemanagerproxy(ibinder remote) { mremote = remote; } ...... public ibinder getservice(string name) throws remoteexception { parcel data = parcel.obtain(); parcel reply = parcel.obtain(); data.writeinterfacetoken(iservicemanager.descriptor); data.writestring(name); mremote.transact(get_service_transaction, data, reply, 0); ibinder binder = reply.readstrongbinder(); reply.recycle(); data.recycle(); return binder; } ...... private ibinder mremote; }
最终通过mremote.transact来执行实际操作。我们在前面已经介绍过了,这里的mremote实际上是一个binderproxy对象,它的transact成员函数是一个jni方法,实现在frameworks/base/core/jni/android_util_binder.cpp文件中的android_os_binderproxy_transact函数中。
这个函数前面我们已经看到了,这里就不再列出来了。不过,当这个函数从:
status_t err = target->transact(code, *data, reply, flags);
这里的reply变量里面就包括了一个helloservice的引用了。注意,这里的reply变量就是我们在servicemanagerproxy.getservice函数里面传进来的参数reply,它是一个parcel对象。
回到servicemanagerproxy.getservice函数中,从下面语句返回:
mremote.transact(get_service_transaction, data, reply, 0);
接着,就通过下面语句将这个helloservice的引用读出来:
ibinder binder = reply.readstrongbinder();
我们看看parcel.readstrongbinder的实现:
public final class parcel { ...... /** * read an object from the parcel at the current dataposition(). */ public final native ibinder readstrongbinder(); ...... }
它也是一个jni方法,实现在frameworks/base/core/jni/android_util_binder.cpp文件中:
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; }
这里首先把java语言实现的parcel对象class转换成c++语言实现的parcel对象parcel,接着,通过parcel->readstrongbinder函数来获得一个binder引用。
我们在前面学习binder机制时,在android系统进程间通信(ipc)机制binder中的client获得server远程接口过程源代码分析这篇文章中,曾经分析过这个函数,它最终返回来的是一个bpbinder对象,因此,下面的语句:
return javaobjectforibinder(env, parcel->readstrongbinder());
就相当于是:
return javaobjectforibinder(env, new bpbinder(handle));
这里的handle就是helloservice这个binder实体在client进程中的句柄了,它是由binder驱动程序设置的,上层不用关心它的值具体是多少。至于javaobjectforibinder这个函数,我们前面介绍如何获取service manager的java远程接口时已经有详细介绍,这里就不累述了,它的作用就是创建一个binderproxy对象,并且把刚才获得的bpbinder对象的地址保存在这个binderproxy对象的mobject成员变量中。
最后返回到hello.oncreate函数中,从下面语句返回:
helloservice = ihelloservice.stub.asinterface( servicemanager.getservice("hello"));
就相当于是:
helloservice = ihelloservice.stub.asinterface(new binderproxy()));
回忆一下前面介绍ihelloservice接口的定义时,ihelloservice.stub.asinterface是这样定义的:
public interface ihelloservice extends android.os.iinterface { /** local-side ipc implementation stub class. */ public static abstract class stub extends android.os.binder implements android.os.ihelloservice { ...... public static android.os.ihelloservice asinterface(android.os.ibinder obj) { if ((obj==null)) { return null; } android.os.iinterface iin = (android.os.iinterface)obj.querylocalinterface(descriptor); if (((iin!=null)&&(iin instanceof android.os.ihelloservice))) { return ((android.os.ihelloservice)iin); } return new android.os.ihelloservice.stub.proxy(obj); } ...... } }
这里的obj是一个binderproxy对象,它的querylocalinterface返回null,于是调用下面语句获得helloservice的远程接口:
return new android.os.ihelloservice.stub.proxy(obj);
相当于是:
return new android.os.ihelloservice.stub.proxy(new binderproxy());
这样,我们就获得了helloservice的远程接口了,它实质上是一个实现了ihelloservice接口的ihelloservice.stub.proxy对象。
五. client通过helloservice的java远程接口来使用helloservice提供的服务的过程
上面介绍的hello这个activity获得了helloservice的远程接口后,就可以使用它的服务了。
我们以使用ihelloservice.getval函数为例详细说明。在hello::onclick函数中调用了ihelloservice.getval函数:
public class hello extends activity implements onclicklistener { ...... @override public void onclick(view v) { if(v.equals(readbutton)) { int val = helloservice.getval(); ...... } else if(v.equals(writebutton)) { ...... } else if(v.equals(clearbutton)) { ...... } } ...... }
通知前面的分析,我们知道,这里的helloservice接口实际上是一个ihelloservice.stub.proxy对象,因此,我们进入到ihelloservice.stub.proxy类的getval函数中:
public interface ihelloservice extends android.os.iinterface { /** local-side ipc implementation stub class. */ public static abstract class stub extends android.os.binder implements android.os.ihelloservice { ...... private static class proxy implements android.os.ihelloservice { private android.os.ibinder mremote; ...... public int getval() throws android.os.remoteexception { android.os.parcel _data = android.os.parcel.obtain(); android.os.parcel _reply = android.os.parcel.obtain(); int _result; try { _data.writeinterfacetoken(descriptor); mremote.transact(stub.transaction_getval, _data, _reply, 0); _reply.readexception(); _result = _reply.readint(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } ...... static final int transaction_getval = (android.os.ibinder.first_call_transaction + 1); } ...... }
这里我们可以看出,实际上是通过mremote.transact来请求helloservice执行transaction_getval操作。这里的mremote是一个binderproxy对象,这是我们在前面获取helloservice的java远程接口的过程中创建的。
binderproxy.transact函数是一个jni方法,我们在前面已经介绍过了,这里不再累述。最过调用到binder驱动程序,binder驱动程序唤醒helloservice这个server。前面我们在介绍helloservice的启动过程时,曾经提到,helloservice这个server线程被唤醒之后,就会调用javabbinder类的ontransact函数:
class javabbinder : public bbinder { javabbinder(jnienv* env, jobject object) : mvm(jnienv_to_javavm(env)), mobject(env->newglobalref(object)) { ...... } ...... virtual status_t ontransact( uint32_t code, const parcel& data, parcel* reply, uint32_t flags = 0) { jnienv* env = javavm_to_jnienv(mvm); ...... jboolean res = env->callbooleanmethod(mobject, gbinderoffsets.mexectransact, code, (int32_t)&data, (int32_t)reply, flags); ...... return res != jni_false ? no_error : unknown_transaction; } ...... javavm* const mvm; jobject const mobject; };
前面我们在介绍helloservice的启动过程时,曾经介绍过,javabbinder类里面的成员变量mobject就是helloservice类的一个实例对象了。因此,这里通过语句:
jboolean res = env->callbooleanmethod(mobject, gbinderoffsets.mexectransact,
code, (int32_t)&data, (int32_t)reply, flags);
就调用了helloservice.exectransact函数,而helloservice.exectransact函数继承了binder类的exectransact函数:
public class binder implements ibinder { ...... // entry point from android_util_binder.cpp's ontransact private boolean exectransact(int code, int dataobj, int replyobj, int flags) { parcel data = parcel.obtain(dataobj); parcel reply = parcel.obtain(replyobj); // theoretically, we should call transact, which will call ontransact, // but all that does is rewind it, and we just got these from an ipc, // so we'll just call it directly. boolean res; try { res = ontransact(code, data, reply, flags); } catch (remoteexception e) { reply.writeexception(e); res = true; } catch (runtimeexception e) { reply.writeexception(e); res = true; } catch (outofmemoryerror e) { runtimeexception re = new runtimeexception("out of memory", e); reply.writeexception(re); res = true; } reply.recycle(); data.recycle(); return res; } }
这里又调用了ontransact函数来作进一步处理。由于helloservice类继承了ihelloservice.stub类,而ihelloservice.stub类实现了ontransact函数,helloservice类没有实现,因此,最终调用了ihelloservice.stub.ontransact函数:
public interface ihelloservice extends android.os.iinterface { /** local-side ipc implementation stub class. */ public static abstract class stub extends android.os.binder implements android.os.ihelloservice { ...... @override public boolean ontransact(int code, android.os.parcel data, android.os.parcel reply, int flags) throws android.os.remoteexception { switch (code) { ...... case transaction_getval: { data.enforceinterface(descriptor); int _result = this.getval(); reply.writenoexception(); reply.writeint(_result); return true; } } return super.ontransact(code, data, reply, flags); } ...... } }
函数最终又调用了helloservice.getval函数:
public class helloservice extends ihelloservice.stub { ...... public int getval() { return getval_native(); } ...... private static native int getval_native(); }
最终,经过层层返回,就回到ihelloservice.stub.proxy.getval函数中来了,从下面语句返回:
mremote.transact(stub.transaction_getval, _data, _reply, 0);
并将结果读出来:
_result = _reply.readint();
最后将这个结果返回到hello.onclick函数中。
这样,client通过helloservice的java远程接口来使用helloservice提供的服务的过程就介绍完了。
至此,android系统进程间通信binder机制在应用程序框架层的java接口源代码分析也完成了,整个binder机制的学习就结束了。
重新学习android系统进程间通信binder机制,请回到android进程间通信(ipc)机制binder简要介绍和学习计划一文。
以上就是android 系统进程通信binder 机制java接口的源码分析,谢谢大家对本站的支持,后续继续补充相关知识!
下一篇: 【数据预处理】Pandas缺失的数据处理