简单理解 Binder 机制

  • 一、为什么要用 Binder
  • 二、Binder 进程间通信机制
  • 三、Java 层中的 Binder 分析
  • 关键一:getIServiceManager()
  • 问题一:getIServiceManager() 方法返回是什么,ServiceManager 的代理对象吗
  • 关键 1.1:ServiceManagerNative.asInterface() 需要关键 1.2 的返回值作为参数,那么我们先看关键 1.2 吧
  • 关键 1.2:BinderInternal.getContextObject()
  • 关键 1.2.1:ProcessState::self()
  • 关键 1.2.1.1:new ProcessState("/dev/binder")
  • 关键 1.2.2:ProcessState::self()->getContextObject(NULL)
  • 关键 1.2.2.1:getStrongProxyForHandle(0)
  • 关键 1.2.3:javaObjectForIBinder()
  • 回到 关键 1.1:ServiceManagerNative.asInterface()
  • 关键 1.1.1:obj.queryLocalInterface()
  • 关键二:getIServiceManager().addService() 注册服务
  • 关键 2.1:Parcel#writeStrongBinder()
  • 关键 2.1.1:nativeWriteStrongBinder()
  • 关键 2.1.1.1:flatten_binder()
  • 关键 2.1.1.1.1:finish_flatten_binder()
  • 关键 2.2:BinderProxy#transact()
  • 关键三:BpBinder::transact()
  • 关键 3.1:IPCThreadState::self()
  • 关键 3.2:IPCThreadState::self()->transact()
  • 关键 3.2.1:writeTransactionData()
  • 关键 3.2.2:waitForResponse()
  • 关键四:talkWithDriver()
  • 关键 4.1:ioctl()
  • 处理 BR_TRANSACTION 返回协议的同时:
  • 发送和处理 BC_REPLY 命令协议:
  • 发送和处理 BR_REPLY 返回协议:
  • 四、AIDL


一、为什么要用 Binder

Android 应用程序是由 Activity、Service、Broadcast Receiver 和 Content Provider 四种类型的组件构成的,四大组件运行可能在相同或不同进程中运行,Android 系统中系统组件运行在独立的进程中,系统服务运行在系统进程 System 中,不同进程的双方如何通信
Android 系统是基于 Linux 内核开发的。Linux 内核提供了丰富的进程间通信机制,如管道(pipe)、信号(Signal)、消息队列(Meessage)、共享内存(Share Memory)和插口(Socket)等。然而,Android 系统并没有采用这些传统的进程间通信机制,而是开发了一套新的进程间通信机制——Binder。与传统的进程间通信机制相比,Binder 进程间通信机制在进程间传输数据时,只需要执行一次复制操作,因此,它不仅提高了效率,而且节省了内存空间

二、Binder 进程间通信机制

Binder 进程间通信机制中涉及了 Client、Service、Server Manager 和 Binder 驱

动程序四个角色

android中binder详解 android binder机制详解_Java


Client、Service 和 Service Manager 运行在用户空间,而 Binder 驱动程序运行在内核空间,其中,Service Manager 和 Binder 驱动程序由系统负责提供,而 Client 和 Service 组件由应用程序来实现。Client、Service 和 Service Manager 均是通过系统调用 open、mmap 和 ioctl 来访问设备文件 /dev/binder,从而实现与 Binder 驱动程序的交互,而交互的目的就是为了能够间接地执行进程间通信

三、Java 层中的 Binder 分析

Java 层 Binder 系统是 Native 层 Binder 系统的一个镜像,但这个镜像终归还需借助 Native 层 Binder 系统来开展工作,平常使用的 Java 层 Binder 要想正常工作离不开 Native 层 Binder 的帮忙

下面我们看一下服务注册到 ServiceManager 的过程,即 addService() 的整个通信过程

1.向 ServiceManager 注册服务
向 ServiceManager 注册服务的函数叫 addService(),其代码如下:
[ServiceManager.java–>ServiceManager.addService()]

