編完 aosp 還在刷機?雲安卓瞭解一下,來試試網頁版模擬器吧!

語言: CN / TW / HK

2022.11.01 今天驚訝地發現,Google 已經正式把這個模擬器的技術命名成了“雲安卓”。感覺應該可以有更多玩法,期待國內廠商玩出花……


長期以來,很多文章一講到框架,總是脫不開下載原始碼、編譯、刷機三個步驟。於是乎,一臺 Google 親兒子 Pixel 手機似乎成了搞框架開發的入門必備。

事實上,Google 自己也面臨著同樣的問題。整個 Android 團隊分佈在全球各地,開發 + 設計 + 測試團隊少說也有上幾千人。Google 每年都會發布新手機,如果在每次研發新品都人手一臺真機,消耗一定是巨大的。而且真正在手機廠商待過的同學才會知道,在新手機量產之前,測試機的資源都是十分緊張的,根本不可能做到人手一臺。

但是問題是擺在這的,開發需要真機的環境,測試需要真機來驗問題,穩定性團隊需要大量的手機來跑 Monkey,難道就真的沒有一個辦法擺脫對真機的依賴嗎?

引見 Cuttlefish

Cuttlefish 名字由來

要說清楚 Cuttlefish,首先要介紹一下這個名字的由來。熟悉 Google 的同學都知道他們起名字向來很搞,這個時候需要先提一下另外一條魚,Goldfish。

早年接觸過 Android 開發的同學,對 avd 這個名詞應該不會陌生。沒錯,就是 Android Virtual Device,大家口中的“模擬器”。 在那個手機效能非常拉胯的蠻荒年代,avd 的出現解決了很多開發者需要依賴真機的問題。而 avd 背後的原理就是 Goldfish。事實上,Goldfish 同時也是 Android 的一個核心代號。

avd 確實極大程度解決了應用開發者的問題,做應用的小夥伴,改一下程式碼,編出一個 apk,可以直接 adb install 一下子就能看到效果,那框架開發者呢?雖然我們也有 adb push,但依然有很多變更是需要編韌體才能驗證的。編韌體需要伺服器去拉整個其他部門的程式碼來全編,全編需要等,好不容易等到韌體出來了,需要吭哧吭哧刷機,刷機又很容易起不來,就算起來了,還有可能發現修改壓根沒生效……這一系列的操作完一抬頭,估計下班時間也快到了,你就說你今天加不加班吧?

Google 也發現了這個問題,從 Android 11 那時候開始,就已經著手研發下一代的模擬器,思路也很簡單。傳統的模擬器還是太重了,現在可是雲時代啊,有沒有可能利用一些技術,讓 Android 跑在“雲端”,而使用者甚至通過瀏覽器就可以訪問到呢?時間來到 2022 年,這條魚總算有了一個相對穩定的版本,就是下面要講的 Cuttlefish。

什麼是 Cuttlefish?

Google 官方給出的定義是:

Cuttlefish 是一種可配置的虛擬 Android 裝置,既可以遠端執行(使用第三方雲產品,如 Google Cloud Engine),又可以在本地執行(在 Linux x86 機器上)。

怎麼理解呢?大家都知道國內大廠很多都有自己的雲服務,比如阿里有阿里雲,騰訊有騰訊雲,華為有華為雲。Google 自然也不例外,他們有自己的計算平臺 Google Cloud Engine(以下簡稱 GCP)。自己買過伺服器折騰過的小夥伴應該知道,有了例項之後,你就可以裝作業系統,Linux、Windows 都行,然後再跑對應的服務,就可以遠端訪問了。

得益於 Cuttlefish,很早之前,Google 的一些框架開發的測試驗證和穩定性驗證工作就不在真機去做了,而是在 GCP 的一個個例項裡進行。步驟也十分簡單,只需要一臺 Ubuntu 例項,設定好環境,下載程式碼,lunch Cuttlefish 的 target,編譯部署,最後直接通過瀏覽器訪問,就可以看到一個網頁線上的模擬器。而且這一切,Google 全都是開源的,並且官網也有詳細的操作步驟。既然可以部署到伺服器,也就意味著我們可以本地驗證,下面帶大家瞭解一下本地執行。

部署 Cuttlefish

