Android在Native层实现了进程间的Binder通信,但是上层应用程序的开发及Framework的实现都是Java,用Java层再实现一次肯定是不合理的,Java可以通过JNI调用Native Code,所以通过JNI复用Binder在Native层的实现就是一个顺理成章的事情。

注册Service

在Init进程的init2阶段,系统启动了ServerThread,在ServerThread中会启动很多用Java实现的系统服务,比如说PowerService:

power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);

新建Server端实体,然后向ServiceManager注册,从代码表面看是和Native层Binder一样的。PowerManagerService继承自Java层的Binder类:

public final class PowerManagerService extends IPowerManager.Stub
public interface IPowerManager extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements android.os.IPowerManager {

所以在new PowerManagerService时会调用Binder的构造函数,Binder的构造函数中调用了init(),init是native方法,执行JNI的android_os_Binder_init:

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder();
if (jbh == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return;
}
ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
jbh->incStrong((void*)android_os_Binder_init);
env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
}

在android_os_Binder_init,新建了一个JavaBBinderHolder对角,并将其指针保存在了obj即Binder的gBinderOffsets.mObject域中,而gBinderOffsets.mObject又是个什么东西?看一下它的定义:

static struct bindernative_offsets_t
{
jclass mClass;
jmethodID mExecTransact;
jfieldID mObject;
} gBinderOffsets;

在AndroidRuntine::startReg中会调用register_android_os_Binder,register_android_os_Binder会调用int_register_android_os_Binder等函数建立Java层Binder、BinderProxy、BinderInternal、Log等与Native层的映射关系。比如在int_register_android_os_Binder中会通过JNI标准的方法GetMethodID等初始化gBinderOffsets:

static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz; clazz = env->FindClass(kBinderPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderOffsets.mExecTransact
= env->GetMethodID(clazz, "execTransact", "(IIII)Z");
assert(gBinderOffsets.mExecTransact); gBinderOffsets.mObject
= env->GetFieldID(clazz, "mObject", "I");
assert(gBinderOffsets.mObject); return AndroidRuntime::registerNativeMethods(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}

在android_os_Binder_init中new了一个JavaBBinderHolder,JavaBBinderHolder new了一个JavaBBinder保存到了自己的成员wp<JavaBBinder> mBinder中。

JavaBBinder继承自Native层的BBinder,并且将Java层的Binder对象(此处即PowerManagerService)保存到了成员mObject中,并通过object()方法返回。

现在我们发现,JavaBinder,BinderBBinderHolder,JavaBBinder存在相互引用关系:

  • PowerManagerService.mObject->JavaBBinderHolder
  • JavaBBinderHolder.mBinder->JavaBBinder
  • JavaBBinder.mObject->PowerManagerService

Binder是一种Client-Server类型的IPC,PowerManagerService属于Server端,从Native Binder中我们知道,Client通过BpBinder经由Binder Driver、BBinder与Serverr通信,PowerManagerService通过JavaBBinderHolder引用JavaBBinder,而JavaBBinder继承自BBinder,符合了Server的条件,Server实体有了,接下来就要向ServiceManager注册,通过以下方法:

ServiceManager.addService(Context.POWER_SERVICE,power);
// In ServiceManager
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
} private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}

BinderInternal.getContextObject是一个Native方法,调用JNIandroid_os_BinderInternal_getContextObject:

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}

ProcessState::self()->getContextObject就很熟悉了,在Binder in Native中可以知道,这个调用返回new BpBinder(0)。

javaObjectForIBinder的作用就是,新建一个Java层的BinderProxy对象,将Native层的BpBinder保存到BinderProxy.mObject,并将BinderProxy的弱引用通过attachObject保存到Native层的BpBinder(成员mObjects中),这样Java层的BinderProxy与Native层的BpBinder就可以相互引用了。Java层的BinderProxy及其在Native层的表示间的映射关系同Binder类一样也是在register_android_os_Binder中建立的。

上面红色的部分就等效于:

gServiceManager = ServiceManagerNative.asInterface(new BinderProxy());

ServiceManagerNative继承自IServiceManager与Java层的Binder类,BinderProxy可以引用BpBinder。asInterface就像Native Binder中的interface_cast的,asInterface实现可以简化为:

return new ServiceManagerProxy(obj);

obj是BinderProxy对象。ServiceManagerProxy直接将这个BinderProxy对象保存在了成员mRemote中,并通过asBinder返回。