public static void addService(String name, IBinder service) {
    try {
        getIServiceManager().addService(name, service, false);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

public static void addService(String name, IBinder service, boolean allowIsolated) {
    try {
    	// 关键一:getIServiceManager()
    	// 关键二:getIServiceManager().addService()
        getIServiceManager().addService(name, service, allowIsolated);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}
关键一:getIServiceManager()
问题一:getIServiceManager() 方法返回是什么,ServiceManager 的代理对象吗

[ServiceManager.java–>ServiceManager.getIServiceManager()]

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

    // Find the service manager
    // 调用 asInterface,传递的参数类型为 BinderInternal.getContextObject()
    // 关键 1.1:ServiceManagerNative.asInterface()
    // 关键 1.2:BinderInternal.getContextObject()
    sServiceManager = ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}
关键 1.1:ServiceManagerNative.asInterface() 需要关键 1.2 的返回值作为参数,那么我们先看关键 1.2 吧
关键 1.2:BinderInternal.getContextObject()

BinderInternal.getContextObject() 方法是一个 native 函数,参考其实现:
[android_util_Binder.cpp–>android_os_Bindernal_getContextObject()]

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    // 下面这句代码将返回一个 BpProxy 对象,其中 NULL(即 0,用于标识目的端)指定 Proxy 通信的目的端是 ServiceManager
    // 关键 1.2.1:ProcessState::self()
    // 关键 1.2.2:ProcessState::self()->getContextObject(NULL)
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    // 关键 1.2.3:javaObjectForIBinder()
    return javaObjectForIBinder(env, b);
}
关键 1.2.1:ProcessState::self()

ProcessState::self() 方法用于获取 ProcessState 实例对象
[frameworks/native/libs/binder/ProcessState.cpp]

// 单例模式,保证每个进程只打开一次 Binder 驱动
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
        return gProcess;
    }
    // 关键 1.2.1.1:实例化 ProcessState
    gProcess = new ProcessState("/dev/binder");
    return gProcess;
}
关键 1.2.1.1:new ProcessState("/dev/binder")

实例化 ProcessState
[frameworks/native/libs/binder/ProcessState.cpp]

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver)) // 打开 Binder 驱动,参数 driver 值为 "/dev/binder"
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        // 采用内存映射函数 mmap,给 Binder 分配一块虚拟地址空间
        // 调用驱动层 binder_map 方法,私有的,可读不可写
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        
        if (mVMStart == MAP_FAILED) { // 分配失败
            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
}
关键 1.2.2:ProcessState::self()->getContextObject(NULL)

[frameworks/native/libs/binder/ProcessState.cpp]

// 参数传入 NULL
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
	// 关键 1.2.2.1:getStrongProxyForHandle(0)
    return getStrongProxyForHandle(0);
}
关键 1.2.2.1:getStrongProxyForHandle(0)

[frameworks/native/libs/binder/ProcessState.cpp]

// handle:参数传入 0
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        // 如果当前没有新的 BpBinder,或无法获取当前 BpBinder 的弱引用,需要创建一个新的 BpBinder
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
        	// ping 一下,检查 ServiceManager 是否可用
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }

            b = new BpBinder(handle); // b 为 Native 层 BpBinder 对象,handle 为 0
            e->binder = b; // 给 e->binder 赋值,下次直接返回已有的 BpBinder 对象
            // 设置 BpBinder 弱引用
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

	// 看这里,最终返回了 result,其类型为 BpBinder,且其 handle 为 0
    return result;
}
关键 1.2.3:javaObjectForIBinder()

[android_util_Binder.cpp–>javaObjectForIBinder()]

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;

    if (val->checkSubclass(&gBinderOffsets)) {
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        return object;
    }

    ...

    // val 对象实际类型是 Native 层 BpBinder
    // Native 层的 BpBinder 中有一个 ObjectManager 成员变量,它用来管理 Native BpBinder 上创建的 Java BpBinder 对象
    // 下面这个 findObject() 函数用来判断 gBinderProxyOffsets 是否已经保存在 ObjectManager 中。如果是,那就需要删除这个旧的对象
    // gBinderProxyOffsets 对应 Java 层的 BinderProxy
    // 也就是说,通过 findObject() 函数,看看 Native 层的 BpBinder 对象的成员变量 ObjectManager 有没有保存 Java 层的 BinderProxy 对象,有就删除,重新创建一个新的 Java 层的 BinderProxy 对象,然后保存到 Native 层的 BpBinder 对象的成员变量 ObjectManager 中
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL) {
        jobject res = jniGetReferent(env, object);
        if (res != NULL) {
            return res;
        }
        // 减去该 Proxy 对象的引用计数
        android_atomic_dec(&gNumProxyRefs);
        // 删除该 Proxy 对象
        val->detachObject(&gBinderProxyOffsets);
        env->DeleteGlobalRef(object);
    }

    // 创建一个新的 BinderProxy 对象(Java 层)
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL) {
        // val.get():获取智能指针指向的对象,直接看成 env 就行
        // 把 Native 层的 BpProxy 的指针指向的对象 val.get() 保存到 BinderProxy 的成员字段 mObject 中
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);
        
        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        // 将这个新创建的(Java 层) BinderProxy 对象注册(attach)到(Native 层) BpBinder 的 ObjectManager 中
        // 同时注册一个回调 proxy_cleanup。当 BinderProxy 对象撤销(detach)的时候,该函数会被调用,以释放一些资源,读者可自行研究 proxy_clean 函数
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);
        // DeathRecipientList 保存了一个用于死亡通知的 list
        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        // 将死亡通知 list 和 BiderProxy 对象联系起来
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        // Note that a new object reference has been created.
        // 增加该 Proxy 对象的引用计数
        android_atomic_inc(&gNumProxyRefs);
        // 下面这个函数用于垃圾回收。创建的 Proxy 对象一旦超过 200 个,该函数将调用 BinderInter 类的 ForceGc 做一次垃圾回收
        incRefsCreated(env);
    }

	// 返回 BinderProxy 对象(Java 层)
    return object;
}

