Binder系列7—framework层分析

一、概述

1.1 Binder架构

binder在framework层,采用JNI技术来调用native(C/C++)层的binder架构,从而为上层应用程序提供服务。 看过binder系列之前的文章,我们知道native层中,binder是C/S架构,分为Bn端(Server)和Bp端(Client)。对于java层在命名与架构上非常相近,同样实现了一套IPC通信架构。


图解:

图中红色代表整个framework层 binder架构相关组件;

Binder类代表Server端,BinderProxy类代码Client端;

图中蓝色代表Native层Binder架构相关组件;

上层framework层的Binder逻辑是建立在Native层架构基础之上的,核心逻辑都是交予Native层方法来处理。

framework层的ServiceManager类与Native层的功能并不完全对应,framework层的ServiceManager类的实现最终是通过BinderProxy传递给Native层来完成的,后面会详细说明。

1.2 Binder类图

下面列举framework的binder类关系图


图解:(图中浅蓝色都是Interface,其余都是Class)

ServiceManager:通过getIServiceManager方法获取的是ServiceManagerProxy对象; ServiceManager的addService, getService实际工作都交由ServiceManagerProxy的相应方法来处理;

ServiceManagerProxy:其成员变量mRemote指向BinderProxy对象,ServiceManagerProxy的addService, getService方法最终是交由mRemote来完成。

ServiceManagerNative:其方法asInterface()返回的是ServiceManagerProxy对象,ServiceManager便是借助ServiceManagerNative类来找到ServiceManagerProxy;

Binder:其成员变量mObject和方法execTransact()用于native方法

BinderInternal:内部有一个GcWatcher类,用于处理和调试与Binder相关的垃圾回收。

IBinder:接口中常量FLAG_ONEWAY:客户端利用binder跟服务端通信是阻塞式的,但如果设置了FLAG_ONEWAY,这成为非阻塞的调用方式,客户端能立即返回,服务端采用回调方式来通知客户端完成情况。另外IBinder接口有一个内部接口DeathDecipient(死亡通告)。

1.3 Binder类分层

整个Binder从kernel至,native,JNI,Framework层所涉及的全部类


二、初始化

在Android系统开机过程中,Zygote启动时会有一个虚拟机注册过程,该过程调用AndroidRuntime::startReg方法来完成jni方法的注册。

2.1 startReg

==> AndroidRuntime.cpp


注册JNI方法,其中gRegJNI是一个数组,记录所有需要注册的jni方法,其中有一项便是REG_JNI(register_android_os_Binder),下面说说register_android_os_Binder过程。

2.2 register_android_os_Binder

==> android_util_Binder.cpp


2.3 注册Binder

==> android_util_Binder.cpp


注册 Binder类的jni方法,其中:

FindClassOrDie(env, kBinderPathName) 基本等价于 env->FindClass(kBinderPathName)

MakeGlobalRefOrDie() 等价于 env->NewGlobalRef()

GetMethodIDOrDie() 等价于 env->GetMethodID()

GetFieldIDOrDie() 等价于 env->GeFieldID()

RegisterMethodsOrDie() 等价于 Android::registerNativeMethods();

(1)gBinderOffsets

gBinderOffsets是全局静态结构体(struct),定义如下:


gBinderOffsets保存了Binder.java类本身以及其成员方法execTransact()和成员属性mObject,这为JNI层访问Java层提供通道。另外通过查询获取Java层 binder信息后保存到gBinderOffsets,而不再需要每次查找binder类信息的方式能大幅度提高效率,是由于每次查询需要花费较多的CPU时间,尤其是频繁访问时,但用额外的结构体来保存这些信息,是以空间换时间的方法。

(2)gBinderMethods


通过RegisterMethodsOrDie(),将为gBinderMethods数组中的方法建立了一一映射关系,从而为Java层访问JNI层提供通道。

总之,int_register_android_os_Binder方法的主要功能:

通过gBinderOffsets,保存Java层Binder类的信息,为JNI层访问Java层提供通道;

通过RegisterMethodsOrDie,将gBinderMethods数组完成映射关系,从而为Java层访问JNI层提供通道。

也就是说该过程建立了Binder类在Native层与framework层之间的相互调用的桥梁。

2.4 注册BinderInternal

==> android_util_Binder.cpp

注册BinderInternal类的jni方法,gBinderInternalOffsets保存了BinderInternal的forceBinderGc()方法。

下面是BinderInternal类的JNI方法注册:

该过程其【2.3】非常类似,也就是说该过程建立了是BinderInternal类在Native层与framework层之间的相互调用的桥梁。

2.5 注册BinderProxy

==> android_util_Binder.cpp

注册BinderProxy类的jni方法,gBinderProxyOffsets保存了BinderProxy的构造方法,sendDeathNotice(), mObject, mSelf, mOrgue信息。

下面BinderProxy类的JNI方法注册

