后AOSP时代还能贡献代码吗?

一个月前,Android闭源的消息铺天盖地。后来大家弄清楚了,Google只是将Android的开发全都切为内部分支,而代码依旧开源(虽然会滞后)。因此,如果我们现在登录AOSP的网页,将会看到这样的置顶信息:

今天我们就来试一试,在后AOSP时代,还能不能贡献代码?以及该如何贡献代码?

起源

(本章节涉及技术细节,如果不感兴趣可以跳过)

事情的起源是我们内部测试碰到一个非常诡异的问题:一些核心系统进程消失了,init认为它启动成功了,可是进程列表中根本找不到。通过分析dump和加日志的方式,我们找到了问题的根因:Android 15中引入了一个功能,在传统cgroup的树状结构中增加apps和system两个根节点,这样我们对系统进程和普通应用可以执行不同的策略。

因此传统的cgroup目录结构就发生了如下变化:

bash 复制代码
/sys/fs/cgroup/uid_10118/pid_4980
               ↓↓↓
/sys/fs/cgroup/apps/uid_10228/pid_5621
/sys/fs/cgroup/system/uid_1000/pid_1348

虽然这个功能在Android 15中就已引入,但直到Android 16才默认开启。

正常情况下,当App死亡后,system_server会收到通知,然后它会负责清理该App对应的cgroup节点。但如果是系统重启(zygote死亡),system_server是来不及为众多App回收cgroup节点的。因此init在回收zygote时,会执行一个removeAllEmptyProcessGroups的操作,将cgroup系统中那些空节点删除,相当于干了本该system_server干的活。

整个流程没有缺陷,但新引入的功能却忽略了removeAllEmptyProcessGroups。removeAllEmptyProcessGroups依然按照老的cgroup目录结构进行处理,结果就是那些空节点无法删除,会被fork出的新进程继承使用。一旦这些节点的freeze状态为true,就会使得新进程被冻结。这个影响无疑是灾难性的。

后续

弄清楚事情的原委后,便可以着手准备fix patch。

首先是下载源码,我们需要更改的文件是/system/core/libprocessgroup/processgroup.cpp,它属于的仓库是platform/system/core。这里简单介绍下Android源码的结构,它由上百个不同的Git仓库组成,譬如常见的platform/frameworks/base和platform/art。而最后组合这些Git仓库的地方就叫做manifest,它里面指定了每个仓库需要用到的版本。至于常用的工具repo,它底层调用的就是git命令,只不过它可以基于manifest帮我们便捷管理成百上千个Git仓库。

通过这个网页,我们可以获取platform/system/core这个仓库的下载地址,以及生成Change-Id的Hook:

bash 复制代码
git clone https://android.googlesource.com/platform/system/core && (cd core && f=`git rev-parse --git-dir`/hooks/commit-msg ; mkdir -p $(dirname $f) ; curl -Lo $f https://gerrit-review.googlesource.com/tools/hooks/commit-msg ; chmod +x $f)

下载完代码后,默认的分支为main。这个分支已经停止更新,因此我们需要按照AOSP的要求切换到android-latest-release。但其实android-latest-release并不是一个仓库分支,而是mainfest的分支。我们可以根据它来找到具体仓库的版本。

根据上图的内容,我们可以知道当下每个具体Git仓库的版本为android15-qpr2-release。这里的qpr指的是"Quarterly Platform Release",qpr2表示Android 15的第二次季度更新。因此我们可以采用如下命令切换到android15-qpr2-release分支。

arduino 复制代码
git checkout -b android15-qpr2-release origin/android15-qpr2-release

之后是代码改动,提交。Commit message里需要填入Google Issue Tracker的Bug ID,因此我们需要提前创建好Ticket,在里面描述清楚问题,以及和Google做必要的沟通。提交后的代码需要push到远程仓库,采用如下命令:

ruby 复制代码
git push --no-thin origin HEAD:refs/for/android15-qpr2-release

提交完之后,系统会返回一个android-review的链接给你。拿着它,我们便可以看到具体的提交。

Google的工程师结合Google Issue上的描述和这里的提交便可以对代码进行review。通过review comment,我们可以不断更新patchset,让修复尽可能完美。

最后,Google的工程师会将我们的代码cherrypick进他们的内部版本,这样我们便可以在日后的开源版本中看见自己的改动。而android-review上的这笔改动会被abandoned,表明这笔改动已被处理。

那我们如何知道自己的改动是被接纳了还是拒绝了呢?其实大多数Google的工程师都会友好地在Google Issue上回复状态,就像下面这样。

感受

虽然后AOSP时代依然可以贡献代码,但感觉远没有以前"友好",具体原因如下:

  1. android-latest-release是已经成熟的Android源码,而Google内部版本可能已经领先大半年了。这样一来,我们基于老版本不管是提交bug fix还是feature,Google的内部版本可能都已经有了。因此提交很可能变成无用功。
  2. 由于版本差异过大,Google cherrypick时大概率需要解冲突,这既增加了他们的人力开支,也让他们更倾向于自己改动,而非cherrypick。
  3. Google内部版本合入时碰到的错误我们看不到,黑盒般的来回沟通会费力费神。

事物的发展大抵如此,曾经开放的走向封闭,曾经繁华的走向萧条。不过,我们也不必为这种变化感到伤怀,就像千年前刘禹锡曾告诉我们的那样:沉舟侧畔千帆过,病树前头万木春。

相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
哈基米南北5 天前
ViewRootImpl 事件分发责任链分析
源码
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo6 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077006 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼6 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone6 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen6 天前
属性动画原理与高级动画实现
android·kotlin·canvas