到此,通过 javaObjectForIBinder() 方法,我们知道方法最终返回了一个 Java 层的 BinderProxy 对象,并且 BinderProxy 对象的 mObject 保存了 Native 层的 BpBinder 对象

  • 创建了一个 Java 层的 BinderProxy 对象
  • 通过 JNI,该 BinderProxy 对象和一个 Native 的 BpBinder 对象挂钩,而该 BpBinder 对象(handle 为 0)的通信目标就是 ServiceManager
回到 关键 1.1:ServiceManagerNative.asInterface()

把关键 1.2 的返回值作为参数,那么就相当于是 ServiceManagerNative.asInterface(BinderProxy) [frameworks/base/core/java/android/os/ServiceManagerNative.java]

// 该成员变量在父类 IServiceManager 中定义
static final String descriptor = "android.os.IServiceManager";

static public IServiceManager asInterface(IBinder obj)
{
    if (obj == null) {
        return null;
    }
    // 关键 1.1.1:obj.queryLocalInterface()
    IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    
    // 调用了 ServiceManagerProxy 的构造方法,参数类型为 BinderProxy
    return new ServiceManagerProxy(obj);
}
关键 1.1.1:obj.queryLocalInterface()

obj 实际为 BinderProxy,类 BinderProxy 定义在 Binder.java 中
[frameworks/base/core/java/android/os/Binder.java]

public IInterface queryLocalInterface(String descriptor) {
		// 返回 null
        return null;
    }

对于 关键 1.1 ServiceManagerNative.asInterface() 方法:

  • 返回的是 ServiceManagerProxy 对象(回答问题一,即 getIServiceManager() 返回的 ServiceManagerProxy 确实是 ServiceManager 的代理对象)
  • ServiceManagerProxy 对象包含了 BinderProxy
  • BinderProxy 关联着 Native 的 BpBinder 对象
  • Native 的 BpBinder 对象(handle 为 0)的通信目标是 ServiceManager
关键二:getIServiceManager().addService() 注册服务

getIServiceManager() 返回的是 ServiceManagerProxy 对象(ServiceManager 的代理对象)
[ServiceManagerNative.java–>ServiceManagerProxy.addService()]

class ServiceManagerProxy implements IServiceManager {
	// 在 关键 1.1 中调用了 ServiceManagerProxy 的构造方法,参数类型为 BinderProxy
	// 因此这里 remote 实际类型为 BinderProxy
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    public IBinder asBinder() {
        return mRemote;
    }
    
    public IBinder getService(String name) throws RemoteException {...}

    public IBinder checkService(String name) throws RemoteException {...}

    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); // 要注册的 Service 的名称
        // 关键 2.1:Parcel#writeStrongBinder()
        data.writeStrongBinder(service); // 将 Service 写进 Parcel
        data.writeInt(allowIsolated ? 1 : 0);
        // mRemote 实际上就是 BinderProxy 对象,调用它的 transact() 方法,将封装好的请求数据发送出去
        // 关键 2.2:BinderProxy#transact()
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
    
    public String[] listServices() throws RemoteException {...}

    public void setPermissionController(IPermissionController controller) throws RemoteException {...}

    private IBinder mRemote;
}
关键 2.1:Parcel#writeStrongBinder()