Google 其實已經在官網給出了詳細的操作步驟了,不過最後那幾步是讓我們下載他編譯好的映象。我們不一樣!我準備帶大家現編現賣,畢竟我們可是開發者!

環境配置

一臺 x86_64 的電腦,Linux 環境,我自己慣用的是 Linux mint,理論上 Ubuntu 20.04 即可。沒必要裝太老的版本。

基本步驟

  1. 確定一下電腦有沒有 kvm,換句話說,確認一下是否支援虛擬化:

bash grep -c -w "vmx\|svm" /proc/cpuinfo

上面的命令應該返回一個大於 0 的值,證明環境沒問題。

  1. 使用如下命令安裝 CuttleFish 所需的依賴:

bash sudo apt install -y git devscripts config-package-dev debhelper-compat golang curl git clone https://github.com/google/android-cuttlefish cd android-cuttlefish for dir in base frontend; do cd $dir debuild -i -us -uc -b -d cd .. done sudo dpkg -i ./cuttlefish-base_*_*64.deb || sudo apt-get install -f sudo dpkg -i ./cuttlefish-user_*_*64.deb || sudo apt-get install -f sudo usermod -aG kvm,cvdnetwork,render $USER sudo reboot

注意,最後那個命令是重啟電腦,記得儲存手頭工作關掉其他視窗。

  1. 下載 AOSP 原始碼,國內推薦大家用清華或者科大的映象,可以參考這篇文章來進行。

  2. 選擇目標,開始編譯:

bash source build/envsetup.sh lunch aosp_cf_x86_64_phone-userdebug

注意,這裡的 aosp_cf_x86_64_phone-userdebug 是手機的映象。如果我們想要編譯其他目標,可以輸入 lunch,然後在選單裡進行選擇。其實我們從這裡就可以看到,Google 這幾年一直在積極開發 CuttleFishaosp_cf 後面有各種裝置型別,從手機,到TV,再到車機,反而是最下面 sdk_ 開頭的目標沒有那麼多了,要知道,這可是之前編本地模擬器時候的目標呀。如果大家有興趣的話,可以選擇其它目標進行編譯。

  1. 開始編譯:

bash m

你沒看錯,就是一個 m。很多教程裡還會讓大家加上 -j 引數來指定任務數,我在這裡並不推薦,因為每個人的電腦效能不同,這個引數設大了,在效能差的裝置上編譯會被直接 kill,設小了,又沒法把效能跑滿,所以還不如不傳,編譯指令碼會根據你的電腦配置自己決定的。 如果是新同步的程式碼,第一次會全編 AOSP 所有模組並輸出映象。我使用一臺 Dell Precision 3660,時間大約在 50 分鐘左右。

  1. 模擬器開機:

bash $ launch_cvd --start_webrtc=true

Google 的命名梗又來了,他們把經由 Cuttlefish 搭建的模擬器稱為 cvd,正好與 avd相對應。--start_webrtc 聲明瞭我們需要在瀏覽器中使用 WebRTC 管理訪問 Cuttlefish 裝置。

就這麼簡單,如果一切順利,不會一會兒就可以在命令列見到一串 Boot completed,這代表模擬器已經啟動好了。

launch_cvd --start_webrtc=true_001.png

這個時候我們開啟瀏覽器,輸入 https://localhost:8443,回車,就可以看到 Cuttlefish 自動幫我們利用 WebRTC 搭建並執行的頁面,我們在左側選擇剛才啟動的 cvd 例項,在右邊就可以看到它的實時畫面,和傳統的 avd 沒有區別,點選事件什麼的也完全能夠響應,同時左側還有一個工具條,可以模擬一些高階操作,這一點也和之前用的 avd 類似。

image.png

使用 Cuttlefish

adb 命令

Cuttlefish 一旦跑起來之後,和本機用資料線插著一臺手機是沒什麼兩樣的,使用 adb devices 可以看到這臺裝置,開啟 Android Studio,也可以看到 logcat 裡有日誌輸出。

多例項啟動

前面說過,Google 的測試團隊很早就開始用 Cuttlefish 來驗 bug 和跑 Monkey 了,這就面臨多裝置的問題,而 Cuttlefish 是完美支援多開的,只需要在啟動的時候加上 --num_instances 引數即可,後面的數字代表你要啟動幾個例項。這裡我以啟動 2 個例項為例:

