关于匿名binder的传输原理总结。

一、缘由

网上有很多关于AIDL原理的讲述,但一直有个疑问是binder为什么在service端是stub,而客户端拿到就变成BinerProxy?网上讲了很多,但一到这个地方就一笔带过,所以决定自己研究下。

二、首先简述下AIDL使用流程

1.创建AIDL文件

AIDL文件会在build下生成java文件。如下:

在service中创建binder,实现stub并在service的onBind()中返回如下:

在另一个进程中绑定

单步调试看下传过来的binder


可以看到客户端是BinderProxy类型。

三、分析service绑定流程寻找stub在何处被转化成了binderProxy

要找到从哪里转化必须分析service绑定流程,

从bindService函数起

ContextWrapper.java中

我们知道是装饰模式,实现在ContextImpl.java中

调用bindServiceCommon函数

可以看到这个ActivityManagerNative.getDefault().bindService,通过代理实际上调用了ActivityManagerService.java的bindService函数

继续bindServiceLocked函数,太长截取关键代码

调用了bringUpServiceLocked函数,继续

调用了realStartServiceLodcked函数


调用了scheduleCreateService和requestServiceBindingsLocked,猜想这两个函数就是创建service和bindservice,成功后肯定回调service的onCreate和onBind。

此处又用到了代理,实际上实现函数在ActivityThread.java中,我关心的是onBind回调,所以直接看scheduleBindService这个函数


又用了个message,继续


终于找到了,通过调用service的onBind函数拿到了Binder,此时binder还是stub类。紧接着通过代理调用了ActivityManagerService的publishService函数,看到binder是直接作为参数传进去的。

参数继续传,继续跟踪

binder没做处理,直接回调了c.conn.connected。在一开始ContextImpl.java的bindServiceCommon函数中做了一些准备工作,就是创建这个回调类。此处调用到了

继续

继续

在doConnected中调用了ServiceConnection类的onServiceConnected函数,就是我们在客户端写的绑定回调。流程结束,不过问题没解决,参数binder始终没变,哪里捣鬼?

从handleBindService拿到binder开始起,此时还是服务端service进程,和ActivityManagerService交互,将binder交给了ActivityManagerService,ActivityManagerService又交给客户端回调onServiceConnected。

刚才分析时遇到ActivityManagerNative.getDefault(),由于也是binder通信,直接找到了实现ActivityManagerService进行分析。

这里有两点:

1.我们写的service和ActivityManagerService通过binder进行传输。

2.传输时的又有一个binder作为参数。这个binder是我们写的service和client通信用的binder。

重新分析下ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder);

在ActivityManagerNative定义了Proxy端操作

Parcel类型,通过writeStrongBinder将binder写入,分析Parcel.java

private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);

调到了jni了,在android_os_Parcel.cpp中

ibinderForJavaObject将binder转化为C++层对应得binder,也就是JavaBBinderHolder,JavaBBinderHolder是个装饰类,里面有JavaBBinder,而JavaBBinder继承BBinder。最后通过Parcel.java中的writeStrongBinder写入到binder驱动中。

writeStrongBinder调用flatten_binder

flatten_binder区分了情况本地binder将type置为BINDER_TYPE_BINDER

我们当然在研究跨进程的binder,所以此处置为BINDER_TYPE_HANDLE,并创建了BpBinder类。BpBinder就是BinderProxy在C++层的对应类。分析到此处大致明白,读取binder的时候肯定是找到BpBinder,进而找到BinderProxy,返回给了ActivityManagerService。

看下怎们读取的

看ActivityManagerService如何拿到传过来的binder,类似

通过readStrongBinder拿到binder,然后调用了publishService()函数给客户端。看jni对应的函数

此处终于明白了,parcel->readStrongBinder()找到BpBinder,javaObjectForIBinder()返回对应的BinderProxy给ActivityManagerService。

如下

之前写的时候置位了,是BINDER_TYPE_HANDLE

在getStrongProxyForHandle中判断BpBinder是否存在,直接找到或创建并返回。

再看javaObjectForIBinder()

通过对应关系找到BinderProxy,如果找不到就创建BinderProxy,并将BinderProxy和BpBinder建立对应关系。gBinderProxyOffsets即jni调用java的BinderProxy类。如下

所以在ActivityManagerService拿到binder的时候,这个binder已经是BinderProxy,后面给到客户端回调onServiceConnected函数。

分析完毕。

四,小结

一开始有这个疑问还是由于对binder的结构了解不深入。总结两点。

(1)Binder分为java层Binder和C++层Binder。Android代码中使用binder的方式很灵活,可以不关心C++层层Binder,直接通过java层Binder封装使用,即本例讨论的AIDL方式。可以在C++直接创建BBbinder和BpBinder来进行通信,比如深入理解android中讲到的MediaServer。当然也可以一侧使用java,另一侧使用C。更直接的可能直接通过ioctl方式直接写入binder驱动都可能。不了解binder的结构就发现各种资料讲解的都不一样,其实只是这几种使用方式的排列组合。只要了解一点,BinderProxy对应BpBinder,Binder对应BBinder的关系就不会错。

(2)系统service都在SystemServer进行注册,系统service的binder都是通过SystemServer查找拿到。SystemServer负责返回给客户端代理对象即BinderProxy。匿名binder,即本例讨论的AIDL,在和ActivityManagerService传输的过程中进行转化。binder作为对象被传输,具体就是通过writeStrongBinder和readStrongBinder。

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

推荐阅读更多精彩内容