该文章是一个系列文章,是本人在 Android 开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android 开发艺术探索》以及《深入理解 Android 卷 Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!另外,本系列文章知识可能需要有一定 Android 开发基础和项目经验的同学才能更好理解,也就是说该系列文章面向的是 Android 中高级开发工程师。
我们在上一篇中比较详尽的介绍了 Android 的消息机制,不过有一些内容我们在不理解 Android Binder 的话是无法讲解清楚的。对于初学 Android 的朋友而言,最难却又最想掌握的恐怕就是 Binder 机制了,因为 Android 系统基本上可以看作是一个基于 Binder 通信的 C/S 架构。 Binder 就像网络一样,把系统的各个部分连接在了一起,因此它是非常重要的。我们下面会 Android Binder 机制进行从上到下从易到难的分层次讲解,从而既能让初学者对 Binder 有一定认识,也能让有一定 Android 基础的人获得收获。
注:下文中的源码均出自 android-6.0.0_r5
对于初学者来说,深入 Android Binder 机制是非常不明智的。Android Binder 机制大都涉及 Java 层、Native 层、驱动层这三三个方面,对于初学者来说想啃这三块硬骨头很容易磕着牙。我们这这一节概述从以下几个方面让你从比较宏观的角度理解 Android Binder。
在该系列博客中的第一章我们就说起了 Android 进程相关问题,Android 故意弱化了进程的概念,而用相对容易理解的四大组件。可是我们在稍微深入 Android 的时候,那么进程是绕不过的。默认情况下,同一个应用程序中的所有组件运行在同一个进程中,而且绝大多数的应用程序也都是这样的。这个默认进程是用这个应用的包名来命名的。
我们在运行 App 的时候经常需要使用一些系统服务,比如剪切板服务,而剪切板服务是运行在 SystemServer 进程中的。那我们的 App 是怎么使用剪切板服务的呢,我们都知道进程是相互独立的,静态变量等等都无法共用。这就涉及到进程间的通信了,即 IPC。我们都知道 Android 是基于 Linux 内核的,那我们简单介绍下 Linux 下的几种 IPC 机制。
管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。
命名管道是一种特殊类型的文件,它在系统中以文件形式存在。这样克服了管道的弊端,他可以允许没有亲缘关系的进程间通信。
共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由 IPC 为进程创建的一个特殊地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到自己的地址空间中。所有进程都可以访问共享内存中的地址,如果一个进程向共享内存中写入了数据,所做的改动将立刻被其他进程看到。
作为 Android 系统下的一种 IPC 机制,其本质上与上面罗列出的 IPC 机制并无本质上的不同,都是作为进程间通信的一种手段。并且在 Android 系统中也不是只存在 Binder 这一种进程间通信的方式,在有些地方也使用了 Socket。既然 Linux 已经提供了众多 IPC 机制,那么 Android 为何还要使用 Binder 作为主要的进程间通信的方式呢,那么当然有他的优点存在。
Java 层 Binder 的功能,依赖于 Native 层 Binder 来实现,可以认为 Java 层 Binder 架构是 Native 层 Binder 架构的一个镜像。但是这并不影响我们分析 Android Java 层 Binder 的功能。我们用一个例子来说明这个过程。
我们在第一篇中就讲解了 SystemServer 这个进程,这个进程和 zygote 进程一起撑起了 Android 世界,他们之中有一个崩溃,Android 世界就会砰然倒塌。Android 许多的重要的系统服务如 AMS、PMS 等都运行在 SystemServer 进程中。但是还有一个比较重要的进程 ServiceManager 进程(简称 SM)跟 zygote 是兄弟进程。这个进程的作用是用来统一管理服务,如 AMS。它们之间的关系如下。
我们的 AMS 需要向 SM 进程中注册信息,其他进程如果想使用 AMS,那么先和 ServiceManager 进程进行通信查询,接着再和 AMS 所在 SystemServer 进程通信。这部分关系图如下
我们这里仅上图分析①②③中的一条道路,我们来分析③,即我们的应用进程(Client)如何与服务进程(Server)交互。
Java 层的 Binder, 我们来看涉及的类的结构图
[IBinder.java]
- public interface IBinder {
- //交互函数
- public boolean transact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException;
- }
我们接着来看 Binder 和 BinderProxy 他们都声明在 Binder.java 中
[Binder.java]
- /**
- Binder类
- */
- public class Binder implements IBinder {
- public final boolean transact(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException {
- ......
- //这里调用了onTransact函数进行处理,一般情况下这个函数都会被它的子类重写
- boolean r = onTransact(code, data, reply, flags);
- if (reply != null) {
- reply.setDataPosition(0);
- }
- return r;
- }
- }
- /**
- BinderProxy类
- */
- final class BinderProxy implements IBinder {
- public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
- //直接以JNI的方式调用Native层的transact函数
- return transactNative(code, data, reply, flags);
- }
- public native boolean transactNative(int code, Parcel data, Parcel reply,
- int flags) throws RemoteException;
- }
通用的 IPC 流程如下
现在假设下面一个场景,我们的应用进程即我们的 App 想要使用 ActivityManagerService 的 startActivity 函数 (这种场景肯定有的,当我们拿到手机的时候,手机已经预装了许多 App, 其中 Launcher App(桌面管理 App) 是在 Android 系统启动完成之后启动的第一个 App,我们安装好一个应用后,点击应用图标即发出 Intent,想要启动另一个 App 中的 Activity,我们在 AndroidManifest.xml 中注册了 Main Activity)。Launcher App 所在的进程要与 AMS 所在的进程 SystemServer 进程交互。
我们来看这个例子。按照上面的通用流程我们猜测 Launcher 进程与 SystemServer 进程交互过程也如上图所示,那么按照这个思路我们来看。分为 3 点:
这一部分是我们的上图中的 test 函数所声明的类或者接口,我们的 Client 端代理和 Server 端服务都要实现这个函数。果然有
[IActivityManager.java]
- public interface IActivityManager extends IInterface {
- public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
- String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
- ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
- ......
- }
这里声明了我们将要调用的业务函数 startActivity,那么接着第二点
ActivityManagerProxy 是在 ActivityManagerNative.java 中声明的内部类
- class ActivityManagerProxy implements IActivityManager
- {
- public ActivityManagerProxy(IBinder remote)
- {
- mRemote = remote;
- }
- public IBinder asBinder()
- {
- return mRemote;
- }
- public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
- String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(caller != null ? caller.asBinder() : null);
- data.writeString(callingPackage);
- intent.writeToParcel(data, 0);
- data.writeString(resolvedType);
- data.writeStrongBinder(resultTo);
- data.writeString(resultWho);
- data.writeInt(requestCode);
- data.writeInt(startFlags);
- if (profilerInfo != null) {
- data.writeInt(1);
- profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } else {
- data.writeInt(0);
- }
- if (options != null) {
- data.writeInt(1);
- options.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- //看这里果然是通过mRemote.transact函数,这里的mRemote是BinderProxy类,关于这一点我们在Native层分析的时候再给出
- mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
- reply.readException();
- int result = reply.readInt();
- reply.recycle();
- data.recycle();
- return result;
- }
- ......
- }
ActivityManagerNative 是继承于 Binder 的抽象类,并重写了 onTransact 方法
- public abstract class ActivityManagerNative extends Binder implements IActivityManager{
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- //根据code处理相应的业务逻辑,我们这里是START_ACTIVITY_TRANSACTION
- switch (code) {
- case START_ACTIVITY_TRANSACTION:
- {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder b = data.readStrongBinder();
- IApplicationThread app = ApplicationThreadNative.asInterface(b);
- String callingPackage = data.readString();
- Intent intent = Intent.CREATOR.createFromParcel(data);
- String resolvedType = data.readString();
- IBinder resultTo = data.readStrongBinder();
- String resultWho = data.readString();
- int requestCode = data.readInt();
- int startFlags = data.readInt();
- ProfilerInfo profilerInfo = data.readInt() != 0
- ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
- Bundle options = data.readInt() != 0
- ? Bundle.CREATOR.createFromParcel(data) : null;
- int result = startActivity(app, callingPackage, intent, resolvedType,
- resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
- reply.writeNoException();
- reply.writeInt(result);
- return true;
- }
- }
- }
既然 ActivityManagerNative 是个抽象类,那么谁真正实现了呢
[ActivityManagerService.java]
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- //重写了onTransact函数
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- ......
- try {
- //调用父类即ActivityManagerNative的onTransact函数
- return super.onTransact(code, data, reply, flags);
- } catch (RuntimeException e) {
- throw e;
- }
- }
- }
Launcher 进程与 SystemServer 进程交互过程如下
关于 Java 层的 Binder 机制,我们只需要理解以 BinderProxy 代表的代理端和 Binder 代表的服务端的概念即可,例如我们本例中的 AMS,AMS 是运行在 SystemServer 进程中的服务端,它间接继承于 Binder,在得到相关请求后,会调用 AMS 重写的 onTransact 函数进行逻辑处理。那么这个请求就是是 AMS 的客户端 ActivityManagerProxy 通过 Binder 的方式发给它的,ActivityManagerProxy 发送这个请求的方式,是通过调用其内部的成员变量 mRemote, 这个 mRemote 其实是 BinderProxy 的对象,然后 BinderProxy 通过 JNI 调用 Native 层对应函数,最终通过 Binder 驱动达到与 SystemServer 交互的目的。
那么还遗留下以下几个问题:
1. 服务器端的代理怎么获得的
2. 位于代理类中的 mRemote 这个变量
要想理解好上面的个问题,我们必须向 Native 层进军。
我们依然以 AMS 分析,我们先来想一下我们在用户进程中即我们的 App 中想使用 AMS 或者其他剪切板之类的系统服务函数了怎么办??按照上面的分析我们要获得 AMS 的代理 ActivityManagerProxy
[ActivityManagerNative.java]
- //这里我们的App进程从SM进程得到AMS服务对应的客户端代理BinderProxy
- IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
- //以BinderProxy为参数得到我们ActivityManagerProxy,并把BinderProxy对象存储在mRemote变量中
- IActivityManager am = asInterface(b);
- return am;
到这里我们就有以下问题,本小节分析 1,2
1. 既然可以通过 SM 获得对应的客户端代理,那么 AMS 必定已经注册在 SM 中了,那么怎么注册的呢?
2. AMS 代理是如何获得的?
3. AMS 代理是如何与 Binder 通信的?
我们来一一分析,在分析问题之前我们先做一个假设,这个假设至关重要,那就是不管我们的 SystemServer 进程与 SM 进程交互也好还是我们的 App 进程与 SM 进程也好,SM 的代理已经事先创建完毕,即不管我们在 SystemServer 端还是 App 端,在与 SM 进程交互的时候不用考虑代理怎么获得的。为什么会有如此假设,因为我自己深受其害,由于上述三个过程均是通过 Binder,很容易陷入思维混乱。
我们 SystemServer 进程中的 AMS 通过 "Socket" 与 SM 进程交互,并把自己注册在 SM 中
SystemServer 创建出 ActivityManagerService 后,最终将调用其 setSystemProcess 方法:
[SystemServer.java]
- public void setSystemProcess() {
- try {
- //注册服务,第二个参数为this,这里通过"socket"与SM交互
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
- ..........
- } catch (PackageManager.NameNotFoundException e) {
- ........
- }
- }
上面的请求最终是通过 SM 服务代理发送的()
[ServiceManagerNative.java]
- public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
- //将数据打包写入Parcel对象
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- //注意这个地方,后文分析,此时的service为ActivityManagerService
- data.writeStrongBinder(service);
- data.writeInt(allowIsolated ? 1 : 0);
- //调用BindProxy的transact函数
- mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
- reply.recycle();
- data.recycle();
- }
上面的过程已经分析过了, 这里我们主要看一下哪个对应的 native 层的 transact 函数
[android_ util_Binder.cpp]
- static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
- jint code, jobject dataObj, jobject replyObj, jint flags)
- {
- ........
- //将java对象转化为native对象
- Parcel* data = parcelForJavaObject(env, dataObj);
- .........
- Parcel* reply = parcelForJavaObject(env, replyObj);
- ........
- //得到native层的BpBinder
- IBinder* target = (IBinder*)
- env->GetLongField(obj, gBinderProxyOffsets.mObject);
- ........
- //通过BpBinder利用IPCThreadState,将请求通过Binder驱动发送给SM进程
- status_t err = target->transact(code, *data, reply, flags);
- ........
- }
SM 进程收到信息后便处理这个消息(这个说法并不准确,准确的说法是,SM 进程中主线程一直在与 binder 设备交互,想必读者也猜到了 for(;;)), 有消息时便通过预先定义好的函数进行处理
[service_manager.c]
- switch(txn->code) {
- case SVC_MGR_ADD_SERVICE:
- s = bio_get_string16(msg, &len);
- if (s == NULL) {
- return -1;
- }
- handle = bio_get_ref(msg);
- allow_isolated = bio_get_uint32(msg) ? 1 : 0;
- //do_add_service
- if (do_add_service(bs, s, len, handle, txn->sender_euid,
- allow_isolated, txn->sender_pid))
- return -1;
- break;
- }
- int do_add_service(struct binder_state *bs,
- const uint16_t *s, size_t len,
- uint32_t handle, uid_t uid, int allow_isolated,
- pid_t spid)
- {
- //结构体si,用来存储服务信息
- struct svcinfo *si;
- //判断服务有没有权限注册,并不是所有的服务都能注册
- if (!svc_can_register(s, len, spid)) {
- return -1;
- }
- //查询服务有没有注册过
- si = find_svc(s, len);
- if (si) {//已经注册过
- if (si->handle) {
- ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
- str8(s, len), handle, uid);
- svcinfo_death(bs, si);
- }
- si->handle = handle;
- } else {//还没有注册过,我们进入这个分支
- si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
- if (!si) {
- ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
- str8(s, len), handle, uid);
- return -1;
- }
- //保存一些handle等信息
- si->handle = handle;
- si->len = len;
- memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
- si->name[len] = '\0';
- si->death.func = (void*) svcinfo_death;
- si->death.ptr = si;
- si->allow_isolated = allow_isolated;
- si->next = svclist;
- svclist = si;
- }
- binder_acquire(bs, handle);
- binder_link_to_death(bs, handle, &si->death);
- return 0;
- }
看到这里 SM 貌似只保留了一些 AMS 的信息而已,实际上并不只是如此,我们来看一下上面的保留问题
[Parcel.java]
- data.writeStrongBinder(service);
- public final void writeStrongBinder(IBinder val) {
- //调用了native函数
- nativeWriteStrongBinder(mNativePtr, val);
- }
跟进 [android_os_Parcel.cpp]
- static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
- {
- Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- //native层的parcel
- const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
- }
- sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
- {
- if (obj == NULL) return NULL;
- //obj为Binder类
- if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
- JavaBBinderHolder* jbh = (JavaBBinderHolder*)
- env->GetLongField(obj, gBinderOffsets.mObject);
- //调用了JavaBBinderHolder的get方法
- return jbh != NULL ? jbh->get(env, obj) : NULL;
- }
- //obj为BinderProxy类
- if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
- return (IBinder*)
- env->GetLongField(obj, gBinderProxyOffsets.mObject);
- }
- ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
- return NULL;
- }
跟进 [Pacel.cpp]
- status_t Parcel: :writeStrongBinder(const sp < IBinder > &val) {
- return flatten_binder(ProcessState: :self(), val, this);
- }
- status_t flatten_binder(const sp < ProcessState > &
- /*proc*/
- , const sp < IBinder > &binder, Parcel * out) {
- flat_binder_object obj;
- obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
- if (binder != NULL) { //binder不为空
- IBinder * local = binder - >localBinder(); //是不是本地binder,本地的意思是同一个进程中的调用
- 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 { //我们这里明显不是
- obj.type = BINDER_TYPE_BINDER;
- obj.binder = reinterpret_cast < uintptr_t > (local - >getWeakRefs());
- obj.cookie = reinterpret_cast < uintptr_t > (local);
- }
- } else { //错误信息
- obj.type = BINDER_TYPE_BINDER;
- obj.binder = 0;
- obj.cookie = 0;
- }
- return finish_flatten_binder(binder, obj, out);
- }
通过上面的代码,我们可以看到当一个服务进行注册时,会将 Java 层的 Binder 对象和 Native 层的 BBinder 关联起来,于是服务端绑定到了 Native 层的 Binder 架构。
此外,addService 中打包传入的其实不是 ActivityManagerService 本身,而是对应的 JavaBBinder 对象。
这里对应的结构如下图所示:
我们上面 SystemServer 中的 AMS 已经在 SM 中准备好了,那我们 ServiceManager.getService(Context.ACTIVITY_SERVICE);
一样的过程,我们知道最终会在 service_manager.c 中处理
- switch(txn->code) {
- //这里有个case穿透,,好吧
- case SVC_MGR_GET_SERVICE:
- case SVC_MGR_CHECK_SERVICE:
- s = bio_get_string16(msg, &len);
- if (s == NULL) {
- return -1;
- }
- //查询AMS保存在SM中对应的的那个handle
- handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
- if (!handle)
- break;
- bio_put_ref(reply, handle);
- return 0;
- }
- 把写入数据后的reply返回
- bio_put_uint32(reply, 0);
回到我们的调用处
[ServiceManagerNative.java]
- public IBinder getService(String name) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IServiceManager.descriptor);
- data.writeString(name);
- mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
- //看这里readStrongBinder,是不是感觉跟我们上面的writeStrongBinder感觉是一对的
- IBinder binder = reply.readStrongBinder();
- reply.recycle();
- data.recycle();
- return binder;
- }
Parcel 的 readStrongBinder 还是个 JNI 调用
[android_ os_Parcel.cpp]
- static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
- {
- Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
- if (parcel != NULL) {
- //这里我们看到了什么,,看函数名字应该是为Binder生成一个java对象吧
- return javaObjectForIBinder(env, parcel->readStrongBinder());
- }
- return NULL;
- }
我们先看 Pacel 的 readStrongBinder 方法
[Parcel.cpp]
- sp<IBinder> Parcel::readStrongBinder() const
- {
- sp<IBinder> val;
- //看到这里,还记得writeStrongBinder中的flatten_binder,这里是unflatten_binder
- unflatten_binder(ProcessState::self(), *this, &val);
- return val;
- }
- status_t unflatten_binder(const sp<ProcessState>& proc,
- const Parcel& in, sp<IBinder>* out)
- {
- const flat_binder_object* flat = in.readObject(false);
- if (flat) {
- switch (flat->type) {
- case BINDER_TYPE_BINDER:
- *out = reinterpret_cast<IBinder*>(flat->cookie);
- return finish_unflatten_binder(NULL, *flat, in);
- case BINDER_TYPE_HANDLE:
- //到这里我们也清楚了进入这个分支
- //调用ProcessState的getStrongProxyForHandle函数
- *out = proc->getStrongProxyForHandle(flat->handle);
- return finish_unflatten_binder(
- static_cast<BpBinder*>(out->get()), *flat, in);
- }
- }
- return BAD_TYPE;
- }
继续跟进 [ProcessState.cpp]
- sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
- {
- sp<IBinder> result;
- AutoMutex _l(mLock);
- handle_entry* e = lookupHandleLocked(handle);
- if (e != NULL) {
- IBinder* b = e->binder;
- if (b == NULL || !e->refs->attemptIncWeak(this)) {
- if (handle == 0) {//这里handle为0的情况是为SM准备的,
- Parcel data;
- status_t status = IPCThreadState::self()->transact(
- 0, IBinder::PING_TRANSACTION, data, NULL, 0);
- if (status == DEAD_OBJECT)
- return NULL;
- }
- //我们的不为0,在这里创建了BpBinder
- b = new BpBinder(handle);
- e->binder = b;
- if (b) e->refs = b->getWeakRefs();
- result = b;
- } else {
- result.force_set(b);
- e->refs->decWeak(this);
- }
- }
- return result;
- }
好了剩下最后一个了 javaObjectForIBinder
[android_ util_Binder.cpp]
- jobject javaObjectForIBinder(JNIEnv * env, const sp < IBinder > &val) {
- if (val == NULL) return NULL;
- //如果val是Binder对象,进入下面分支,此时val是BpBinder
- if (val - >checkSubclass( & gBinderOffsets)) {
- // One of our own!
- jobject object = static_cast < JavaBBinder * >(val.get()) - >object();
- LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
- return object;
- }.........
- //调用BpBinder的findObject函数
- //在Native层的BpBinder中有一个ObjectManager,它用来管理在Native BpBinder上创建的Java BinderProxy对象
- //findObject用于判断gBinderProxyOffsets中,是否存储了已经被ObjectManager管理的Java BinderProxy对象
- jobject object = (jobject) val - >findObject( & gBinderProxyOffsets);
- if (object != NULL) {
- jobject res = jniGetReferent(env, object);............
- //如果该Java BinderProxy已经被管理,则删除这个旧的BinderProxy
- android_atomic_dec( & gNumProxyRefs);
- val - >detachObject( & gBinderProxyOffsets);
- env - >DeleteGlobalRef(object);
- }
- //创建一个新的BinderProxy对象
- object = env - >NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
- if (object != NULL) {
- // The proxy holds a reference to the native object.
- env - >SetLongField(object, gBinderProxyOffsets.mObject, (jlong) val.get());
- val - >incStrong((void * ) javaObjectForIBinder);
- // The native object needs to hold a weak reference back to the
- // proxy, so we can retrieve the same proxy if it is still active.
- jobject refObject = env - >NewGlobalRef(env - >GetObjectField(object, gBinderProxyOffsets.mSelf));
- //新创建的BinderProxy对象注册到BpBinder的ObjectManager中,同时注册一个回收函数proxy_cleanup
- //当BinderProxy对象detach时,proxy_cleanup函数将被调用,以释放一些资源
- val - >attachObject( & gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup);
- // Also remember the death recipients registered on this proxy
- sp < DeathRecipientList > drl = new DeathRecipientList;
- drl - >incStrong((void * ) javaObjectForIBinder);
- //将死亡通知list和BinderProxy联系起来
- env - >SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast < jlong > (drl.get()));
- // Note that a new object reference has been created.
- android_atomic_inc( & gNumProxyRefs);
- //垃圾回收相关;利用gNumRefsCreated记录创建出的BinderProxy数量
- //当创建出的BinderProxy数量大于200时,该函数将利用BinderInternal的ForceGc函数进行一个垃圾回收
- incRefsCreated(env);
- return object;
- }
- }
到这里总算都打通了总体流程如下
还剩下遗留下的两个问题
通过 Java 层的服务端代理最终调用到 BpBinder.transact 函数
[BpBinder.cpp]
- status_t BpBinder:transact(uint32_t code,const Parcel&data,Parcel*reply,uint32_t flags){
- if(mAlive){
- //BpBinder把transact工作交给了IPCThreadState。
- status_t status=IPCThreadState:self()->transact(
- mHandle,code,data,reply,flags);//mHandle也是参数
- if(status==DEAD_OBJECT)mAlive=0;
- return status;
- }
- return DEAD_OBJECT;
- }
[IPCThreadState.cpp]
- IPCThreadState::IPCThreadState()
- : mProcess(ProcessState::self()),
- mMyThreadId(gettid()),
- mStrictModePolicy(0),
- mLastTransactionBinderFlags(0)
- {
- pthread_setspecific(gTLS, this);
- clearCaller();
- //mIn和mOut是两个Parcel。 把它看成是发送和接收命令的缓冲区即可。
- mIn.setDataCapacity(256);
- mOut.setDataCapacity(256);
- }
- status_t IPCThreadState::transact(int32_t handle,
- uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags)
- {
- ......
- /*
- 注意这里的第一个参数BC_TRANSACTION,它是应用程序向binder设备发送消息的消
- 息码,而binder设备向应用程序回复消息的消息码以BR_开头。 消息码的定义在
- binder_module.h中,请求消息码和回应消息码的对应关系,需要查看Binder驱动的实
- 现才能将其理清楚,我们这里暂时用不上。
- */
- err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
- ......
- err = waitForResponse(NULL, NULL);
- ......
- return err;
- }
- status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
- int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
- {
- //binder_transaction_data是和binder设备通信的数据结构。
- binder_transaction_data tr;
- //果然,handle的值传递给了target,用来标识目的端,其中0是ServiceManager的标志。
- tr.target.handle=handle;
- //code是消息码,是用来switch/case的!
- tr.code = code;
- tr.flags = binderFlags;
- tr.cookie = 0;
- tr.sender_pid = 0;
- tr.sender_euid = 0;
- const status_t err = data.errorCheck();
- if (err == NO_ERROR) {
- tr.data_size = data.ipcDataSize();
- tr.data.ptr.buffer = data.ipcData();
- tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
- tr.data.ptr.offsets = data.ipcObjects();
- } 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中,而不是直接发出去,可见这个函数有点名不副实。
- mOut.writeInt32(cmd);
- mOut.write(&tr, sizeof(tr));
- return NO_ERROR;
- }
- 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;
- //看见没?这里开始操作mIn了,看来talkWithDriver中
- //把mOut发出去,然后从driver中读到数据放到mIn中了。
- cmd = mIn.readInt32();
- }
- }
- status_t IPCThreadState::talkWithDriver(bool doReceive)
- {
- binder_write_read bwr;
- //中间东西太复杂了,不就是把mOut数据和mIn接收数据的处理后赋值给bwr吗?
- status_t err;
- do {
- //用ioctl来读写
- if (ioctl(mProcess->mDriverFD,BINDER_WRITE_READ, &bwr) >= 0)
- err = NO_ERROR;
- else
- err = -errno;
- } while (err == -EINTR);
- //到这里,回复数据就在bwr中了,bmr接收回复数据的buffer就是mIn提供的
- if (bwr.read_consumed > 0) {
- mIn.setDataSize(bwr.read_consumed);
- mIn.setDataPosition(0);
- }
- returnNO_ERROR;
- }
我们本篇详细分析了 Binder 机制,从概述 ->Java 层 Binder->Native 层 Binder->Binder 驱动,位于各层次的读者都能获得收获。
不好意思各位,下周有个比较重要的面试,所以暂时不会更新该系列的博客,但是也会更新其他博客。记录准备面试的过程中需要用到的比较容易错误的知识。
此致,敬礼
来源: http://www.cnblogs.com/wangle12138/p/8087709.html