该过程其【2.3】非常类似,也就是说该过程建立了是BinderProxy类在Native层与framework层之间的相互调用的桥梁。

三、注册服务

3.1 SM.addService

[-> ServiceManager.java]


先来看看getIServiceManager()过程,如下:

3.2 getIServiceManager

[-> ServiceManager.java]


采用了单例模式获取ServiceManager getIServiceManager()返回的是ServiceManagerProxy(简称SMP)对象

3.2.1 getContextObject()

[-> android_util_binder.cpp]


BinderInternal.java中有一个native方法getContextObject(),JNI调用执行上述方法。

对于ProcessState::self()->getContextObject(),在获取ServiceManager的第3节已详细解决,即ProcessState::self()->getContextObject()等价于 new BpBinder(0);

3.2.2 javaObjectForIBinder

[-> android_util_binder.cpp]


根据BpBinder(C++)生成BinderProxy(Java)对象. 主要工作是创建BinderProxy对象,并把BpBinder对象地址保存到BinderProxy.mObject成员变量. 到此,可知ServiceManagerNative.asInterface(BinderInternal.getContextObject()) 等价于


3.3 SMN.asInterface

[-> ServiceManagerNative.java]


由此,可知ServiceManagerNative.asInterface(new BinderProxy()) 等价于new ServiceManagerProxy(new BinderProxy()). 为了方便,ServiceManagerProxy简称为SMP。

3.3.1 ServiceManagerProxy初始化

[-> ServiceManagerNative.java ::ServiceManagerProxy]


mRemote为BinderProxy对象,该BinderProxy对象对应于BpBinder(0),其作为binder代理端,指向native层大管家service Manager。

ServiceManager.getIServiceManager最终等价于new ServiceManagerProxy(new BinderProxy()),意味着【3.1】中的getIServiceManager().addService(),等价于SMP.addService().

framework层的ServiceManager的调用实际的工作确实交给SMP的成员变量BinderProxy;而BinderProxy通过jni方式,最终会调用BpBinder对象;可见上层binder架构的核心功能依赖native架构的服务来完成的。

3.4 SMP.addService

[-> ServiceManagerNative.java ::ServiceManagerProxy]

3.5 writeStrongBinder(Java)

[-> Parcel.java]


3.5.1 android_os_Parcel_writeStrongBinder

[-> android_os_Parcel.cpp]

3.5.2 ibinderForJavaObject

[-> android_util_Binder.cpp]


根据Binde(Java)生成JavaBBinderHolder(C++)对象. 主要工作是创建JavaBBinderHolder对象,并把JavaBBinderHolder对象地址保存到Binder.mObject成员变量.

3.5.3 JavaBBinderHolder.get()

[-> android_util_Binder.cpp]


JavaBBinderHolder有一个成员变量mBinder,保存当前创建的JavaBBinder对象,这是一个wp类型的,可能会被垃圾回收器给回收,所以每次使用前,都需要先判断是否存在。

3.5.4 JavaBBinder初始化

==> [-> android_util_Binder.cpp]


创建JavaBBinder,该对象继承于BBinder对象。

data.writeStrongBinder(service)最终等价于parcel->writeStrongBinder(new JavaBBinder(env, obj));

3.6 writeStrongBinder(C++)

[-> parcel.cpp]


3.6.1 flatten_binder

[-> parcel.cpp]


将Binder对象扁平化,转换成flat_binder_object对象。

对于Binder实体,则cookie记录Binder实体的指针;

对于Binder代理,则用handle记录Binder代理的句柄;

关于localBinder,代码见Binder.cpp。


3.6.2 finish_flatten_binder


再回到小节3.4的addService过程,则接下来进入transact。

3.7 BinderProxy.transact

[-> Binder.java ::BinderProxy]


回到ServiceManagerProxy.addService,其成员变量mRemote是BinderProxy。transactNative经过jni调用,进入下面的方法

3.8 android_os_BinderProxy_transact

[-> android_util_Binder.cpp]


Java层的BinderProxy.transact()最终交由Native层的BpBinder::transact()完成。Native Binder的注册服务(addService)中有详细说明BpBinder执行过程。另外,该方法可抛出RemoteException。

3.9 小结

addService的核心过程:

四、获取服务

4.1 SM.getService

[-> ServiceManager.java]


关于getIServiceManager(),在前面小节3.2已经讲述了,等价于new ServiceManagerProxy(new BinderProxy())。 其中sCache = new HashMap()以hashmap格式缓存已组成的名称。请求获取服务过程中,先从缓存中查询是否存在,如果缓存中不存在的话,再通过binder交互来查询相应的服务。

4.2 SMP.getService

[-> ServiceManagerNative.java ::ServiceManagerProxy]


4.3 BinderProxy.transact

[-> Binder.java]

4.4 android_os_BinderProxy_transact

[-> android_util_Binder.cpp]


0

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容