您的位置:首页 > 移动开发 > Android开发

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为空,该方法的实现如下:

@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远程接口过程源代码分析
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