Binder 通信笔记(Java)
来源:互联网 发布:社会静力学知乎 编辑:程序博客网 时间:2024/06/05 23:14
- 概述
- Service注册
- 获取service_manager代理
- Service的初始化
- addService
- Binder驱动调用Service
- 参考资料
概述
在上一节Binder 通信笔记(native)中,分析了在c++层service和client是怎样与binder驱动通信的。在Android中,绝大部分的应用和很多关键的系统Service是用Java来完成的。这一节,我们分析一下Java层程序是如何使用binder驱动进行通信的。其实Java层的binder通信是基于native的,它只是把binder的“网络层”(BpBinder和BBinder)做了一下封装,通过JNI将业务发送给了上一层。先看以下结构图
可以看到native层的类关系图和上一节下半部分完全相同,java层多了BinderProxy.class和Binder.class将native层的数据传送到上层。这一节我们只分析上半部分代码,下半部分的代码请查看上一节Binder 通信笔记(native)。
Service注册
这一节以ActivityManagerService为例,分析以下Java层Service注册到serviceManager的过程。ActivityManagerService是在SystemServer进程里面注册的,本节以分析binder为主,SystemServer的启动过程这里就不说了,网上有很多资料。大概流程是
SystemServer:main() ->run() ->startBootstrapServices() ->mActivityManagerService.setSystemProcess(); ->ServiceManager.addService("activity", this, true);
下面看一下ServiceManager.addService的实现。
public static void addService(String name, IBinder service, boolean allowIsolated) { try { getIServiceManager().addService(name, service, allowIsolated); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }
获取service_manager代理
在Java层有一个ServiceManager.class作为service_manager的代理,它是如何实现的呢,我们继续跟代码,看一下getIServiceManager()
。
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject()); return sServiceManager; }
ServiceManager是一个单例实现,第一次初始化执行了ServiceManagerNative.asInterface(BinderInternal.getContextObject())
。先看一下括号里吗的参数。BinderInternal.getContextObject()
是一个native函数。它的实现在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(NULL);
上一篇博客已经分析过,它返回了BpBinder(0), 这个0就代表着远程为service_manager。继续看一下javaObjectForIBinder();
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val){ if (val == NULL) return NULL; //1 if (val->checkSubclass(&gBinderOffsets)) { jobject object = static_cast<JavaBBinder*>(val.get())->object(); LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object); return object; } AutoMutex _l(mProxyLock); jobject object = (jobject)val->findObject(&gBinderProxyOffsets); // 2 if (object != NULL) { jobject res = jniGetReferent(env, object); if (res != NULL) { ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res); return res; } LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); android_atomic_dec(&gNumProxyRefs); val->detachObject(&gBinderProxyOffsets); env->DeleteGlobalRef(object); } //3 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); if (object != NULL) { LOGDEATH("objectForBinder %p: created new proxy %p !\n", val.get(), object); // The proxy holds a reference to the native object. env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get()); val->incStrong((void*)javaObjectForIBinder); // 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); // Also remember the death recipients registered on this proxy sp<DeathRecipientList> drl = new DeathRecipientList; drl->incStrong((void*)javaObjectForIBinder); env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get())); // Note that a new object reference has been created. android_atomic_inc(&gNumProxyRefs); incRefsCreated(env); } return object;}
参数val为BpBinder(0),checkSubclass()函数使用IBinder里面的实现,直接返回false,所以1里的if为false。2里面是看一下是不是已经初始化过,直接进行返回,第一次引用是肯定为空,我们直接看3下面的代码。看代码之前先补充一下gBinderProxyOffsets。它是一个结构体,在jni进行init时int_register_android_os_BinderProxy()
进行的初始化。看一下这个结构体,注释里是它值
static struct binderproxy_offsets_t{ // Class state. jclass mClass; //android.os.BinderProxy jmethodID mConstructor; //android.os.BinderProxy.<init>() jmethodID mSendDeathNotice; //android.os.BinderProxy.sendDeathNotice() // Object state. jfieldID mObject; //android.os.BinderProxy.mObject jfieldID mSelf; //android.os.BinderProxy.mSelf jfieldID mOrgue; //android.os.BinderProxy.mOrgue} gBinderProxyOffsets;
再分析javaObjectForIBinder第3段代码可以看出来是首先创建了一个BinderProxy的Java对象,并且把它的成员变量mObject指向BpBinder。同时BpBinder的持有BinderProxy,方便第二次调用时直接返回。
所以BinderInternal.getContextObject()
返回的是BinderProxy对象。下面再看一下ServiceManagerNative.asInterface
的实现
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); }
直接new一个ServiceManagerProxy返回。我们看一下他的类关系图
替换一下,getIServiceManager()
就是 new ServiceManagerProxy(new BinderProxy())
。这样我们其实就是调用的ServiceManagerProxy的addService()函数。
Service的初始化
在分析addService()之前,我们需要先看一下ActivityManagerService的初始化过程,先看以下它的类关系图
ActivityManagerService的继承关系在上图中一目了然 。我们重点关注一下Binder的构造函数,在这里做了一些重要的初始化工作,在addService的时候会用到。Binder的初始化就是调用了一个init()函数,这个init()函数是一个 native函数,它的实现在android_util_Binder.cpp里面。
static void android_os_Binder_init(JNIEnv* env, jobject obj){ JavaBBinderHolder* jbh = new JavaBBinderHolder(); if (jbh == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; } ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh); jbh->incStrong((void*)android_os_Binder_init); env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);}
创建了一个JavaBBinderHolder对象,并把指针赋给Binder.mObject。gBinderOffsets和前面的gBinderProxyOffsets类似,也是在程序启动时初始化的,他的结构体代码如下
static struct bindernative_offsets_t{ // Class state. jclass mClass; //android.os.Binder jmethodID mExecTransact; //android.os.Binder.execTransact(); // Object state. jfieldID mObject; //android.os.Binder.mObject} gBinderOffsets;
分析完Service的初始化之后,我们再看一下Service是怎样通过ServiceManagerProxy注册到service_manager里面的。
addService
ServiceManagerProxy的 addService代码如下
public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); }
先把service写入到序列化类Parcel里面。然后调用mRemote.transact(),将序列化的数据发送出去。这里的mRemote就是我们前面初始化ServiceManagerProxy传入的BinderProxy。下面看一下Parcel.writeStrongBinder()
public final void writeStrongBinder(IBinder val) { nativeWriteStrongBinder(mNativePtr, val); }
nativeWriteStrongBinder是一个jni的调用,它的实现在android_os_Parcel.cpp
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object){ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } }}
parcel->writeStrongBinder()
在上一节已经分析过,如果是一个BpBinder它会将handle的值存入parcel中,如果是BBinder它会将BBinder 的this指针存储到 parcel中。这里我们是addService操作,所以我们可以大胆猜测括号里是一个BBinder的子类。下面我们看一下ibinderForJavaObject(env, object)是如何实现将Java的Servie和BBinder绑定的。
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj){ if (obj == NULL) return NULL; if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {//Binder.class JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject); return jbh != NULL ? jbh->get(env, obj) : NULL; } if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {//BinderProxy.class return (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); } ALOGW("ibinderForJavaObject: %p is not a Binder object", obj); return NULL;}
这里的obj是ActivityManagerService,它是Binder的子类。所以执行第二个if语句。还记得我们前面在讲Binder的构造函数时,在init里面我们在native层分配了一个JavaBBinderHolder类,并将它的指针存在mObject成员变量中。现在我们把它取出来然后调用他的get()函数。看一下这个类的源码实现。
class JavaBBinderHolder : public RefBase{public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj); mBinder = b; ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n", b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); } return b; } sp<JavaBBinder> getExisting() { AutoMutex _l(mLock); return mBinder.promote(); }private: Mutex mLock; wp<JavaBBinder> mBinder;};
看一下get()函数,第一次调用时,mBinder为空,于是创建了一个JavaBBinder,并把obj传了进去。然后把JavaBBinder赋值给mBinder。接着看看JavaBBinder
class JavaBBinder : public BBinder{public: JavaBBinder(JNIEnv* env, jobject object) : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) { ALOGV("Creating JavaBBinder %p\n", this); android_atomic_inc(&gNumLocalRefs); incRefsCreated(env); } bool checkSubclass(const void* subclassID) const { return subclassID == &gBinderOffsets; } jobject object() const { return mObject; }protected: virtual ~JavaBBinder() { ALOGV("Destroying JavaBBinder %p\n", this); android_atomic_dec(&gNumLocalRefs); JNIEnv* env = javavm_to_jnienv(mVM); env->DeleteGlobalRef(mObject); } virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { ... } virtual status_t dump(int fd, const Vector<String16>& args) { return 0; }private: JavaVM* const mVM; jobject const mObject;};
JavaBBinder会把传进来的service引用赋值给自己的mObject。可以看出Binder.class,JavaBBinderHolder,JavaBBinder这三者是一个循环持有的过程,他们的关系图为
这样Java层和c++层都持有了对方的引用。
同时JavaBBinder还是BBinder的子类。也就是说,ibinderForJavaObject返回了JavaBBinder也就是一个BBinder。下面我们看一下BinderProxy.transact()函数。
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); return transactNative(code, data, reply, flags); }
transactNative()是一个jni实现,它的源码在android_os_Parcel.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException{ if (dataObj == NULL) { jniThrowNullPointerException(env, NULL); return JNI_FALSE; } Parcel* data = parcelForJavaObject(env, dataObj); //1 if (data == NULL) { return JNI_FALSE; } Parcel* reply = parcelForJavaObject(env, replyObj); //2 if (reply == NULL && replyObj != NULL) { return JNI_FALSE; } IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);//3 if (target == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); return JNI_FALSE; } ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n", target, obj, code); //printf("Transact from Java code to %p sending: ", target); data->print(); status_t err = target->transact(code, *data, reply, flags);//4 if (err == NO_ERROR) { return JNI_TRUE; } else if (err == UNKNOWN_TRANSACTION) { return JNI_FALSE; } signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); return JNI_FALSE;}
在1,2里面分别把Java序列化的data和reply转变为一个c++的Parcle变量。3中取出了mObject值,在前面获得server_manager代理的时候我们把他初始化为一个BpBinder(0)。在4里面调用BpBinder->transact()函数。下面就进入了C++层和binder通信的过程,和上一篇博客分析的一样,会调用到IPCThreadState和binder驱动进行读写。到这里我们就已经把我们的ActivityManagerService注册到Binder驱动和 activity_manager里面 。
Binder驱动调用Service
上一节我们分析了Java中的Service如何注册到binder里面的。那么,binder又是如何调用到Service的业务实现的呢。在上一篇博客Binder通信笔记(native)篇中,我们看到在IPCProcessState读取到binder数据之后,会通过我们注册到binder驱动里面BBinder指针,调用它的transact()函数。在Java Serivce注册的时候,我们注册的是JavaBBinder,它是BBinder的子类。JavaBBinder并没有重写transact()函数,所以回复用BBinder中的实现,调用onTransact()函数。JavaBBinder重写了onTransact()的实现,我们看一下源码
virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM); ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); IPCThreadState* thread_state = IPCThreadState::self(); const int32_t strict_policy_before = thread_state->getStrictModePolicy(); //printf("Transact from %p to Java code sending: ", this); //data.print(); //printf("\n"); jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(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 code */ env->DeleteLocalRef(excep); } // Check if the strict mode state changed while processing the // call. The Binder state will be restored by the underlying // Binder system in IPCThreadState, however we need to take care // of the parallel Java state as well. if (thread_state->getStrictModePolicy() != strict_policy_before) { set_dalvik_blockguard_policy(env, strict_policy_before); } jthrowable excep2 = env->ExceptionOccurred(); if (excep2) { report_exception(env, excep2, "*** Uncaught exception in onBinderStrictModePolicyChange"); /* clean up JNI local ref -- we don't return to Java code */ env->DeleteLocalRef(excep2); } // Need to always call through the native implementation of // SYSPROPS_TRANSACTION. if (code == SYSPROPS_TRANSACTION) { BBinder::onTransact(code, data, reply, flags); } //aout << "onTransact to Java code; result=" << res << endl // << "Transact from " << this << " to Java code returning " // << reply << ": " << *reply << endl; return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; }
第15行,调用了mObject的gBinderOffsets.mExecTransact函数,通过前面的分析知道,此处的mObject是一个Binder类的引用,gBinderOffsets.mExecTransact是Binder类的execTransact()方法。所以,业务处理分发给了Java层的Binder类的execTransact()。
// Entry point from android_util_Binder.cpp's onTransactprivate boolean execTransact(int code, long dataObj, long 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; // Log any exceptions as warnings, don't silently suppress them. // If the call was FLAG_ONEWAY then these exceptions disappear into the ether. try { res = onTransact(code, data, reply, flags); } catch (RemoteException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Binder call failed.", e); } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (RuntimeException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e); } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (OutOfMemoryError e) { // Unconditionally log this, since this is generally unrecoverable. Log.e(TAG, "Caught an OutOfMemoryError from the binder stub implementation.", e); RuntimeException re = new RuntimeException("Out of memory", e); reply.setDataPosition(0); reply.writeException(re); res = true; } checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); reply.recycle(); data.recycle(); // Just in case -- we are done with the IPC, so there should be no more strict // mode violations that have gathered for this thread. Either they have been // parceled and are now in transport off to the caller, or we are returning back // to the main transaction loop to wait for another incoming transaction. Either // way, strict mode begone! StrictMode.clearGatheredViolations(); return res; }
这里调用了onTransact(code, data, reply, flags),onTransact()在ActivityManagerService里面被继承了,真正的业务处理放在了这里 ,这样我们的Service函数就会被真正的执行,并且把执行后的结构存储在reply里面。
到这里我们就分析完了Java层和Binder驱动通信源码。
参考资料
http://blog.csdn.net/universus/article/details/6211589
http://blog.csdn.net/luoshengyang/article/details/6618363
http://blog.csdn.net/innost/article/details/47208049
- Binder 通信笔记(Java)
- Binder 通信笔记(native)
- binder 进程间通信笔记
- Android Java Binder 通信机制
- Android7.0 Binder通信(4) Java层中的Binder
- binder 通信
- Binder通信
- binder通信
- Binder通信
- Android学习笔记1-2--通信2--Binder
- binder通信实例之java客户端与java服务端
- Binder进程间通信机制的Java接口
- 006——Java层Binder框架通信原理
- binder通信实例之java客户端与c++服务端
- Binder笔记
- binder 通信实例
- Binder通信流程图
- Binder通信流程分析
- !DOCTYPE是文档说明
- 深度强化学习系列(二):强化学习基础
- LeetCode 304. Range Sum Query 2D - Immutable
- JAVA第一课知识点总结
- ViewPager定时切换
- Binder 通信笔记(Java)
- Disable Maven Nature
- nRF52832 GPIO
- Git快速入门
- 图解phpstorm常用快捷键
- Linux下python安装升级详细步骤 | Python2 升级 Python3
- net use访问远程电脑
- 2016年10月总结
- 有点难