|
. ^4 o0 E' _4 W6 C" C0 i9 a
2 d& s' ]; [2 d' K/ K1 ^6 ^9 H2022.11.01 今天惊讶地发现,Google 已经正式把这个模拟器的技术命名成了“云安卓”。感觉应该可以有更多玩法,期待国内厂商玩出花……
1 Q- n7 P [7 e) s 长期以来,很多文章一讲到框架,总是脱不开下载源码、编译、刷机三个步骤。于是乎,一台 Google 亲儿子 Pixel 手机似乎成了搞框架开发的入门必备。
, Y' X C0 ^: c4 |( m; b$ D6 n事实上,Google 自己也面临着同样的问题。整个 Android 团队分布在全球各地,开发 + 设计 + 测试团队少说也有上几千人。Google 每年都会发布新手机,如果在每次研发新品都人手一台真机,消耗一定是巨大的。而且真正在手机厂商待过的同学才会知道,在新手机量产之前,测试机的资源都是十分紧张的,根本不可能做到人手一台。" W2 O1 V \/ Z( _- X
但是问题是摆在这的,开发需要真机的环境,测试需要真机来验问题,稳定性团队需要大量的手机来跑 Monkey,难道就真的没有一个办法摆脱对真机的依赖吗?/ @/ V% H3 [' m3 p
引见 CuttlefishCuttlefish 名字由来要说清楚 Cuttlefish,首先要介绍一下这个名字的由来。熟悉 Google 的同学都知道他们起名字向来很搞,这个时候需要先提一下另外一条鱼,Goldfish。
8 g" W& C% s) f4 b* E早年接触过 Android 开发的同学,对 avd 这个名词应该不会陌生。没错,就是 Android Virtual Device,大家口中的“模拟器”。 在那个手机性能非常拉胯的蛮荒年代,avd 的出现解决了很多开发者需要依赖真机的问题。而 avd 背后的原理就是 Goldfish。事实上,Goldfish 同时也是 Android 的一个内核代号。
; T4 q4 g6 |1 havd 确实极大程度解决了应用开发者的问题,做应用的小伙伴,改一下代码,编出一个 apk,可以直接 adb install 一下子就能看到效果,那框架开发者呢?虽然我们也有 adb push,但依然有很多变更是需要编固件才能验证的。编固件需要服务器去拉整个其他部门的代码来全编,全编需要等,好不容易等到固件出来了,需要吭哧吭哧刷机,刷机又很容易起不来,就算起来了,还有可能发现修改压根没生效……这一系列的操作完一抬头,估计下班时间也快到了,你就说你今天加不加班吧?- g( C+ g$ p7 x U' f8 }
Google 也发现了这个问题,从 Android 11 那时候开始,就已经着手研发下一代的模拟器,思路也很简单。传统的模拟器还是太重了,现在可是云时代啊,有没有可能利用一些技术,让 Android 跑在“云端”,而用户甚至通过浏览器就可以访问到呢?时间来到 2022 年,这条鱼总算有了一个相对稳定的版本,就是下面要讲的 Cuttlefish。4 t* x: t" ]$ P0 J
什么是 Cuttlefish?Google 官方给出的定义是:+ a3 | D9 o, A# a0 K4 I
Cuttlefish 是一种可配置的虚拟 Android 设备,既可以远程运行(使用第三方云产品,如 Google Cloud Engine),又可以在本地运行(在 Linux x86 机器上)。
/ U- h F* O9 ^: e 怎么理解呢?大家都知道国内大厂很多都有自己的云服务,比如阿里有阿里云,腾讯有腾讯云,华为有华为云。Google 自然也不例外,他们有自己的计算平台 Google Cloud Engine(以下简称 GCP)。自己买过服务器折腾过的小伙伴应该知道,有了实例之后,你就可以装操作系统,Linux、Windows 都行,然后再跑对应的服务,就可以远程访问了。
* t7 N& i4 o7 M. T6 z得益于 Cuttlefish,很早之前,Google 的一些框架开发的测试验证和稳定性验证工作就不在真机去做了,而是在 GCP 的一个个实例里进行。步骤也十分简单,只需要一台 Ubuntu 实例,设置好环境,下载代码,lunch Cuttlefish 的 target,编译部署,最后直接通过浏览器访问,就可以看到一个网页在线的模拟器。而且这一切,Google 全都是开源的,并且官网也有详细的操作步骤。既然可以部署到服务器,也就意味着我们可以本地验证,下面带大家了解一下本地运行。
5 H: C* v0 S, E4 N7 @部署 CuttlefishGoogle 其实已经在官网给出了详细的操作步骤了,不过最后那几步是让我们下载他编译好的镜像。我们不一样!我准备带大家现编现卖,毕竟我们可是开发者!
. z) Q9 `3 H/ x/ P! ^环境配置一台 x86_64 的电脑,Linux 环境,我自己惯用的是 Linux mint,理论上 Ubuntu 20.04 即可。没必要装太老的版本。
# ^; W/ {5 l1 F' y基本步骤- 确定一下电脑有没有 kvm,换句话说,确认一下是否支持虚拟化:
7 H: c6 I! `6 c4 s r- G/ q; Hgrep -c -w "vmx\|svm" /proc/cpuinfo复制代码上面的命令应该返回一个大于 0 的值,证明环境没问题。 - 使用如下命令安装 CuttleFish 所需的依赖:1 N" A* r' K9 U% F+ M+ k& U9 A0 G" X9 R
sudo apt install -y git devscripts config-package-dev debhelper-compat golang curlgit clone https://github.com/google/android-cuttlefishcd android-cuttlefishfor dir in base frontend; do cd $dir debuild -i -us -uc -b -d cd ..donesudo dpkg -i ./cuttlefish-base_*_*64.deb || sudo apt-get install -fsudo dpkg -i ./cuttlefish-user_*_*64.deb || sudo apt-get install -fsudo usermod -aG kvm,cvdnetwork,render $USERsudo reboot复制代码注意,最后那个命令是重启电脑,记得保存手头工作关掉其他窗口。 - 下载 AOSP 源码,国内推荐大家用清华或者科大的镜像,可以参考这篇文章来进行。
- 选择目标,开始编译:( Y% u$ x6 h2 ^) A4 {- U# s
source build/envsetup.shlunch aosp_cf_x86_64_phone-userdebug复制代码注意,这里的 aosp_cf_x86_64_phone-userdebug 是手机的镜像。如果我们想要编译其他目标,可以输入 lunch,然后在菜单里进行选择。其实我们从这里就可以看到,Google 这几年一直在积极开发 CuttleFish,aosp_cf 后面有各种设备类型,从手机,到TV,再到车机,反而是最下面 sdk_ 开头的目标没有那么多了,要知道,这可是之前编本地模拟器时候的目标呀。如果大家有兴趣的话,可以选择其它目标进行编译。 - 开始编译:' t' R1 i2 S+ j! u( \! N
m复制代码你没看错,就是一个 m。很多教程里还会让大家加上 -j 参数来指定任务数,我在这里并不推荐,因为每个人的电脑性能不同,这个参数设大了,在性能差的设备上编译会被直接 kill,设小了,又没法把性能跑满,所以还不如不传,编译脚本会根据你的电脑配置自己决定的。如果是新同步的代码,第一次会全编 AOSP 所有模块并输出镜像。我使用一台 Dell Precision 3660,时间大约在 50 分钟左右。 - 模拟器开机:
~& x3 a; D) i a" Q$ launch_cvd --start_webrtc=true复制代码Google 的命名梗又来了,他们把经由 Cuttlefish 搭建的模拟器称为 cvd,正好与 avd相对应。--start_webrtc 声明了我们需要在浏览器中使用 WebRTC 管理访问 Cuttlefish 设备。# B4 ~0 f; f% f* g, P6 r5 C
就这么简单,如果一切顺利,不会一会儿就可以在命令行见到一串 Boot completed,这代表模拟器已经启动好了。' B+ W* ?3 t9 z* c: Z3 e
* F1 o- U, p% J" Y0 Q
这个时候我们打开浏览器,输入 https://localhost:8443,回车,就可以看到 Cuttlefish 自动帮我们利用 WebRTC 搭建并运行的页面,我们在左侧选择刚才启动的 cvd 实例,在右边就可以看到它的实时画面,和传统的 avd 没有区别,点击事件什么的也完全能够响应,同时左侧还有一个工具条,可以模拟一些高级操作,这一点也和之前用的 avd 类似。( m* U3 j" i6 T4 H1 F' \( ?

6 F- m i9 W. t! o- f* T1 a使用 Cuttlefishadb 命令Cuttlefish 一旦跑起来之后,和本机用数据线插着一台手机是没什么两样的,使用 adb devices 可以看到这台设备,打开 Android Studio,也可以看到 logcat 里有日志输出。* L' G% P: ~/ F9 i s+ k. Z
多实例启动前面说过,Google 的测试团队很早就开始用 Cuttlefish 来验 bug 和跑 Monkey 了,这就面临多设备的问题,而 Cuttlefish 是完美支持多开的,只需要在启动的时候加上 --num_instances 参数即可,后面的数字代表你要启动几个实例。这里我以启动 2 个实例为例:
& F" f4 ^- b! d/ I( }# e$ launch_cvd --start_webrtc=true --num_instances= 2复制代码如果提示 launch_cvd 找不到,你应该是忘记 source build/envsetup.sh && lunch aosp_cf_x86_64_phone-userdebug 了。
0 O8 ] N! _* K$ E# w" y1 W$ g
: O7 W2 [" T) L可以从网页看到此时已经有2台设备在运行了,这两台设备是独立的,没有任何关系。我们尝试执行一下 adb devices:
$ G C4 f5 P( \( t" k! H9 J' z$ adb devicesList of devices attached0.0.0.0:6520 device0.0.0.0:6521 device复制代码确实可以看到两台设备,Cuttlefish 会从第一台设备开始,将端口号往上递增,来区分不同设备。有了多台设备,就可以轻松跑一些稳定性测试之类的了。还有很多其它用例,跟插着多台设备类似,不在此赘述。; }3 W+ O) H6 q" t) K, h
下图演示了在 Cuttlefish 上运行 atest 测试。说实话单元测试在很多公司似乎都不被重视,但 Google 自己的代码几乎都有单元测试。关于单元测试推荐 qing 的这篇文章:《给安卓开发小白们的unit test指南 - 这也能测?这也要测?》。: c) y: Q# N+ H8 W- I. G
& j3 S6 X4 D/ k/ k3 G
实战:Framework 修改快速验证Cuttlefish 在我这段时间用下来而言,最大的好处无非就是方便了我对 AOSP 的开发调试和验证,免去的繁琐的编模块,·adb push,甚至刷机等过程。这里打算以 Settings 模块为例,假设我现在有一个需求,想在 Settings 启动时弹出一个 toast。
$ f1 y- a4 g _5 E! k为了调试方便,这次选择 lunch eng 的类型:
! l' L+ r) d% }" U9 {2 ?$ source build/envsetup.sh && lunch aosp_cf_x86_64_phone-eng复制代码下面开始做需求,这里简单粗暴一些,直接打开 DashboardFragment.java,在 onCreate 加上代码:# ?1 \% ^# y9 d( v
@Overridepublic void onCreate(Bundle icicle) { super.onCreate(icicle); Toast.makeText(getPrefContext(), "Hello Cuttlfish", Toast.LENGTH_SHORT).show(); // Settings 原生代码 }}复制代码这只是最最最简单的改动,而更多时候,熟悉 Settings 模块的同学都知道,日常做 Settings 的需求,你可能还需要改到 SettingsLib 、 framework/base,还有其它很多关联目录,要编好几个 apk,好几个 jar,验证的时候要 push 一大堆东西到不同的目录,非常痛苦。
9 Y7 [% g6 w) u6 F( j7 h7 i# K8 {有了 Cuttlefish 之后,似乎就没那么复杂了。我一般会直接在 AOSP 根目录执行一下全编:
: y2 v* R" f0 |* i$ \. t$ m复制代码有些小伙伴估计急了,你特么在逗我?全编?别慌,要知道编译是增量的。Soong 会比对前后的 Ninja 文件,如果没有差异,直接跳过,有差异,则会编对应的地方。所以一般我甚至不关心我需要编哪几个模块,整个交给编译系统就好了,如下图所示:
2 g# s- f) N' w4 e
- V$ b4 t. A4 ^: T' e( f1 x因为是全编,模块编译完之后会自动生成新的 system.img。
1 N7 e* x/ R/ ]2 B$ x" m0 V
; {4 M" N, h2 x1 L+ y0 F3 E9 ~! h没有漫长的拷贝固件,没有漫长的刷机过程,无需担心能不能点亮,无需一次次点击为了跳过开机向导,而是直接启动 Cuttlefish,还记得命令吗?
_& }; E/ y$ [$ launch_cvd --start_webrtc=true复制代码然后打开我们修改后的模块:8 e4 z9 J7 w& I, T

R* K. U& n5 F看到 Toast 弹出,修改已经生效了,就是这么方便!- |* g& ?, Z2 I# U, j0 W% f
更多用法Cuttlefish 的更多用法,建议大家直接看官网,这里就不照搬了。其实 Google 很多文档写的都很详细,只可惜很多小伙伴要么不看,要么就是出问题直接搜百度,找到的都是别人消化后的东西。希望大家能养成“先看官网,后看文章”的好习惯。! M% e, U+ s1 `
source.android.com/docs/setup/…! ^ ?$ q# n& |* u, h
总结本文基于现阶段 Android Framework 工程师在开发调试阶段可能遇到的实际问题,向大家介绍了 Google 的云安卓方案,该方案不依赖物理设备,而是基于虚拟机 + WebRTC,通过浏览器就可以访问到云设备,理论上可以为 Android Framework 开发测试工作带来极大的便利。另外,云安卓整个技术理论上也会有很多其它应用场景,大家可以自行发挥创造力。
; ?" |) G5 g) k) O% o
7 ?* t% N$ @ N# ]# x4 o( ?" }% b& M1 h/ S( r6 Y
- I8 s) a- {4 u% Z: Z% D; k
, }5 Q5 \, ?6 B; u( d5 m0 s2 U9 ^8 M) y1 A/ N7 h; @' k$ Y/ Y0 E
|
|