Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索》以及《深入理解Android 卷Ⅰ,Ⅱ,Ⅲ》中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!!另外,本系列文章知识可能需要有一定Android开发基础和项目经验的同学才能更好理解,也就是说该系列文章面向的是Android中高级开发工程师。
前言
我们在上一篇中比较详尽的介绍了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为进程创建的一个特殊地址范围,它将出现在该进程的地址空间中。其他进程可以将同一段共享内存连接到自己的地址空间中。所有进程都可以访问共享内存中的地址,如果一个进程向共享内存中写入了数据,所做的改动将立刻被其他进程看到。
- 共享内存是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层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,那么接着第二点
是否存在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;
}
}
到这里总算都打通了总体流程如下
驱动层Binder
AMS代理是如何与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驱动,位于各层次的读者都能获得收获。
下篇预告
不好意思各位,下周有个比较重要的面试,所以暂时不会更新该系列的博客,但是也会更新其他博客。记录准备面试的过程中需要用到的比较容易错误的知识。
此致,敬礼