昨天 Android 界有个大新闻,就是 AOSP 不再开源了。本来昨天就打算写点东西,奈何一直没抽出时间。一个晚上过去了,现在这事儿越传越那啥,我有点看不下去了。
首先上结论,"AOSP 不再开源",这是一条彻头彻尾的 Fake News。昨天这事儿,国内的媒体,所有说 Android 停止开源的,有一天算一个,非蠢即坏,建议大家都可以取关。
事情是怎么传出来的
这个事情最开始出来,是在一个叫 androidauthority 的网站,有个叫 Mishaal Rahman 的发布的。这个网站集合了大量 Android 的一手变化,有很多作者在上面写文章,有点类似国内的公众号,或者更像少数派。
关心 Android 生态的同学,对于 Mishaal Rahman 这个人应该不陌生。
这哥们儿应该算是 Android 的死忠粉 + 技术型调查记者,常年跟踪 Android 的各类变化,更是 AOSP 的一手体验者。每次 Android 最新的 Beta 出来,他总能第一时间挖出各种最新功能,写出来体验文章。另外,这哥们儿也是懂技术的,每天都会在 AOSP 捡 Google 的提交看,然后分析 Google 内部最近在对 Android 干嘛,有时候甚至直接反编译镜像或者扒代码,然后写文章说 Android 接下来估计准备干嘛干嘛。
然后呢,就是昨天这哥们儿写了篇文章,确认了 AOSP 后续将转变称为内部开发,定期释放代码的开发模式,目的是为了简化流程,不阻碍外部开发者。
这哥们儿的消息是怎么来的?又是扒代码扒出来的?或者认识 Google 内部的人?我们不得而知,但有一点可以肯定,就是这瓜肯定是保熟的。
消息一出不得了,国内好多媒体立刻上头,直达颅内,直至高潮。爱范儿上来更是直接一个大新闻《独家 | Google 决定终止开源 Android》。
估计这事儿在内网外网发酵都挺厉害,Mishaal 本人也意识到了其中的误导性,到了晚些的时候,他也赶紧发了一条动态澄清这个事:
所以看到这里,大家至少应该明白所谓的"不再开源",究竟是怎么一回事儿了吧?
AOSP 究竟是怎么开源的
熟悉我,或者过去看过我文章的同学应该都知道,在过去的3年里,由于工作需要再加上个人爱好,我经常给 AOSP 和 androidx 提交代码。这些经历,使我对 AOSP 的贡献、释放流程从一开始的模糊变得逐渐清晰。搞多了之后,甚至慢慢是能从 AOSP 的分支设置、代码 review 流程中,简单窥见到 Google 内部的开发流程。接下来我会简单给大家做一个分享。
你以为的开源
我相信大部分人,包括我自己在内,最开始知道 Android 是个开源系统的时候,肯定都觉得,Google 是在某个地方,比如 Github,把 Android 的代码全部托管在上面,大家一起在上面缝缝补补,愉快地玩耍。然后每次到了一个里程碑的时候,官方就打一个 tag,编一个大版本,然后发布。
开源的乐趣在于,如果这期间你有幸给它打了提交,那么只需要开开心心等到下次里程碑发布,你的提交就可以跑到全球的 Android 用户手上了。
Github 上有数不清的开源项目,大家似乎都是这么玩的。
真实的 AOSP 开源
然而事实上,Google 不是这么做的。
Android 的开源代码,Google 一直托管在自家的 Gerrit 平台,并且为每个 repo 建立了一个 main
分支。
你以为这个分支就是主要分支了吗?错❌。这个分支仅仅是外部的主要分支,在 Google 内部,他们还有一个自己的 internal-main
,这个分支比 AOSP 的 main
要领先很多,Google 往往会在每隔几个月的 Feature Drop 之后,把 internal-main
整体 merge 到 main
。
那么问题来了,看起来现在有2个 main
分支,那 Google 是以哪边为主,又是怎么来处理冲突的呢?
这个时候就要提到 Google 一直践行的 Presubmit-Verify 机制。
给 AOSP 提交过代码的同学,应该对 Gerrit 上的 Presubmit-Verified 不陌生,这是代码能够被合入的强指标之一,只有达到 +2 了,代码才能被合入。
那么,谁来给这个指标 +2 呢?答案是 Google 的 CI。
每当我们给 AOSP 新增了一个变更(以下简称 CL
(Change Line)),我们需要先加对应的 Googler 来 review。Googler 如果觉得你的提交没太大问题,会给你置一个 Presubmit-Ready +1 。
这个 Presubmit-Ready
只有 Googler 手上有,外部开发者是没办法置的。很多外部开发者给 AOSP 提交一般都直接卡在了这一步,因为如果你没有找到合适的 Googler,又或者 Googler 没有留意到,那么你的 CL 往往就这么飘着没有后续了。
Presubmit-Ready
是 Gerrit 的一个触发器,一旦被触发,CI 就会过来挑选你这条提交,开始跑集成测试。而根据我过去的经验,这个集成测试会做以下几件事:
首先,你的提交会被 Cherry-Pick 到 internal-main
,来验证有没有合入冲突。如果有冲突,你的 CL 会被直接 Presubmit-Verified -1,我曾经有一笔提交就是这样。
这个时候,如果你添加的 Googler 足够热心,他们往往会登进内部系统,看看究竟是哪里冲突了,然后告诉你让你修改。然而实际上,我在 AOSP 看到过不少提交,这一步跑不过,但又看不到错误日志,也没有 Googler 跟进,老实说这非常打击人的积极性。
接着,你可以修复你的冲突,又或者假使你的提交完全没有合入冲突。此时编译 + 集成测试流程就会被启动。Google 有强大的 GCP 平台,编译也都是分布式的。你的提交会被编译出固件,然后在很多 target 上被启动,速度很快。这些 target 多数按照机型、abi、平台来分布,因为大家都知道 Android 可以跑在很多平台,Google 的 CI 会确保你的提交在每个平台都运行正常。这些验证都是自动化的,这一点确实做得很强。如果你对这些流程感兴趣,可以参考我之前写的文章:
编完 aosp 还在刷机?云安卓了解一下,来试试网页版模拟器吧!
以及 Google 的 atest 套件。
最后,既然是集成测试,结果就肯定有成功或者失败。如果没什么太大问题,大约1-2小时之后,你会看到一个叫 Treehugger 的 bot 来给你的提交置 Presubmit-Verified +2。
相反地,如果你的提交有测试用例没跑过,或者出现了其他幺蛾子,Treehugger 会给你直接 Presubmit-Verified -2
为啥我说是"幺蛾子"?,因为 AOSP 的 CI 隔三岔五会出一些莫名其妙的 Flaky Issue。我相信公司内部有 CI 平台的小伙伴对这种错误一定不陌生,换句话讲就是时好时坏的问题,有时候失败了,一行代码都不改,重新触发一下,又可能编过了。
Google 也一样,Flaky 是软件测试领域一个无法避免,只能降低概率的问题。还记得我前面说的,外部开发者没有 Presubmit-Ready
吗?如果你的 CL
被 Presubmit-Verified -2 又找不到原因,你只能在评论区呼唤 Googler 帮你重新触发一次。比较幸运的是,在过去3年,我遇到的 Googler 都很热心,如果因为 Flaky 问题跑失败了,他们都很乐于帮我重新触发。然而,不得不承认,有时候逛 Gerrit,我也能看到一些 CL
经历一次 Presubmit-Verified -2 之后,就没人再帮它重试,作者在下面叫天天不应,叫地地不灵。
到这里,你以为你的提交就可以被合并了吗?并不是。从 2024 年开始,在获得 Presubmit-Verified +2 之后,对于外部开发者,你的 CL
还必须获得2位 Googler 的批准才能被合并。而在这之前,是只要 Owner 同意了就可以的。这无疑又给外部开发者提交代码增加了一份保(zhang)障(ai)。
至此,如果你的 CL
满足了全部条件,就会被 merged 到 main
分支。
结束了吗?并没有。在你的提交被 merge 之后,CI 会再次赶来,将你的提交捡过去跑一遍整体集成测试,这个测试的产物和结果可以在 ci.android.com 看到。如果一切依然没什么问题,那么过段时间,Google 会把你的提交正式合并到 internal-main
,说白了内部分支一定要是最新的,这也是为了季度性从 internal-main
往 main
合并的时候能够减少冲突。以 Settings 模块为例,你看到的所有 "Merge xxxx into ..." 这种标题的提交,就是拿来干这个的,这种 Merged 类提交在 Gerrit 是看不到的,但是我们可以在 Gitiles 上看到。
Google 这次会怎么做?
截止本章发稿,我留了个心眼跑去 AOSP 官网看了一下,发现这次的更新已经体现了。
只能说,这一变更对于外部开发者,以及一些著名的民间 ROM 团队,影响多少还是有的:
首先,Google 大概率会不再理会 AOSP 的这个 main
分支,转而定期向 android-latest-release
这个 revision 去释放代码。android-latest-release
不是一个具体的分支,只是 repo init
时候可选的一份清单文件,等这份清单能拉到的代码,注定是晚于当前最新版本的(至少一定晚于 Pixel 的系统更新)。
其次,由于这次变更势必会造成 main
分支大幅滞后,而 android-latest-release
也只是定期发布,可预见的将来就是,即使开发者发现了一些问题,提交了 CL,大概率也会跟内部分支起冲突,又或者这个问题内部已经修复了,不再需要你的 CL,这无疑很大程度会打击开发者的积极性和参与度。
需要补充的是,AOSP 其实并不是所有的库都完全是这种模式。对于像内核相关的,又或者一些 apex 类型的模块,比如 packages/modules/Bluetooth 或者 packages/modules/NFC 这类,它们从最开始就是基于 aosp 的 main
来开发和释放的,从目前 Gerrit 的情况来看,这些库暂时还处于活跃提交状态,不清楚是否受此政策影响。
最后,androidx
项目暂时没有受到这个变更的影响,大家依然可以通过 Gerrit 或者 github 仓库向 androidx-main
分支做贡献。(但实际上 androidx-main
也是一个外部分支,androidx
项目也有自己的内部分支)。
而对于那些与 Google 签了合约的手机厂商而言,改变之前和改变之后其实没多大影响。这些厂商因为是签约的 Partner,他们一直就可以在 aosp 定期释放节点前很早就拿到最新代码。很多人总以为 Google 是同步向 aosp 和厂商释放代码的,这是一个经典的误解,同时也让我想起了魔趣 ROM 的前开发者 ZRGNiX 昨天这条动态:
是啊,曾几何时,多少对开源和 Android 抱有憧憬的开发者,渴望参与其中,觉得能让自己的代码跑在数以亿计的 Android 设备上,是一件多么酷的事。而事实上,早在多年前,AOSP 就已经是这种"最后才释放到开源社区"的模式了。
简单来讲,如果以前社区开发者只是最晚拿到代码的话,这次变更之后,相当于"给你的代码也只要你看看,不需要你帮着改"了。
简单猜测原因
好了,文章写到这里,想必大家也都知道究竟发生了什么事了。其实冷静下来,回望 AOSP 过去这几年,再看看 Android 团队的新闻,其实不难猜测出这次背后的原因:
政策上,Google 现在也是 "AI First"。这几年在 Android 上的投入也是越来越少,从大版本更新的亮点越来越少这一点上,其实也能看出端倪。
技术上,Google 这几年为了维护多个分支,保持代码同步、处理冲突,估计也是费了不少劲,随着政策的修改,想必人力上也有变动,带来的无非就是不打算再继续这样维护下去吧。
成本上,大家在公司肯定都知道,Infra 里面,CI、CD 是需要消耗大量人力去维护,以及服务器算力还有空间的。虽然我不愿意相信 Google 这么大公司会很在意 Android 的 CI、CD 消耗的这部分资源,但也许停止接受外部开发者的贡献,确实能降低员工 Code-Review 的成本,更能减少 CI、CD 的服务器消耗?(根据我的观察,一笔 CL 导致的 Presubmit
验证基本都在 2h 左右,甚至更久)也许这也是一种降本增效吧。
最后
从 2008 年开始算,一转眼,Android也算是 17 年了。如今 AI 时代已来,Android 的框架技术层也早已趋于稳定,而应用技术层这么多年来一直都卷得不可开交。早年卷插件化,热修复,现在卷 Compose,跨平台,后面卷什么?谁又能知道呢?时代在不断前进的,Google 一定也在不断调整战略方向。
今年以来,Chet Haase,Romain Guy,这些每年在 I/O 大会都能见到的熟面孔,而且算是创始人级别的大佬,也都离开了 Google,去寻找自己的下一个十年。最近我也时常在想,作为10年 Android 开发的我,下一个十年又会在哪,又该做些什么呢?
我们呢?