[frameworks/native/libs/binder/Parcel.cpp]

/**
 * Write an object into the parcel at the current dataPosition(),
 * growing dataCapacity() if needed.
 */
public final void writeStrongBinder(IBinder val) {
	// 关键 2.1.1:nativeWriteStrongBinder()
    nativeWriteStrongBinder(mNativePtr, val);
}
关键 2.1.1:nativeWriteStrongBinder()

nativeWriteStrongBinder() 是一个 native 函数
[frameworks/native/libs/binder/Parcel.cpp]

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
	// 关键 2.1.1.1:flatten_binder()
    return flatten_binder(ProcessState::self(), val, this);
}
关键 2.1.1.1:flatten_binder()

将 binder 对象转为 struct flat_binder_object 对象

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
	// 定义 flat_binder_object 结构体
    flat_binder_object obj;

	// 当结构体 flat_binder_object 描述的是一个 Binder 实体对象(还可以描述 Binder 引用对象)时,才有实际意义
	// 可用来描述 Binder 实体对象在处理一个进程间通信请求时,其所运行的线程应当具有的最小线程优先级
    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
        /* minimum priority for all nodes is nice 0 */
        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
    } else {
        /* minimum priority for all nodes is MAX_NICE(19) */
        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    }

    if (binder != NULL) { // 传入的 binder 肯定不为 NULL,走这里
    	// 其实 binder 是我们要注册的服务,即 BBinder
    	// 可以查看 frameworks/native/libs/binder/Binder.cpp 中的 BBinder::localBinder() 函数,返回的是 this 即 BBinder 本身
    	// 也很容易理解,服务获取本地 Binder,返回的是自己没毛病
        IBinder *local = binder->localBinder(); // local 返回 this,不为空
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else { // local 不为空,走这里
        	// 下面是给 lat_binder_object 结构体成员变量赋值的过程

			// type 可用来区分当前结构体描述的是 Binder 实体类型还是 Binder 引用类型
            obj.type = BINDER_TYPE_BINDER; // type = BINDER_TYPE_BINDER,表示描述的是一个强类型的 Binder 实体对象
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); // 当前是描述的是 Binder 实体对象,binder 指向与该 Binder 实体对象对应的一个 Service 组件内部的一个弱引用计数对象(weakref_impl)的地址
            obj.cookie = reinterpret_cast<uintptr_t>(local); // 当前是描述的是 Binder 实体对象,cookie 指向 Service 组件的地址
        }
    } else {
        obj.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

	// 关键 2.1.1.1.1:finish_flatten_binder()
    return finish_flatten_binder(binder, obj, out);
}
  • 对于 Binder 实体,使用 cookie 记录 Binder 实体的指针
  • 对于 Binder 代理,使用 handle 记录 Binder 代理的句柄
关键 2.1.1.1.1:finish_flatten_binder()

将 struct flat_binder_object 对象写入到 Parcel out 中
[frameworks/native/libs/binder/Parcel.cpp]

inline static status_t finish_flatten_binder(
    const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
	// Parcel::writeObject() 函数作用:
        // 添加前,计算容量还够
            // 1. 通过指针 mData 和指针偏移量 mDataPos 来存储数据 flat
            // 2. 调用 finishWrite(sizeof(flat_binder_object)) 函数更新指针偏移量 mDataPos
        // 添加前,计算容量不够
            // 调用 growData() 函数更新指针 mData
            // 使用 goto restart_write 语句,代码返回到再次添加数据的地方执行
    return out->writeObject(flat, false);
}

小结:关键 2.1 把 binder 对象转为 struct flat_binder_object 对象,写到了 Parcel out 中

关键 2.2:BinderProxy#transact()

BinderProxy 的 transact 是一个 native 函数
[android_util_Binder.cpp–>android_os_BinderProxy_transact()]

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
    ...
    // 从 Java 的 Parcel 对象中得到作为参数的 Native 的 Parcel 对象
    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) {
        return JNI_FALSE;
    }
    // 得到一个用于接收回复的 Parcel 对象
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

	// 还记得在 关键 1.2.3:javaObjectForIBinder() 函数中的一些对应关系,这里再总结一下:
	// gBinderProxyOffsets 对应 Java 层的 BinderProxy
	// Native 层的 BpProxy 保存在 Java 层 BinderProxy 对象的成员变量 mObject 中
	// 因此,我们可以通过 gBinderProxyOffsets 获取到 Java 层的 BinderProxy,通过 Java 层的 BinderProxy 的成员变量 mObject 获取到 Native 层的 BpProxy
    // 获取 Native 的 BpBinder 对象
    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    if (target == NULL) {
        return JNI_FALSE;
    }

    ...
    // 通过 Native 的 BpBinder 对象将请求发送给 ServiceManager
    // code:ADD_SERVICE_TRANSACTION
    // flags:0
    // 关键三:BpBinder::transact()
    status_t err = target->transact(code, *data, reply, flags);
    ...

    signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/, data->dataSize());
    return JNI_FALSE;
}

