Android 8.0系统源码分析--Binder进程间通信(一)
2017-11-24 20:44
489 查看
开始我们的沉淀之路,老罗的书中第二章讲的是Android HAL层的知识,而且直接自己实现了一个虚拟的freg驱动程序,后面的几节是分别从native、java层如何访问这个虚拟的驱动程序接口,我这里没有这样的环境,所以就不分析这节了,第三章的智能指针我对比8.0系统源码和老罗的书,基本修改很小,大家如果要学习的话,就直接看老罗的书吧,这也反映出一个问题,就是我们学到的知识肯定是有用的,老罗在自己博客下面回答博友的提问时也一直在强调这点,我们学过的、学会的知识不可能浪费,没有用,肯定是有用的,即使上层再如何变化,但是涉及到核心的东西,变化也是很小的。老罗书中的第四章讲的是Log驱动的实现,对比Log来说,我们一般也就是会使用就可以了,所以也不打算在这一章节上花时间。
那么我们就进入第五章--Binder进程间通信。这是最有分量的一节,难度也非常大,之前自己也看过老罗的Binder系列博客很久了,但是对其中的各各环节还是理解的不透,我们就从这里开始学习吧。
老罗分析Binder进程间通信的实现时,开始讲解了很多Binder的结构体,我个人讲不清这个,我就按照自己的思路来学吧。如果大家搞过应用层的开发,相信大家都很清楚,我们使用的最多的就是Activity,它的启动过程就是一个完整的Binder调用,那么我们就以这个过程为学习路线,来分析一下startActivity的过程中Application应用层是怎么通过Binder进程间通信调用到ActivityManagerServie当中的。
我们的入口函数当然就是Activity类的startActivity方法了。Activity类的startActivity方法实现很简单,就是直接调用两个参数的startActivity方法,此时传入的第二个参数options为空,该方法的实现如下:
这个方法中最重要的就是最后的try/catch了,通过调用ActivityManager.getService().startActivity来启动目标Activity,然后调用checkStartActivityResult方法来检查启动结果。我们继续跟踪ActivityManager.getService().startActivity,它需要分两段来分析。
第一段调用ActivityManager.getService()来获取binder代理对象,它的实现如下:
IActivityManagerSingleton是ActivityManager类中类型为Singleton<IActivityManager>的静态成员变量,get()方法是单例模式Singleton来实现的,当调用get()方法时,就会执行范型 T 的create()方法,Singleton类的代码如下:
ActivityManager这里以Context.ACTIVITY_SERVICE为key值获取到一个IBinder对象,然后调用IActivityManager.Stub.asInterface(b)进行转换,就会得到一个BinderProxy对象,IActivityManager.aidl文件经过编译后就会生成IActivityManager.java,但是源码中没有,我就自己写了一个ICameraService.aidl文件,然后生成对应的ICameraService.java,我们可以用它来对比分析一下,ICameraService.java源码如下:
首先来看一下Parcel.obtain()方法的实现,源码如下:
好,我们继续回到主流程中,当新建一个Parcel对象时,传入的参数nativePtr为0,表示该对象还没有在native层创建,于是接着调用nativeCreate来执行native层的创建。native层的创建很简单,就是直接新建了一个Parcel的对象,然后将该对象的指针返回来,我们随便来看一下nativeWriteString方法的实现,以更好的理解Parcel写入数据时必须按照顺序的原因。nativeWriteString方法的JNI定义是由android_os_Parcel_writeString来执行的,android_os_Parcel_writeString的实现代码如下:
Parcel的分析就暂时到这里,我们继续回到主流程当中。mRemote获取到的就是一个BinderProxy的对象,那我们就继续看它的transact方法的实现逻辑。BinderProxy类的定义在frameworks\base\core\java\android\os\Binder.java文件中,它的transact方法的实现如下:
transactNative方法的实现在frameworks\base\core\jni\android_util_Binder.cpp文件中,源码如下:
BpBinder类的transact方法实现在frameworks\native\libs\binder\BpBinder.cpp文件中,源码如下:
IPCThreadState类的transact方法实现在frameworks\native\libs\binder\IPCThreadState.cpp文件中,源码如下:
8.0系统源码分析--开篇下载老罗的Android系统源代码情景分析【罗升阳著】PDF版本电子书。下一步继续调用waitForResponse来执行Binder通信。
waitForResponse方法的实现源码如下:
如果想详细了解Binder进程间通信内容,可以查看老罗的系列博客,讲的非常好,地址如下:
Android进程间通信(IPC)机制Binder简要介绍和学习计划
浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路
浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
那么我们就进入第五章--Binder进程间通信。这是最有分量的一节,难度也非常大,之前自己也看过老罗的Binder系列博客很久了,但是对其中的各各环节还是理解的不透,我们就从这里开始学习吧。
老罗分析Binder进程间通信的实现时,开始讲解了很多Binder的结构体,我个人讲不清这个,我就按照自己的思路来学吧。如果大家搞过应用层的开发,相信大家都很清楚,我们使用的最多的就是Activity,它的启动过程就是一个完整的Binder调用,那么我们就以这个过程为学习路线,来分析一下startActivity的过程中Application应用层是怎么通过Binder进程间通信调用到ActivityManagerServie当中的。
我们的入口函数当然就是Activity类的startActivity方法了。Activity类的startActivity方法实现很简单,就是直接调用两个参数的startActivity方法,此时传入的第二个参数options为空,该方法的实现如下:
@Override public void startActivity(Intent intent) { this.startActivity(intent, null); } @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); } public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }按照我们正常的启动逻辑,第二个参数options为空,所以进入else分支,调用startActivityForResult来进一步处理,再次调用三个参数的同名方法,mParent变量一般为空,所以会进入第一个if分支,这里最重要的就是mInstrumentation.execStartActivity、mMainThread.sendActivityResult这两句逻辑了。mInstrumentation.execStartActivity这句就会进入到我们的目标,将Activity的启动数据封装完成后,通过binder机制发送到Server端,也就是ActivityManagerService;mMainThread.sendActivityResult这句在判断调用正常的情况下,通知应用主线程ActivityThread来处理启动后的结果,mMainThread是一个ActivityThread类型的成员变量,它是在当前的Activity启动成功后,通过应用程序主线程ActivityThread类的performLaunchActivity方法来赋值的。我们就追踪mInstrumentation.execStartActivity的实现就可以了。mInstrumentation是Activity类的成员变量,它的类型是Instrumentation,它有三个execStartActivity重名方法,而当前的调用是第四个参数为Activity类型的,该方法的实现如下:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } if (mActivityMonitors != null) { synchronized (mSync) { final int N = mActivityMonitors.size(); for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); ActivityResult result = null; if (am.ignoreMatchingSpecificIntents()) { result = am.onStartActivity(intent); } if (result != null) { am.mHits++; return result; } else if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null; } break; } } } } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
这个方法中最重要的就是最后的try/catch了,通过调用ActivityManager.getService().startActivity来启动目标Activity,然后调用checkStartActivityResult方法来检查启动结果。我们继续跟踪ActivityManager.getService().startActivity,它需要分两段来分析。
第一段调用ActivityManager.getService()来获取binder代理对象,它的实现如下:
/** * @hide */ public static IActivityManager getService() { return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
IActivityManagerSingleton是ActivityManager类中类型为Singleton<IActivityManager>的静态成员变量,get()方法是单例模式Singleton来实现的,当调用get()方法时,就会执行范型 T 的create()方法,Singleton类的代码如下:
public abstract class Singleton<T> { private T mInstance; protected abstract T create(); public final T get() { synchronized (this) { if (mInstance == null) { mInstance = create(); } return mInstance; } } }
ActivityManager这里以Context.ACTIVITY_SERVICE为key值获取到一个IBinder对象,然后调用IActivityManager.Stub.asInterface(b)进行转换,就会得到一个BinderProxy对象,IActivityManager.aidl文件经过编译后就会生成IActivityManager.java,但是源码中没有,我就自己写了一个ICameraService.aidl文件,然后生成对应的ICameraService.java,我们可以用它来对比分析一下,ICameraService.java源码如下:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\Work\\Project\\workstudio\\CameraService\\app\\src\\main\\aidl\\com\\huawei\\cameraservice\\ICameraService.aidl */ package com.huawei.cameraservice; // Declare any non-default types here with import statements public interface ICameraService extends android.os.IInterface { /** * Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.huawei.cameraservice.ICameraService { private static final java.lang.String DESCRIPTOR = "com.huawei.cameraservice.ICameraService"; /** * Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.huawei.cameraservice.ICameraService interface, * generating a proxy if needed. */ public static com.huawei.cameraservice.ICameraService asInterface(android.os.IBinder obj) { if ((obj == null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin != null) && (iin instanceof com.huawei.cameraservice.ICameraService))) { return ((com.huawei.cameraservice.ICameraService) iin); } return new com.huawei.cameraservice.ICameraService.Stub.Proxy(obj); } @Override 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_getMainCameraId: { data.enforceInterface(DESCRIPTOR); int _result = this.getMainCameraId(); reply.writeNoException(); reply.writeInt(_result); return true; } case TRANSACTION_openCamera: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); int _result = this.openCamera(_arg0); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.huawei.cameraservice.ICameraService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int getMainCameraId() 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_getMainCameraId, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public int openCamera(int id) 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); _data.writeInt(id); mRemote.transact(Stub.TRANSACTION_openCamera, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getMainCameraId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_openCamera = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public int getMainCameraId() throws android.os.RemoteException; public int openCamera(int id) throws android.os.RemoteException; }DESCRIPTOR就是当前Server的描述符,比如ActivityManagerService的描述符就是“activity”,queryLocalInterface方法会在本进程中查找,假如我们想要获取到ActivityManagerService,而且我们是在SystemServer进程当中 ,那肯定就直接找到了,我们当前的声明中,启动Activity时本进程肯定是找不到,所以 iin 结果为空,那么就以obj对参数创建一个Proxy对象返回给我们,实际上这个Proxy对象就是BinderProxy,它定义在frameworks\base\core\java\android\os\Binder.java文件当中。好,这里我们获取到BinderProxy对象之后,继续往下读代码。那么就调用它的startActivity方法,因为没有IActivityManager编译出来的java文件,我们就以openCamera方法为例来继续我们的流程。Proxy类的代码如下:
private static class Proxy implements com.huawei.cameraservice.ICameraService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public int getMainCameraId() 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_getMainCameraId, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } @Override public int openCamera(int id) 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); _data.writeInt(id); mRemote.transact(Stub.TRANSACTION_openCamera, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } }像这样的aidl生成的方法全部都是这种格式:1、获取到两个Parcel对象,一个用于存储我们调用方法时的数据,一个用于存储方法执行完成后的返回结果;2、依次写入我们的通信数据;3、执行transact方法;4、读取返回结果,如果有异常,则抛出异常,如果没有异常,则说明通信成功,将结果返回到Client端。这里要特别说明的就是,Parcel用于存储通信数据和取返回结果时,一定完全按照服务器定义好的顺序,否则数据就会出错。这是为什么呢?要查这个原因,就要看看Parcel这个数据载体的实现了。
首先来看一下Parcel.obtain()方法的实现,源码如下:
/** * Retrieve a new Parcel object from the pool. */ public static Parcel obtain() { final Parcel[] pool = sOwnedPool; synchronized (pool) { Parcel p; for (int i=0; i<POOL_SIZE; i++) { p = pool[i]; if (p != null) { pool[i] = null; if (DEBUG_RECYCLE) { p.mStack = new RuntimeException(); } return p; } } } return new Parcel(0); }这里就是用了池的概念,sOwnedPool是Parcel类的成员变量,它的类型是Parcel[]数组,初始化长度为6,首次执行Parcel类的obtain方法时,sOwnedPool中的成员全部为空,所以直接新建对象返回,但是从这里看不出来和对象池有什么关系,sOwnedPool中每个元素是怎么赋值的?奇妙的地方就在recycle()方法当中了,我们来看一下recycle()方法的实现:
/** * Put a Parcel object back into the pool. You must not touch * the object after this call. */ public final void recycle() { if (DEBUG_RECYCLE) mStack = null; freeBuffer(); final Parcel[] pool; if (mOwnsNativeParcelObject) { pool = sOwnedPool; } else { mNativePtr = 0; pool = sHolderPool; } synchronized (pool) { for (int i=0; i<POOL_SIZE; i++) { if (pool[i] == null) { pool[i] = this; return; } } } }从注释也可以看出来,是将一个即将要回收的对象放入对象池中,而释放的只是它所占用的内存空间而已,这里最奇妙的就是第一个if分支给局部变量pool赋值了,因为pool在声明时没有初始化,所以直接将成员变量sOwnedPool赋值给局部变量pool之后,那么它们两个就是同一个对象了,而且hashcode值也相同,所以接下来给pool的元素赋值时就相当于为sOwnedPool元素赋值了,这样sOwnedPool中的6个元素就会依次在回收6个新建对象时依次被填充上了!!真是非常巧妙,但是写法上不容易理解!
好,我们继续回到主流程中,当新建一个Parcel对象时,传入的参数nativePtr为0,表示该对象还没有在native层创建,于是接着调用nativeCreate来执行native层的创建。native层的创建很简单,就是直接新建了一个Parcel的对象,然后将该对象的指针返回来,我们随便来看一下nativeWriteString方法的实现,以更好的理解Parcel写入数据时必须按照顺序的原因。nativeWriteString方法的JNI定义是由android_os_Parcel_writeString来执行的,android_os_Parcel_writeString的实现代码如下:
static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jlong nativePtr, jstring val) { Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); if (parcel != NULL) { status_t err = NO_MEMORY; if (val) { const jchar* str = env->GetStringCritical(val, 0); if (str) { err = parcel->writeString16( reinterpret_cast<const char16_t*>(str), env->GetStringLength(val)); env->ReleaseStringCritical(val, str); } } else { err = parcel->writeString16(NULL, 0); } if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } }nativePtr就是在创建C++层对象时的指针,首先将我们传入的String字符串转换为char数组,然后调用parcel类的writeString16方法进行写入。writeString16方法的实现在frameworks\native\libs\binder\Parcel.cpp文件当中,源码如下:
status_t Parcel::writeString16(const String16& str) { return writeString16(str.string(), str.size()); } status_t Parcel::writeString16(const char16_t* str, size_t len) { if (str == NULL) return writeInt32(-1); status_t err = writeInt32(len); if (err == NO_ERROR) { len *= sizeof(char16_t); uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t)); if (data) { memcpy(data, str, len); *reinterpret_cast<char16_t*>(data+len) = 0; return NO_ERROR; } err = mError; } return err; }看到这里我们就非常清楚了,当写入一个String字符串时,会先写入该字符串的长度len,然后才调用memcpy系统函数将字符串内容复制申请好的内存空间中,所以千万不能乱读乱写,否则读出来的数据肯定就是错误的数据了。
Parcel的分析就暂时到这里,我们继续回到主流程当中。mRemote获取到的就是一个BinderProxy的对象,那我们就继续看它的transact方法的实现逻辑。BinderProxy类的定义在frameworks\base\core\java\android\os\Binder.java文件中,它的transact方法的实现如下:
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { Binder.checkParcel(this, code, data, "Unreasonably large binder buffer"); if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)) { // For now, avoid spamming the log by disabling after we've logged // about this interface at least once mWarnOnBlocking = false; Log.w(Binder.TAG, "Outgoing transactions from this process must be FLAG_ONEWAY", new Throwable()); } final boolean tracingEnabled = Binder.isTracingEnabled(); if (tracingEnabled) { final Throwable tr = new Throwable(); Binder.getTransactionTracker().addTrace(tr); StackTraceElement stackTraceElement = tr.getStackTrace()[1]; Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName()); } try { return transactNative(code, data, reply, flags); } finally { if (tracingEnabled) { Trace.traceEnd(Trace.TRACE_TAG_ALWAYS); } } }该方法首先对输入数据data的大小进行检查,是通过调用checkParcel方法来完成的,它当中执行if (CHECK_PARCEL_SIZE && parcel.dataSize() >= 800*1024) 判断,也就是说Binder进程间通信的传输数据最大为800K,如果超过800K,就会打印出Unreasonably large binder buffer异常。所以我们在使用Binder进程间通信时,如果数据量过大,就要考虑其他方案来实现我们的目的。第一个参数code就指我们调用Server端的方法请求码,它是以android.os.IBinder.FIRST_CALL_TRANSACTION为基数递增的,最后一个参数flags的意思是此次请求是否同步。比如我们现在分析的场景,启动Activity时,不仅要求ActivityManagerService完成Activity的启动,而且还要等待它给我们返回结果才能继续往下执行,也就是同步的,因此它的值为0;而假如我们要使用音乐播放器播放一段音乐,不需要它给我们返回结果,我们只需要将命令发送给MediaServer就直接返回继续处理我们的逻辑了,这种场景下就是异步的,那么它的值就是1。最后继续调用transactNative来处理我们的请求。
transactNative方法的实现在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) // throws RemoteException { if (dataObj == NULL) { jniThrowNullPointerException(env, NULL); return JNI_FALSE; } 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->GetLongField(obj, gBinderProxyOffsets.mObject); 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); bool time_binder_calls; int64_t start_millis; if (kEnableBinderSample) { // Only log the binder call duration for things on the Java-level main thread. // But if we don't time_binder_calls = should_time_binder_calls(); if (time_binder_calls) { start_millis = uptimeMillis(); } } //printf("Transact from Java code to %p sending: ", target); data->print(); status_t err = target->transact(code, *data, reply, flags); //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); if (kEnableBinderSample) { if (time_binder_calls) { conditionally_log_binder_call(start_millis, target, code); } } if (err == NO_ERROR) { return JNI_TRUE; } else if (err == UNKNOWN_TRANSACTION) { return JNI_FALSE; } signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize()); return JNI_FALSE; }该方法先对data数据进行判断,如果data为空,就直接抛出空指针异常。紧接着将我们从Java层传进来的对象转换为C++层的指针,如果转换出错,则中断执行,直接返回JNI_FALSE,下一步获取到C++层的Binder代理对象指针,实际是一个BpBinder对象,然后将封装好的C++层的四个对象作为参数,调用BpBinder对象的transact方法。
BpBinder类的transact方法实现在frameworks\native\libs\binder\BpBinder.cpp文件中,源码如下:
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come back to life. if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; }首先检查当前的Binder代理对象是否还存活,只有在存活的状态下才能进行后续的逻辑。IPCThreadState和ProcessState两个类就是Binder通信的适配器,中转逻辑都是在它们两个类中完成的,它的self()方法获取到的就是一个IPCThreadState对象,我们继续分析它的transact方法的实现。
IPCThreadState类的transact方法实现在frameworks\native\libs\binder\IPCThreadState.cpp文件中,源码如下:
status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS; IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " << handle << " / code " << TypeCode(code) << ": " << indent << data << dedent << endl; } if (err == NO_ERROR) { LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); } if (err != NO_ERROR) { if (reply) reply->setError(err); return (mLastError = err); } if ((flags & TF_ONE_WAY) == 0) { #if 0 if (code == 4) { // relayout ALOGI(">>>>>> CALLING transaction 4"); } else { ALOGI(">>>>>> CALLING transaction %d", code); } #endif if (reply) { err = waitForResponse(reply); } else { Parcel fakeReply; err = waitForResponse(&fakeReply); } #if 0 if (code == 4) { // relayout ALOGI("<<<<<< RETURNING transaction 4"); } else { ALOGI("<<<<<< RETURNING transaction %d", code); } #endif IF_LOG_TRANSACTIONS() { TextOutput::Bundle _b(alog); alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " << handle << ": "; if (reply) alog << indent << *reply << dedent << endl; else alog << "(none requested)" << endl; } } else { err = waitForResponse(NULL, NULL); } return err; }该方法首先仍然会进行数据检查,TF_ACCEPT_FDS表示是否可以携带文件描述符,接下来调用writeTransactionData将数据进一步封装成binder_transaction_data结构体,老罗的书中对所有Binder通信的结构体有非常详细的分析说明,大家可以去Android
8.0系统源码分析--开篇下载老罗的Android系统源代码情景分析【罗升阳著】PDF版本电子书。下一步继续调用waitForResponse来执行Binder通信。
waitForResponse方法的实现源码如下:
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { uint32_t cmd; int32_t err; while (1) { if ((err=talkWithDriver()) < NO_ERROR) break; err = mIn.errorCheck(); if (err < NO_ERROR) break; if (mIn.dataAvail() == 0) continue; cmd = (uint32_t)mIn.readInt32(); IF_LOG_COMMANDS() { alog << "Processing waitForResponse Command: " << getReturnString(cmd) << endl; } switch (cmd) { case BR_TRANSACTION_COMPLETE: if (!reply && !acquireResult) goto finish; break; case BR_DEAD_REPLY: err = DEAD_OBJECT; goto finish; case BR_FAILED_REPLY: err = FAILED_TRANSACTION; goto finish; case BR_ACQUIRE_RESULT: { ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); const int32_t result = mIn.readInt32(); if (!acquireResult) continue; *acquireResult = result ? NO_ERROR : INVALID_OPERATION; } goto finish; case BR_REPLY: { binder_transaction_data tr; err = mIn.read(&tr, sizeof(tr)); ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); if (err != NO_ERROR) goto finish; if (reply) { if ((tr.flags & TF_STATUS_CODE) == 0) { reply->ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer, this); } else { err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer); freeBuffer(NULL, reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), this); } } else { freeBuffer(NULL, reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), this); continue; } } goto finish; default: err = executeCommand(cmd); if (err != NO_ERROR) goto finish; break; } } finish: if (err != NO_ERROR) { if (acquireResult) *acquireResult = err; if (reply) reply->setError(err); mLastError = err; } return err; }这里就是Binder通信比较核心的地方了,其中的BR_TRANSACTION_COMPLETE、BR_DEAD_REPLY、BR_ACQUIRE_RESULT、BR_REPLY都是Binder的通信协议,talkWithDriver方法就是最终和Binder驱动进行交互了,它是通过调用ioctl系统函数,将封装好的数据发送到Binder驱动中,然后由Binder驱动进行解析以实现和Server端的通信的。Binder通信协议定义在bionic\libc\kernel\uapi\linux\android\binder.h文件当中,包括了binder_transaction_data数据交互协议、binder_write_read数据结构体、binder_driver_return_protocol返回协议、binder_driver_command_protocol命令协议,该文件的整个源码如下:
/**************************************************************************** **************************************************************************** *** *** This header was automatically generated from a Linux kernel header *** of the same name, to make information necessary for userspace to *** call into the kernel available to libc. It contains only constants, *** structures, and macros generated from the original header, and thus, *** contains no copyrightable information. *** *** To edit the content of this header, modify the corresponding *** source file (e.g. under external/kernel-headers/original/) then *** run bionic/libc/kernel/tools/update_all.py *** *** Any manual change here will be lost the next time this script will *** be run. You've been warned! *** **************************************************************************** ****************************************************************************/ #ifndef _UAPI_LINUX_BINDER_H #define _UAPI_LINUX_BINDER_H #include <linux/types.h> #include <linux/ioctl.h> /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define B_PACK_CHARS(c1,c2,c3,c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4)) #define B_TYPE_LARGE 0x85 enum { BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ }; enum { FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ }; #ifdef BINDER_IPC_32BIT typedef __u32 binder_size_t; typedef __u32 binder_uintptr_t; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #else typedef __u64 binder_size_t; typedef __u64 binder_uintptr_t; #endif /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ struct flat_binder_object { __u32 type; __u32 flags; union { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t binder; __u32 handle; }; binder_uintptr_t cookie; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ }; struct binder_write_read { binder_size_t write_size; binder_size_t write_consumed; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t write_buffer; binder_size_t read_size; binder_size_t read_consumed; binder_uintptr_t read_buffer; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ }; struct binder_version { __s32 protocol_version; }; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #ifdef BINDER_IPC_32BIT #define BINDER_CURRENT_PROTOCOL_VERSION 7 #else #define BINDER_CURRENT_PROTOCOL_VERSION 8 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #endif #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) #define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) #define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ #define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) #define BINDER_THREAD_EXIT _IOW('b', 8, __s32) #define BINDER_VERSION _IOWR('b', 9, struct binder_version) /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ enum transaction_flags { TF_ONE_WAY = 0x01, TF_ROOT_OBJECT = 0x04, TF_STATUS_CODE = 0x08, /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ TF_ACCEPT_FDS = 0x10, }; struct binder_transaction_data { union { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u32 handle; binder_uintptr_t ptr; } target; binder_uintptr_t cookie; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u32 code; __u32 flags; pid_t sender_pid; uid_t sender_euid; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_size_t data_size; binder_size_t offsets_size; union { struct { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t buffer; binder_uintptr_t offsets; } ptr; __u8 buf[8]; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ } data; }; struct binder_ptr_cookie { binder_uintptr_t ptr; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t cookie; }; struct binder_handle_cookie { __u32 handle; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t cookie; } __packed; struct binder_pri_desc { __s32 priority; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ __u32 desc; }; struct binder_pri_ptr_cookie { __s32 priority; /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ binder_uintptr_t ptr; binder_uintptr_t cookie; }; enum binder_driver_return_protocol { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BR_ERROR = _IOR('r', 0, __s32), BR_OK = _IO('r', 1), BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), BR_REPLY = _IOR('r', 3, struct binder_transaction_data), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), BR_DEAD_REPLY = _IO('r', 5), BR_TRANSACTION_COMPLETE = _IO('r', 6), BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BR_NOOP = _IO('r', 12), BR_SPAWN_LOOPER = _IO('r', 13), BR_FINISHED = _IO('r', 14), BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), BR_FAILED_REPLY = _IO('r', 17), }; enum binder_driver_command_protocol { /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), BC_REPLY = _IOW('c', 1, struct binder_transaction_data), BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BC_INCREFS = _IOW('c', 4, __u32), BC_ACQUIRE = _IOW('c', 5, __u32), BC_RELEASE = _IOW('c', 6, __u32), BC_DECREFS = _IOW('c', 7, __u32), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), BC_REGISTER_LOOPER = _IO('c', 11), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BC_ENTER_LOOPER = _IO('c', 12), BC_EXIT_LOOPER = _IO('c', 13), BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), }; #endif剩下的就到了Binder进程间通信最核心的地方了,也就是waitForResponse之后的流程,我们下次继续分析。
如果想详细了解Binder进程间通信内容,可以查看老罗的系列博客,讲的非常好,地址如下:
Android进程间通信(IPC)机制Binder简要介绍和学习计划
浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路
浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
相关文章推荐
- Android 8.0系统源码分析--Binder进程间通信(三)
- Android 8.0系统源码分析--Binder进程间通信(二)
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析(2)
- [Binder.5] Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(3)
- Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析(2)
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析(3)
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- [Binder.3] Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
- Android进程间通信之Binder机制源码分析
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码文件分析
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(2)
- Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
- [Binder.4] Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
- Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
- Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(4)