ServiceManagerProxy同时实现了IServiceManager,而且由其名字可知,ServiceManagerProxy是作为ServiceManager在Client端的代理的,看下它的addService的实现:

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);
data.writeStrongBinder(service);
data.writeInt(allowIsolated ? 1 : 0);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, );
reply.recycle();
data.recycle();
}

writeStrongBinder是Native方法,调用android_os_Parcel_writeStrongBinder,在android_os_Parcel_writeStrongBinder将Java Parcel转换成Native Parcel(Native Parcel的指针保存在Java Parcel的成员变量中),然后调用以下语句:

const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));

sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)根据obj返回JavaBBinder或Native BpBinder,在这里传入的obj 是PowerManagerService,返回JavaBBinder。接下来调用了mRemote.transact,mRemote是BinderProxy的对象。

BinderProxy的transact是Native方法,调用JNIandroid_os_BinderProxy_transact,在android_os_BinderProxy_transact中通过:

IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject);
...
status_t err = target->transact(code, *data, reply, flags);

获取到BinderProxy中保存的BpBinder,然后调用BpBinder的transact,到这里就和Native Binder的调用流程一样了,Native ServiceManager会注册我们的Service,在这里是PowerManagerService。

获得注册的Service

Service已经向ServiceManager注册了,那么我们怎么获得所注册的Service,或者更准确地说,怎么获得所注册的Service的代理呢?

回想下我们在APK中是怎么获取系统服务的:

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

看一下getSystemService的实现,位于ContextImpl中:

    @Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
} registerService(POWER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});

1. ServiceManager.getService获得IBinder对象

同ServiceManager.addService一样,ServiceManager.getService首先获得一个ServiceManagerProxy的对象,然后调用它的getService方法:

    public IBinder getService(String name) throws RemoteException {
...
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder();
...
return binder;
}

mRemote是BinderProxy对象,内部引用了BpBinder,调用BinderProxy的Native方法transact与Binder通信,然后通过readStrongBinder()读取返回的数据,一个IBinder对象。

readStrongBinder中通过javaObjectForIBinder返回了BinderProxy对象,前面已经说过。

2. 通过asInterface将获得的IBinder对象转换成IPowerManager对象

IPowerManager.Stub.asInterface可以简化为:

return new android.os.IPowerManager.Stub.Proxy(obj);

Proxy只是将传入的参数(BinderProxy)保存到了成员mRemote中并通过asBinder返回。

Proxy与Stub都是IPowerManager.aidl编译后生成的类,都位于IPowerManager.java中。关于aidl网上有很多资料。

3. IPowerManager对象是不向外暴露的,构造一个PowerManager封装IPowerManager返回。

PowerManager只是将IPowerManager保存在了成员变量中,PowerManager中保存了BinderProxy,BinderProxy中引用了Native BpBinder,就可以与Server进行通信了。

Server端响应Client请求

Server端接收到Client的请求后会调用BBinder的transact处理请求,transact会调用虚函数onTransact,JavaBBinder继承自BBinder,所以会调用JavaBBinder::onTransact,在JavaBBinder::onTransact中有以下一句:

jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, (int32_t)&data, (int32_t)reply, flags);

通过JNI反向调用了Java类的方法。前面我们知道了,Java实现的Service中,Service对象,JavaBBinderHolder,JavaBBinder存在相互引用关系,JavaBBinder的成员mObject引用了Java中的Service对象,比如此处的PowerManagerService,而且在int_register_android_os_Binder中通过

gBinderOffsets.mExecTransact  = env->GetMethodID(clazz, "execTransact", "(IIII)Z");

将Service的execTransact方法(其实是Binder的方法)保存在了gBinderOffsets.mExecTransact中,所在以JavaBBinder::onTransact中会调用Binder.execTransact。在Binder.execTransact中调用了onTransact,执行子类即Stub类的onTransact方法,在onTransact中根据code值执行相应的方法,最终是调用Service类(继承自Stub)中相应的方法。

总结

Java层通过JNI利用了Native层的Binder,在JNI函数注册时会建立Java层Binder,BinderProxy,BinderInternal等类与Native层的映射关系。Java层Service实体继承自Java层的Binder类,在Binder类初始化时会创建一个JavaBBinderHolder作为JavaBBinder的容器,JavaBBinder继承自BBinder,Java层Binder类引用JavaBBinderHolder,JavaBBinderHolder引用JavaBBinder,JavaBBinder继承自BBinder并引用Java层的Binder类,这三者互相引用,这样Java层的Service实体就可以通过BBinder与驱动进行通信了。