上面的代码流程只是 Java 层注册服务到 Service Manager 过程的一部分,即把注册服务的请求交给了 Native 层的 BpBinder,由此,我们发现 Java 层的 Binder 最终还是要借助 Native 的 Binder 进行通信

关键三:BpBinder::transact()
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) {
    	// mHandle:查看 关键 1.2.2.1:getStrongProxyForHandle(0) 函数,其中 handle 传入的是 0
    	// code:ADD_SERVICE_TRANSACTION
    	// data:要传递给 Binder 驱动的数据
    	// reply:用于接收回复的 Parcel 对象
    	// flags:传入的 0
    	
    	// BpBinder::transact() 最终把 transact 的活交给了 IPCThreadState
    	// 关键 3.1:IPCThreadState::self()
    	// 关键 3.2:IPCThreadState::self()->transact()
        status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}
关键 3.1:IPCThreadState::self()

[frameworks/native/libs/binder/IPCThreadState.cpp]

static bool gHaveTLS = false; // gHaveTLS 默认为 false
static pthread_key_t gTLS = 0;

IPCThreadState* IPCThreadState::self()
{
    // 首次进入 gHaveTLS 默认为 false
    if (gHaveTLS) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        // 创建 IPCThreadState 对象实例并返回
        return new IPCThreadState;
    }

    if (gShutdown) {
        return NULL;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) { // 首次进入 gHaveTLS 默认为 false,走这里
        // pthread_key_create():创建线程的 TLS(Thread Local Storage)
        // - 用于创建线程本地存储空间
        // - 每个线程都有自己的 TSL(Thread Local Storage),该空间为线程私有,线程间不共享
        // - 可通过 pthread_setspecific()、pthread_getspecific() 函数在线程中存取数据
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        // gHaveTLS 置为 true
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    // 首次进入 gHaveTLS 默认为 false,执行 goto restart 语句,代码从第 7 行开始执行,创建 IPCThreadState 对象
    goto restart;
}

IPCThreadState::self() 函数最终会创建并返回 IPCThreadState 对象

关键 3.2:IPCThreadState::self()->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 传入 0,此时置为 TF_ACCEPT_FDS
    flags |= TF_ACCEPT_FDS;

    ...

    if (err == NO_ERROR) { // 数据没错
        ...
        // 关键四:writeTransactionData() 用来传输数据
        // flags:TF_ACCEPT_FDS
        // handle:传入的 0
        // code:ADD_SERVICE_TRANSACTION
    	// data:要传递给 Binder 驱动的数据

		// 关键 3.2.1:writeTransactionData()
        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) { // flags:传入的 0,走这里
        ...
        // reply:用于接收回复的 Parcel 对象
        if (reply) { // 不为空,走这里
        	// 关键 3.2.2:waitForResponse()
            err = waitForResponse(reply); // 发送 BC_TRANSACTION 命令协议
        } else { // 当前需要同步,但是 reply 又为 false,表示不需要等待结果返回
            Parcel fakeReply; // fake 中文意思为伪造,这里是伪造 reply
            err = waitForResponse(&fakeReply);
        }
        ...
    } else { // ONE_WAY,不需等待 reply
        err = waitForResponse(NULL, NULL);
    }

    return err;
}
关键 3.2.1:writeTransactionData()

[frameworks/native/libs/binder/IPCThreadState.cpp]

