Binder:为什么要通过onTransact()调用目标方法

0x00 背景

最近被提出一串问题:为什么android.os.Binder要提供onTransact()方法给子类重写。为什么要通过Client:invokeMethod -> onTransact() -> Service:targetMethod这一曲折过程来调用一个远程方法,为什么不能直接指定方法名称来调用。

这些问题阐述了同一个疑问:对于调用者而言,目标方法为何远在天边。

实际上,这并不是一个无关紧要的问题。尝试解答此问题有助于了解API设计者的初衷,以便从不同角度探究可能潜在的问题。了解系统创作者的思想,从而更好地使用其设计的接口及系统特性,避免出现错误决策导致长期迭代中难以维护。

本文假设你已具备IPC(进程间通信)开发经验。

0x01 AIDL 与 onTransact()

做一些简单回顾:

首选,无论定义于何处,.aidl文件始终是生成目标.java文件的声明标记。大多数情况下,对android.os.IInterfaceandroid.os.Binder的继承及实现不应当手动操作。所有的生成行为应当由.aidl声明来完成。此外,所生成的目标文件位于app/build/generated/source目录下。

其次,android.os.Binder实现于android.os.IBinderandroid.os.Binder实现了大多数进程状态所必要的功能,以及所有必要的功能调度。

.aidl存在的目的就是为了剔除大量重复性的工作。这其中包括,所生成目标文件下的类种类Stub方法:onTransact(int, android.os.Parcel, android.os.Parcel, int)。此方法重写自android.os.Binder。此外,.aidl是为对外暴露接口而设计的。

0x02 onTransact() 干了些什么

Binder.onTransact()是为Binder.transact()的调用而准备的。Binder.transact()做了两件事:

public final boolean transact(int code, Parcel data, Parcel reply,
        int flags) throws RemoteException {
    if (data != null) {
        data.setDataPosition(0);
    }
    boolean r = onTransact(code, data, reply, flags);
    if (reply != null) {
        reply.setDataPosition(0);
    }
    return r;
}

此段代码位于android/os/Binder.java

首先,在调用Binder.onTransact()之前及之后,分别对请求结构的引用及返回结构的引用重置读写position,以及调用Binder.onTransact()。在此提醒,Binder.transact()的调用者是Stub下的内部类Proxy中的各个.aidl中定义的方法。

最终,千辛万苦地,终于来到了.aidl自行生成实现的Binder.onTransact()方法了。特别的是,有两个地方值得去注意:

  • 其一,在最终的开发中,将会继承抽象类Stub,并实现所有在.aidl中定义的方法。这些具体方法的直接调用者,正是当前我们所在的onTransact()方法;

  • 其二,正是基于上面一条,可以得知:无论远程调用者(Client)身处何方,最终,一定会经过此处的onTransact()方法,并由onTransact()直接调用目标方法。

要知道,传入onTransact()方法的参数中,拥有目标方法的ID、指向参数的引用,以及指向返回结果的引用。所有远程调用者(Client)想要做的事,都通过层层调用及参数包装汇聚到onTransact(),再由onTransact()分发到真正的目标方法执行。

那么问题来了。为什么?

0x03 关键问题:进程隔离

一个简洁明了的回答是:除了预先定义的接口,其余的一切实现在进程间均相互不可见。

现在,以更直观的方式来展示调用者(Client)与服务(Service)间的关系:

上下层关系

显然,所有的Client亦或是Service,都是平级的。原因显而易见:这部分运行时程序,都是基于Android Framework开发的。

那么,如果A程序自行定义了接口,B程序怎样知道A程序定义了接口?换言之:B程序该通过什么方式来查找A程序中的自定义接口以至调用?显然,所有基于Android Framework开发的程序,都不存在上下级关系。

同时,由于虚拟机相互独立,因此这些程序并不在同一个运行时中。两两之间相隔一堵不透明的墙,它们唯一可见的,就是下层的Binder元素。

答案就此基本浮出水面。Client与Service的状态是不可预知的,使用Binder Driver隐藏进程间调用细节,并通过Binder.onTransact()分发调用指令,最终在参数引用中写入计算结果——这一过程实现了设计模式中的简易命令模式。整个进程间调用作用于Binder Driver,至于Binder.onTransact()格外引人瞩目,则是因为它是整个过程的末端操作。

正如上图所示,把所有请求汇聚到onTransact(),具体需要请求哪个方法,则抽象为id处理。另外,所有目标方法的请求参数及返回体都要求是基本类型或被.aidl所定义的。这意味着在传输过程中所有信息都被视作“流”来处理。

0x04 更多思考

理解Binder调度过程有助于设计更易于维护的接口——尤其是库。某些需求的实现可能需要对ProxyStub进行手动编辑,此时理解API设计者的意图显得极为重要。

毕竟,维护那些凭直觉写出的代码,简直就是灾难。

内推

现在,欢聚时代(YY Inc.)及虎牙(HUYA Inc.)所有岗位(包括但不限于 Android、iOS、Java、前端、大数据、机器学习、音视频算法、其他非技术岗均可)均可进行内部推荐。

发送简历到 zhujiajun#yy.com(#替换成@),并附上简历,即可内推。

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

推荐阅读更多精彩内容

  • 原文链接: http://weishu.me/2016/01/12/binder-index-for-newer/...
    miniminiming阅读 719评论 1 6
  • 本笔记整理自: https://www.gitbook.com/book/tom510230/android_...
    01_小小鱼_01阅读 982评论 0 4
  • Binder浅析 1. 背景知识 Binder在Android系统中是用来进行进程间通信的,所以在介绍Binder...
    蕉下孤客阅读 2,277评论 0 8
  • 一、IPC简介 (1)IPC是Inter-Process Communication的缩写,含义为进程间通信或者跨...
    遥遥的远方阅读 7,172评论 0 3
  • 好想把生活过的浪漫有情调,有诗、有远方;可是现实是我要养家糊口。所以把生活过成了这样:该上班的时候上班,兢兢业业,...
    Shelley1165阅读 160评论 1 0