要失业了!写在 Android “不再开源”之后

昨天 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 吗?如果你的 CLPresubmit-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-mainmain 合并的时候能够减少冲突。以 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 开发的我,下一个十年又会在哪,又该做些什么呢?

我们呢?

相关推荐
后端码匠1 分钟前
MySQL 8.0安装(压缩包方式)
android·mysql·adb
梓仁沐白1 小时前
Android清单文件
android
董可伦4 小时前
Dinky 安装部署并配置提交 Flink Yarn 任务
android·adb·flink
每次的天空4 小时前
Android学习总结之Glide自定义三级缓存(面试篇)
android·学习·glide
恋猫de小郭4 小时前
如何查看项目是否支持最新 Android 16K Page Size 一文汇总
android·开发语言·javascript·kotlin
LuXi_foryou6 小时前
错误: 程序包org.junit不存在 import org.junit.Test;
junit·android studio
flying robot6 小时前
小结:Android系统架构
android·系统架构
xiaogai_gai6 小时前
有效的聚水潭数据集成到MySQL案例
android·数据库·mysql
鹅鹅鹅呢7 小时前
mysql 登录报错:ERROR 1045(28000):Access denied for user ‘root‘@‘localhost‘ (using password Yes)
android·数据库·mysql
在人间负债^7 小时前
假装自己是个小白 ---- 重新认识MySQL
android·数据库·mysql