// cmd:BC_TRANSACTION
// binderFlags:TF_ACCEPT_FDS
// handle:0
// code:ADD_SERVICE_TRANSACTION
// data:要传递给 Binder 驱动的数据
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    // binder 驱动通信的数据结构
    binder_transaction_data tr;

    tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
    tr.target.handle = handle; // handle = 0,用于标识目的端
    tr.code = code; // code = ADD_SERVICE_TRANSACTION
    tr.flags = binderFlags; // binderFlags = TF_ACCEPT_FDS
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;

    // 数据错误检查
    const status_t err = data.errorCheck();
    if (err == NO_ERROR) { // 数据没有出错,给 binder_transaction_data 赋值
        tr.data_size = data.ipcDataSize(); // 数据大小
        tr.data.ptr.buffer = data.ipcData(); // 把 struct flat_binder_object 数据赋值给 tr.data.ptr.buffer
        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); // mObjectsSize,结构体在数组中的偏移量(size_t),会有很多个结构体???
        tr.data.ptr.offsets = data.ipcObjects(); // mObjects,Binder 数据在结构体中的偏移量(uintptr_t),结构体中不止包含 Binder 数据,还有其他数据,要获取 Binder 数据,需要知道 Binder 数据在结构体中的偏移量???
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
        tr.offsets_size = 0;
        tr.data.ptr.offsets = 0;
    } else {
        return (mLastError = err);
    }

	// mOut 在 IPCThreadState.h 中定义,类型为 Parcel,mOut 存储发往 Binder 设备的数据
    // 先网 mOut 中写入请求码
    mOut.writeInt32(cmd); // cmd = BC_TRANSACTION
    // 再往 mOut 中写入请求数据
    mOut.write(&tr, sizeof(tr)); // 将 binder_transaction_data 写入到 mOut 中
    // 此时 Parcel mOut 的存储结构为:(cmd = BC_TRANSACTION)+(struct binder_transaction_data)

    return NO_ERROR;
}

把 struct flat_binder_object 对象(在 Parcel 中传递的数据结构)转为 truct binder_transaction_data 对象(和 Binder 驱动通信的数据结构)
最后 Parcel mOut 的存储结构为:(cmd = BC_TRANSACTION)+(struct binder_transaction_data)
对于 struct binder_transaction_data,我们看看它的数据结构

struct binder_transaction_data {
	union {
		size_t handle; // 0
		void *ptr;
	} target;
	void cookie;
	unsigned int code; // ADD_SERVICE_TRANSACTION
	unsigned int flags; // TF_ACCEPT_FDS
	pid_t sender_pid;
	uid_t sender_euid;
	size_t data_size; // 存储数据的大小
	size_t offsets_size; // 结构体数据偏移量
	union {
		struct {
			const void *buffer; // 存储数据包括一般数据和 Binder 数据,当前这里对应 struct flat_binder_object 的数据
			const void *offsets; // Binder 数据在当前 struct binder_transaction_data 数据结构中的偏移量
		} ptr;
		uint8_t buf[8];
	} data;
};

target.handle:标识通信的目的端,为 0,即 ServiceManager
code :ADD_SERVICE_TRANSACTION,在后面用来区分到底是要调用那个函数
data_size:数据大小
data.ptr.buffer:存储的数据,有一般数据和 Binder 数据
offsets_size:数组内偏移量
data.ptr.offsets Binder 数据在整个数据中的偏移位置,加上上面数组内偏移量,就可以获取到 Binder 对象

关键 3.2.2:waitForResponse()

[frameworks/native/libs/binder/IPCThreadState.cpp]

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        // 关键四:talkWithDriver() 和 Binder 驱动程序进行交互
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32();

        ...

        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:
            {
                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));
                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;
}
关键四:talkWithDriver()

和 Binder 驱动程序进行交互
[frameworks/native/libs/binder/IPCThreadState.cpp]

// talkWithDriver() 函数在 IPCThreadState.h 中声明,doReceive:为默认参数,默认值为 true
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ...

    // binder_write_read 是用来与 binder 设备进行交换数据的结构
    binder_write_read bwr;
    
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    // 请求命令的填充
    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();
    
    if (doReceive && needRead) {
        // bwr 接收数据缓冲区信息的填充。如果以后收到数据,就直接填充在 mIn 中了(然后再交给 bwr???)
        bwr.read_size = mIn.dataCapacity(); // mIn,接收来自 Binder 设备的数据
        bwr.read_buffer = (uintptr_t)mIn.data(); // 把指针传给了 bwr
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }

    ...
    
    // 读缓存和写缓存都为空,则返回
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {
        ...
#if defined(__ANDROID__)
        // 通过 ioctl 不停的读写,跟 binder driver 进行通信
        // 进入内核, 传递的参数是 struct binder_write_read
        // 关键 4.1:ioctl()
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
        if (mProcess->mDriverFD <= 0) {
            err = -EBADF;
        }
        ...
    } while (err == -EINTR);

    ...

    if (err >= NO_ERROR) {
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                mOut.remove(0, bwr.write_consumed); // 将已处理的命令移除
            else
                mOut.setDataSize(0);
        }
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed); // 将读取出来的返回协议保存在 mIn 中,在返回到 waitForResponse 时,就可以解析 mIn 中的内容了 
            mIn.setDataPosition(0);
        }
        ...
        return NO_ERROR;
    }

    return err;
}
关键 4.1:ioctl()