$ launch_cvd --start_webrtc=true --num_instances=2

如果提示 launch_cvd 找不到,你應該是忘記 source build/envsetup.sh && lunch aosp_cf_x86_64_phone-userdebug 了。

image.png

可以從網頁看到此時已經有2臺裝置在運行了,這兩臺裝置是獨立的,沒有任何關係。我們嘗試執行一下 adb devices: $ adb devices List of devices attached 0.0.0.0:6520 device 0.0.0.0:6521 device 確實可以看到兩臺裝置,Cuttlefish 會從第一臺裝置開始,將埠號往上遞增,來區分不同裝置。有了多臺裝置,就可以輕鬆跑一些穩定性測試之類的了。還有很多其它用例,跟插著多臺裝置類似,不在此贅述。

下圖演示了在 Cuttlefish 上執行 atest 測試。說實話單元測試在很多公司似乎都不被重視,但 Google 自己的程式碼幾乎都有單元測試。關於單元測試推薦 qing 的這篇文章:《給安卓開發小白們的unit test指南 - 這也能測?這也要測?》

image.png

實戰:Framework 修改快速驗證

Cuttlefish 在我這段時間用下來而言,最大的好處無非就是方便了我對 AOSP 的開發除錯和驗證,免去的繁瑣的編模組,·adb push,甚至刷機等過程。這裡打算以 Settings 模組為例,假設我現在有一個需求,想在 Settings 啟動時彈出一個 toast。

為了除錯方便,這次選擇 lunch eng 的型別:

bash $ source build/envsetup.sh && lunch aosp_cf_x86_64_phone-eng

下面開始做需求,這裡簡單粗暴一些,直接開啟 DashboardFragment.java,在 onCreate 加上程式碼:

java @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); Toast.makeText(getPrefContext(), "Hello Cuttlfish", Toast.LENGTH_SHORT).show(); // Settings 原生程式碼 } }

這只是最最最簡單的改動,而更多時候,熟悉 Settings 模組的同學都知道,日常做 Settings 的需求,你可能還需要改到 SettingsLibframework/base,還有其它很多關聯目錄,要編好幾個 apk,好幾個 jar,驗證的時候要 push 一大堆東西到不同的目錄,非常痛苦。

有了 Cuttlefish 之後,似乎就沒那麼複雜了。我一般會直接在 AOSP 根目錄執行一下全編:

bash $ m 有些小夥伴估計急了,你特麼在逗我?全編?別慌,要知道編譯是增量的。Soong 會比對前後的 Ninja 檔案,如果沒有差異,直接跳過,有差異,則會編對應的地方。所以一般我甚至不關心我需要編哪幾個模組,整個交給編譯系統就好了,如下圖所示:

image.png

因為是全編,模組編譯完之後會自動生成新的 system.img

image.png

沒有漫長的拷貝韌體,沒有漫長的刷機過程,無需擔心能不能點亮,無需一次次點選為了跳過開機嚮導,而是直接啟動 Cuttlefish,還記得命令嗎?

bash $ launch_cvd --start_webrtc=true

然後開啟我們修改後的模組:

vokoscreenNG-2022-10-31_18-58-13.gif

看到 Toast 彈出,修改已經生效了,就是這麼方便!

更多用法

Cuttlefish 的更多用法,建議大家直接看官網,這裡就不照搬了。其實 Google 很多文件寫的都很詳細,只可惜很多小夥伴要麼不看,要麼就是出問題直接搜百度,找到的都是別人消化後的東西。希望大家能養成“先看官網,後看文章”的好習慣。

https://source.android.com/docs/setup/create/cuttlefish

總結

本文基於現階段 Android Framework 工程師在開發除錯階段可能遇到的實際問題,向大家介紹了 Google 的雲安卓方案,該方案不依賴物理裝置,而是基於虛擬機器 + WebRTC,通過瀏覽器就可以訪問到雲裝置,理論上可以為 Android Framework 開發測試工作帶來極大的便利。另外,雲安卓整個技術理論上也會有很多其它應用場景,大家可以自行發揮創造力。