作者:wangle12138 链接:http://www.cnblogs.com/wangle12138/p/8087709.html 声明:本文是 wangle12138 原创投稿,转发等请联系原作者授权。
前言我们在上一篇中比较详尽的介绍了 Android 的消息机制,不过有一些内容我们在不理解Android Binder 的话是无法讲解清楚的。对于初学 Android 的朋友而言,最难却又最想掌握的恐怕就是 Binder 机制了,因为 Android 系统基本上可以看作是一个基于 Binder 通信的 C/S 架构。 Binder 就像网络一样,把系统的各个部分连接在了一起,因此它是非常重要的。我们下面会 Android Binder 机制进行从上到下从易到难的分层次讲解,从而既能让初学者对 Binder 有一定认识,也能让有一定Android基础的人获得收获。 注:下文中的源码均出自android-6.0.0_r5 Binder概述对于初学者来说,深入 Android Binder 机制是非常不明智的。Android Binder机制大都涉及Java层、Native层、驱动层这三三个方面,对于初学者来说想啃这三块硬骨头很容易磕着牙。我们这这一节概述从以下几个方面让你从比较宏观的角度理解Android Binder。 进程在该系列博客中的第一章我们就说起了Android进程相关问题,Android故意弱化了进程的概念,而用相对容易理解的四大组件。可是我们在稍微深入Android的时候,那么进程是绕不过的。默认情况下,同一个应用程序中的所有组件运行在同一个进程中,而且绝大多数的应用程序也都是这样的。这个默认进程是用这个应用的包名来命名的。 进程间通信我们在运行App的时候经常需要使用一些系统服务,比如剪切板服务,而剪切板服务是运行在SystemServer进程中的。那我们的App是怎么使用剪切板服务的呢,我们都知道进程是相互独立的,静态变量等等都无法共用。这就涉及到进程间的通信了,即IPC。我们都知道Android是基于Linux内核的,那我们简单介绍下Linux下的几种IPC机制。 管道(Pipe)管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。比如fork或exec创建的新进程,在使用exec创建新进程时,需要将管道的文件描述符作为参数传递给exec创建的新进程。当父进程与使用fork创建的子进程直接通信时,发送数据的进程关闭读端,接受数据的进程关闭写端。 管道只能在本地计算机中使用,而不可用于网络间的通信。
命名管道(FIFO)命名管道是一种特殊类型的文件,它在系统中以文件形式存在。这样克服了管道的弊端,他可以允许没有亲缘关系的进程间通信。 共享内存(Share Memory)共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到自己的地址空间中。所有进程都可以访问共享内存中的地址,如果一个进程向共享内存中写入了数据,所做的改动将立刻被其他进程看到。 内存映射(Memory Map)内存映射是由一个文件到一块内存的映射,在此之后进程操作文件,就像操作进程空间里的内存地址一样了。 套接字(Socket)套接字机制不但可以单机的不同进程通信,而且使得跨网机器间进程可以通信。 套接字的创建和使用与管道是有区别的,套接字明确地将客户端与服务器区分开来,可以实现多个客户端连到同一服务器。 Binder作为Android系统下的一种IPC机制,其本质上与上面罗列出的IPC机制并无本质上的不同,都是作为进程间通信的一种手段。并且在Android系统中也不是只存在Binder这一种进程间通信的方式,在有些地方也使用了Socket。既然Linux已经提供了众多IPC机制,那么Android 为何还要使用Binder作为主要的进程间通信的方式呢,那么当然有他的优点存在。 采用C/S的通信模式。而在linux通信机制中,目前只有socket支持C/S的通信模式,但socket有其劣势,具体参看第二条。 有更好的传输性能。对比于Linux的通信机制,socket:是一个通用接口,导致其传输效率低,开销大;管道和消息队列:因为采用存储转发方式,所以至少需要拷贝2次数据,效率低;共享内存:虽然在传输时没有拷贝数据,但其控制机制复杂(比如跨进程通信时,需获取对方进程的pid,得多种机制协同操作)。 安全性更高。Linux的IPC机制在本身的实现中,并没有安全措施,得依赖上层协议来进行安全控制。而Binder机制的UID/PID是由Binder机制本身在内核空间添加身份标识,安全性高;并且Binder可以建立私有通道,这是linux的通信机制所无法实现的(Linux访问的接入点是开放的)。 对用户来说,通过binder屏蔽了client的调用server的隔阂,client端函数的名字、参数和返回值和server的方法一模一样,对用户来说犹如就在本地(也可以做得不一样),这样的体验或许其他ipc方式也可以实现,但binder出生那天就是为此而生。
Java层BinderJava层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,那么接着第二点 是否存在Server端服务代理?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; } ...... }
是否存在Server端服务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层进军。 Native层Binder我们依然以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,很容易陷入思维混乱。 AMS是如何注册的?我们SystemServer进程中的AMS通过SM的代理与SM进程交互(读者也可以把这个过程想象为你所能理解的进程间通信方式,例如管道、Socket等),并把自己注册在SM中 SystemServer创建出ActivityManagerService后,最终将调用其setSystemProcess方法: [SystemServer.java] public void setSystemProcess() { try { //注册服务,第二个参数为this,这里假设SystemServer通过“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对象。 这里对应的结构如下图所示: AMS代理是如何获得的?我们上面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; } }
到这里总算都打通了总体流程如下 驱动层BinderAMS代理是如何与Binder通信的?通过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); } return NO_ERROR; }
本篇总结我们本篇详细分析了Binder机制,从概述->Java层Binder->Native层Binder->Binder驱动,位于各层次的读者都能获得收获。
下篇预告不好意思各位,下周有个比较重要的面试,所以暂时不会更新该系列的博客,但是也会更新其他博客。记录准备面试的过程中需要用到的比较容易错误的知识。
此致,敬礼
|