进入内核,通过 ioctl 不停的读写,跟 binder driver 进行通信,传递的参数是 struct binder_write_read
内核处理过程:

  1. 读取 BC_TRANSACTION 命令协议和 struct binder_transaction _data
  2. 根据 handle 找到 Binder 实体对象,然后找到 Server Process
  3. 将一个 BR_TRANSACTION_COMPLETE 返回协议发送到 Client Process 中,把返回协议写到 mIn 中
  4. 现在已经返回到 IPCThreadState 的 talkWithDriver(),又返回到 waitForResponse() 中处理 BR_TRANSACTION_COMPLETE,然后开始等待 Server Process 返回结果
处理 BR_TRANSACTION 返回协议的同时:
  1. 将一个 BINDER_WORK_TRANSACTION_COMPLETE 工作项添加到 Client Process 队列中处理,同时将一个 BINDER_WORK_TRANSACTION 工作项添加到 Server Process 队列中处理
  2. 内核处理 BINDER_WORK_TRANSACTION_COMPLETE 工作项,向 Server Process发送了一个 BR_TRANSACTION返回协议
  3. ServiceManager 所在进程被唤醒后,会调用 binder_parse() 处理返回协议
  4. ServiceManager 根据参数,判断执行操作 SVC_MGR_ADD_SERVICE。调用对应的函數 do_add_service() 函数为要注册的 Service 创建 svcinfo 结构体,并添加到全局队列 svclist 中(以后就可以直接从全局队列 svclist 中查所需的 service 了)
发送和处理 BC_REPLY 命令协议:

ServiceManager 进程注册成功后,就会通过 IO 控制命令 BINDER_WRITE_READ 将 BC_REPLY 发送到 kernel

int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;

    bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    // ioctl 过程
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    return res;
}

之后都是在 Kernel 中完成的操作,在 kernel 中的处理:

  1. 读取 BC_REPLY命令协议
  2. 找到 target process(现在是Client Process)
  3. 将一个 BINDER_WORK_TRANSACTION_COMPLETE 工作项添加到 ServiceManager Process 队列中处理,同时将一个 BINDER_WORK_TRANSACTION 工作项添加到 Client Process 队列中处理,这两个工作项是并行处理的
  4. 处理 BINDER_WORK_TRANSACTION_COMPLETE 工作项,将一个 BR_TRANSACTION_COMPLETE 返回协议发送到 ServiceManager 中

ServiceManager 处理完 BR_TRANSACTION_COMPLETE 后,就又开始等待新的进程间通信请求了

发送和处理 BR_REPLY 返回协议:

在前面处理 BC_REPLY 中,会并行将一个 BINDER_WORK_TRANSACTION 工作项添加到 Client Process 队列中处理

  1. kernel 根据 BINDER_WORK_TRANSACTION 工作项,向 Client Process 发送一个 BR_REPLY 返回协议
  2. Client Process 返回到 IPCThreadState的talkWithDriver(),再回到 waitForResponse 中处理 BR_REPLY
  3. waitForResponse() 函数中将返回的結果取出,保存在 Parcel 对象的 reply 中。然后跳出循环,方法结束。至此,Service 的注册过程就执行完了

Service 注册之后,就会启动 Binder thread pool,等待 client 的请求,此时 Service 将作为 Service 端处理收到的请求,收到的请求会通过 executeCommand() 进行处理

请求和响应

处理 BR_TRANSACTION 返回协议的过程,对应我们平时请求服务,挂起客户端进程的阶段
处理 BR_REPLY 返回协议的过程,对应我们平时请求服务,收到服务端返回的结果的阶段

四、AIDL

