Android Java Binder 通信机制

Binder 系统可以运行在Android Native环境,但在Java虚拟机中却运行不了。因此,要在Java环境中使用Binder通信,就需要调用一些JNI native函数(/android_runtime/android_util_Binder.cpp)

 

获取IServiceManager

ServiceManager.java文件管理着Java层的所有服务。如果要调用ServiceManager.java中的任何函数,都必须先获取到IserviceManager这个接口。

private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }

BinderInternal.getContextObject 是一个定义为android_os_BinderInternal_getContextObject JNI native函数。通过调用C++层的binder system, 它可以获取到一个IBinder(实际上它是指向C++层的BpServiceManager),然后通过调用javaObjectForIBinder,就可以创建一个java类,从而代替C++中的IBinder对象。

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) { sp<IBinder> b = ProcessState::self()->getContextObject(NULL); return javaObjectForIBinder(env, b); }

javaObjectForIBinder首先会判断这个object对象是service提供者还是service的使用者。在getIServiceManager中,这个object是一个服务使用者,因此它会new一个java BinderProxy object来取代C++环境中的IBinder object。

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { 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; }

就这样,现在我们就有了个Java 的BinderProxy object。 ServiceManagerNative.asInterface将会在BinderProxy 对象中new一个ServiceManagerProxy。

static public IServiceManager asInterface(IBinder obj) { return new ServiceManagerProxy(obj); }

因此,调用getIServiceManager将最终返回个ServiceManagerProxy实例。

 

创建Service

当创建Java service 对象(派生于Binder)时,将会调用init native函数android_os_Binder_init(请参考Binder.java)。在这里它会new一个JavaBBinderHoder,目前可能用不到,但在后面会派上用场。

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); }

 

 添加Service RPC调用

任何Java层的service都应该调用IServiceManager.addService 这个API函数来注册自身的服务。IServiceManager.addService其实就等于ServiceManagerProxy.addService这个函数。

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(); }

 在调用ServiceManagerProxy.addService过程中,java中的service object会被写入到Parcel容器中,并最终调用到android_os_Parcel_writerStrongBinder这个Native函数。

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); } } }

android_os_Parcel_writeStrongBinder通过调用ibinderForJavaObject来产生一个JavaBBinderHolder object,它的功能相当于C++层的IBinder object。

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; }

JavaBBinderHolder将最终new一个JavaBBinder实例。

sp<JavaBBinder> get(JNIEnv* env) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, mObject); mBinder = b; LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d/n", b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount()); } return b; }

JavaBBinder object派生于BBinder。调用完ibinderForJavaObject之后,Android就已经在JAVA层的service类中创建了一个C++层的BBinder对象。

 

接着,ServiceManagerProxy会调用BinderProxy JNI native函数android_os_BinderProxy_transact来实现JAVA到C++之间的PRC调用。在这个函数中,C++中的IBinder object(实际上就是之前提到的BpServiceManager对象)对应于Java 中的BinderProxy,它原先保存在javaObjectForIBinder中。

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) { 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; }

到现在为止,Android已经可以把Java层的RPC调用发送到C++层了。RPC调用将会交由service_manager进程来处理。至于C++层的处理过程将不在本文的讨论范围之内,有兴趣的话可以参考作者关于C++层Binder 系统原理介绍的文章。

 

获取IsensorService服务

获取一个接口(interface)的唯一方式是通过调用IserviceManager.getService函数。过程类似于调用IServiceManager.addService。Java 的ServiceManagerProxy把RPC发送给C++层的BpServiceManager,BpServiceManager会把调用发送到service_manager进程。BpServiceManager会接着进行执行。返回的C++层的IBinder object实际上就是一个BpBinder实例。

virtual sp<IBinder> getService(const String16& name) const { unsigned n; for (n = 0; n < 5; n++){ sp<IBinder> svc = checkService(name); if (svc != NULL) return svc; LOGI("Waiting for sevice %s.../n", String8(name).string()); sleep(1); } return NULL; } virtual sp<IBinder> checkService( const String16& name) const { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder(); }

 

接收到transact之后,ServiceManagerProxy会调用JNI native函数android_os_Parcel_readStrongBinder。这个函数会调用javaObjectForIBinder函数来为返回的C++ IBinder object创建一个Java 对象。

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; }

javaObjectForIBinder会判断object属于service提供者还是服务使用者。在这里,这个object对象是个服务使用者。因此,它会new一个Java BinderProxy object来代表C++中的IBinder object。这样,我们就获得了一个Java BinderProxy对象。接着,ISensorService.Stub.asInterface会在BinderProxy对象中new一个ISensorService.Stub.Proxy。

/** * Cast an IBinder object into an ISensorService interface, * generating a proxy if needed. */ public static android.hardware.ISensorService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.hardware.ISensorService in = (android.hardware.ISensorService)obj.queryLocalInterface(DESCRIPTOR); if ((in!=null)) { return in; } return new android.hardware.ISensorService.Stub.Proxy(obj); }

这样,我们就获得了一个ISensorService.Stub.Proxy实例。

 

ISensorService.reportAccurary RPC调用

这等同于调用ISensorService.Stub.Proxy.reportAccuracy。它的代码是通过aidl语言自动生成的。它调用BinderProxy 的JNI native函数android_os_BinderProxy_transact来把JAVA中的RPC调用派发到C++中。就这样,Android完成了JAVA到C++之间的RPC调用。

 

处理ISensorService.reportAccuracy RPC调用

RPC调用将由C++层的JavaBBinder object处理,JavaBBinder object会在调用IServiceManager.addService时创建。

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); jthrowable excep = env->ExceptionOccurred(); if (excep) { report_exception(env, excep, "*** Uncaught remote exception! " "(Exceptions are not yet supported across processes.)"); res = JNI_FALSE; /* clean up JNI local ref -- we don't return to Java */ env->DeleteLocalRef(excep); }

JavaBBinder会通过JNI调用到Java层的函数。这个函数是Binder.executeTransact。

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; } reply.recycle(); data.recycle(); return res; }

最终,Binder.executeTransact会调用到ISensorService.onTransact。ISensorService.onTransact会调用到SensorService.reportAccuracy来执行实际的工作。

 

原文转载地址:http://blog.chinaunix.net/space.php?uid=20564848&do=blog&id=73517

First written by Steve Guo, please keep the mark if forwarding.

你可能感兴趣的:(Android Java Binder 通信机制)