进程向Java层的ServiceManager代理发送GET_SERVICE请求,然后通过JNI向Native层的ServiceManager请求服务,Native层的ServiceManager返回请求的服务的代理对象BpBinder,通过javaObjectForIBinder函数将Native的BpBinder转化为Java层对应的BinderProxy,然后通过aidl生成的Stub类asInterface方法将BinderProxy封闭到请求的服务的代理对象中,这个代理对象引用了BinderProxy,BinderProxy内部保存了Native层的BpBinder,这样就可以与驱动进行通信了。

当Server端接收到Client的请求时会通过BBinder的transact调用Server的服务,BBinder的transact调用虚函数onTransact,这样就会调到BBinder的子类JavaBBinder的onTransact,而JavaBinder::onTransact会通过JNI反向调用到Java层Binder类的execTransact,Binder.execTransact调用onTransact即子类Stub的onTransact,然后根据code值调用Service实体类(继承自Stub)相应的方法。

Binder in Java的更多相关文章

  1. Android : 跟我学Binder --- (6) JAVA实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  2. Binder机制,从Java到C (6. Binder in Native : libbinder)

    1.Java和C++中的Binder 从前一篇 Binder机制,从Java到C (5. IBinder对象传递形式) 中可以看到,使用Binder的Java代码,到最后都会进入到Native环境,将 ...

  3. 《深入理解Android 卷III》第二章 深入理解Java Binder和MessageQueue

    <深入理解Android 卷III>即将公布.作者是张大伟.此书填补了深入理解Android Framework卷中的一个主要空白,即Android Framework中和UI相关的部分. ...

  4. Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  5. 图解Android - Binder 和 Service

    在 Zygote启动过程 一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了 ...

  6. Binder Proxy技术方案

    Binder Proxy技术方案 作者 低端码农 时间 2014.08.23 0x0 看到有多朋友尝试通过hook系统进程system_process的ioctl,以企图截获系统的IPC通讯.这个方法 ...

  7. Android : 跟我学Binder --- (5) C++实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  8. Android : 跟我学Binder --- (4) 驱动情景分析

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  9. Android : 跟我学Binder --- (3) C程序示例

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

随机推荐

  1. 前端框架 EasyUI (2)页面布局 Layout

    在 Web 程序中,页面布局对应用程序的用户体验至关重要. 在一般的信息管理类的 Web 应用程序中,页面结构通常有一个主工作区,然后在工作区上下左右靠近边界的区域设置一些边栏,用于显示信息或放置一些 ...

  2. 一看就懂的ReactJs入门教程-精华版

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...

  3. SQL Server内存遭遇操作系统进程压榨案例

    场景: 最近一台DB服务器偶尔出现CPU报警,我的邮件报警阈(请读yù)值设置的是15%,开始时没当回事,以为是有什么统计类的查询,后来越来越频繁. 探索: 我决定来查一下,究竟是什么在作怪,我排查的 ...

  4. ABP文档 - SignalR 集成

    文档目录 本节内容: 简介 安装 服务端 客户端 连接确立 内置功能 通知 在线客户端 帕斯卡 vs 骆峰式 你的SignalR代码 简介 使用Abp.Web.SignalR nuget包,使基于应用 ...

  5. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  6. Node.js:path、url、querystring模块

    Path模块 该模块提供了对文件或目录路径处理的方法,使用require('path')引用. 1.获取文件路径最后部分basename 使用basename(path[,ext])方法来获取路径的最 ...

  7. [原] Cgroup CPU, Blkio 测试

    关于Cgroup的简单测试 [toc] 简单介绍Cgroup (如果对cgroup熟悉可以忽略) 一般情况下,cgroup挂载到一个虚拟文件目录,然后可以通过文件系统的API对其操作. ># m ...

  8. 小兔Java教程 - 三分钟学会Java文件上传

    今天群里正好有人问起了Java文件上传的事情,本来这是Java里面的知识点,而我目前最主要的精力还是放在了JS的部分.不过反正也不麻烦,我就专门开一贴来聊聊Java文件上传的基本实现方法吧. 话不多说 ...

  9. 【夯实Nginx基础】Nginx工作原理和优化、漏洞

    本文地址 原文地址 本文提纲: 1.  Nginx的模块与工作原理    2.  Nginx的进程模型    3 . NginxFastCGI运行原理        3.1 什么是 FastCGI   ...

  10. MyBatis源码分析(二)语句处理器

    StatementHandler 语句处理器,主要负责语句的创建.参数的设置.语句的执行.不负责结果集的处理. Statement prepare(Connection connection, Int ...