三、Java 层中的 Binder 分析 中,我们发现在 Java 层 Binder 的架构中,Bp 端(客户端)可以通过 BinderProxy(如:Java 层 ServerManagerProxy#addService() -> Java 层 BinderProxy#transact() -> 获取 Java 层 BinderProxy 对象 mObject 中保存的 native 层 BpBinder,BpBinder#transact())的 transact() 方法与 Bn 端(服务端)发送请求,而 Bn 端通过继承 Binder 类重写 onTransact() 接受并处理来自 Bp 端的请求。这个结构非常清晰而且简单,但是实现起来却颇为繁琐。于是 Android 提供了 AIDL 语言以及 AIDL 解释器自动生成一个服务端的 Bn 端 以及客户端的 Bp 端

这里先介绍使用 AIDL 来进行进程间通信的流程,分为服务端和客户端两个方面。
1.服务端
服务端首先要创建一个 Service 用来监听客户端的连接请求,然后创建一个 AIDL 文件,将暴露给客户端的接口在这个 AIDL 文件中声明,最后在 Service 中实现这个 AIDL 接口即可

2.客户端
客户端所要做事情就稍微简单一些,首先需要绑定服务端的 Service,绑定成功后,将服务端返回的 Binder 对象转成 AIDL 接口所属的类型,接着就可以调用 AIDL 中的方法了

3.AIDL 接口的创建
首先看 AIDL 接口的创建,如下所示,我们创建了一个后缀为 AIDL 的文件,在里面声明了一个接口 interface IBookManager 和两个接口方法 getBookList()addBook()

// IBookManager.aidl
package com.ryg.chapter_2.aidl;

import com.ryg.chapter_2.aidl.Book;

interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
}

另外一个需要注意的地方是,如果 AIDL 文件中用到了自定义的 Parcelable 对象,那么必须新建一个和它同名的 AIDL 文件,并在其中声明它为 Parcelable 类型。在上面的 IBookManager.aidl 中,我们用到了 Book 这个类,所以,我们必须要创建 Book.aidl,然后在里面添加如下内容:

package com.ryg.chapter_2.aidl;
parcelable Book;

4.远程服务端 Service 的实现
上面讲述了如何定义 AIDL 接口,接下来我们就需要实现这个接口了。我们先创建一个 Service,称为 BookManagerService,代码如下:

public class BookManagerService extends Service {
	private static final String TAG = "BMS";
	
	private CopyOnWriteArrayList<Book> mBookList = new CopyOnWriteArrayList<Book>();
	
	private Binder mBinder = new IBookManager.Stub() {
		@Override
		public List<Book> getBookList() throws RemoteException {
			return mBookList;
		}
	
		@Override
		public void addBook(Book book) throws RemoteException {
			mBookList.add(book);
		}
	};
	
	@Override
	public void onCreate() {
		super.onCreate();
		mBookList.add(new Book(1, "Android"));
		mBookList.add(new Book(2, "Ios"));
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}
}

5.客户端的实现
客户端的实现就比较简单了,首先要绑定远程服务,绑定成功后将服务端返回的 Binder 对象转换成 AIDL 接口,然后就可以通过这个接口去调用服务端的远程方法了,代码如下所示

public class BookManagerActivity extends Activity {
	private static final String TAG = "BookManagerActivity ";
	
	private ServiceConnection mConnection = new ServiceConnection() {
		public void onServiceConnected(ComponentName className, IBinder service) {
			// 问题 1:这里的 service 其实是 BookManagerService#onBind() 方法的返回值,即服务端的 Sub 对象的本地代理
			// 至于为什么是 BookManagerService#onBind() 方法的返回值,请参考:[bindService() 调用流程]()
			// 问题 2:为什么要 IBookManager.Stub.asInterface() 这样调用
			// 用于将服务端的 Binder 对象转换成客户端所需的 AIDL 接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的就是服务端的 Sub 对象本身,否则返回的是系统封装后的 Stub.proxy 对象,而 Stub.proxy 对象实现了 IBookManager 接口,因此在下面可以顺利通过接口方法进行远程调用
			IBookManager bookManager = IBookManager.Stub.asInterface(service);
			try {
				List<Book> list = bookManager.getBookList();
				Log.i(TAG, "query book list, list type:" + list.getClass().getCanonicalName());
				Log.i(TAG, "query book list:" + list.toString());
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	
		public void onServicceDisconnected(ComponentName className) {
		
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_book_manager);
		Intent intent = new Intent(this, BookManagerService.class);
		bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
	}
	
	@Override
	protected void onDestroy() {
		unbindService(mConnection);
		super.onDestroy();
	}
}