常見問題

Google 是否在任何設備上使用過 A/B OTA?

是的。 A/B 更新的營銷名稱是無縫更新。自 2016 年 10 月起,Pixel 和 Pixel XL 手機附帶 A/B,所有 Chromebook 都使用相同的update_engine A/B 實現。必要的平台代碼實現在 Android 7.1 及更高版本中是公開的。

為什麼 A/B OTA 更好?

A/B OTA 在進行更新時可提供更好的用戶體驗。每月安全更新的測量結果表明,此功能已經證明是成功的:截至 2017 年 5 月,95% 的 Pixel 用戶在一個月後運行最新的安全更新,而 Nexus 用戶的這一比例為 87%,並且 Pixel 用戶的更新速度比 Nexus 用戶更快。在 OTA 期間更新塊失敗不再導致設備無法啟動;在新的系統映像成功啟動之前,Android 保留回退到以前的工作系統映像的能力。

A/B 如何影響 2016 像素分區大小?

下表包含有關發貨 A/B 配置與內部測試的非 A/B 配置的詳細信息:

像素分區大小甲/乙非 A/B
引導加載程序50*2 50
引導32*2 32
恢復0 32
緩存0 100
收音機70*2 70
小販300*2 300
系統2048*2 4096
全部的5000 4680

A/B 更新只需要增加 320 MiB 的閃存,刪除恢復分區可節省 32MiB,刪除緩存分區可節省 100MiB。這平衡了引導加載程序、引導分區和無線電分區的 B 分區的成本。供應商分區的大小翻了一番(絕大多數大小增加)。 Pixel 的 A/B 系統圖像是原始非 A/B 系統圖像的一半大小。

對於內部測試的 Pixel A/B 和非 A/B 變體(僅發貨 A/B),使用的空間僅相差 320MiB。在 32GiB 的設備上,這不到 1%。對於 16GiB 設備,這將低於 2%,而對於 8GiB 設備,這一比例幾乎為 4%(假設所有三個設備都具有相同的系統映像)。

你為什麼不使用 SquashFS?

我們對 SquashFS 進行了試驗,但未能達到高端設備所需的性能。我們不為手持設備使用或推薦 SquashFS。

更具體地說,SquashFS 在系統分區上節省了大約 50% 的大小,但絕大多數壓縮良好的文件是預編譯的 .odex 文件。這些文件的壓縮率非常高(接近 80%),但係統分區其餘部分的壓縮率要低得多。此外,Android 7.0 中的 SquashFS 引發了以下性能問題:

  • 與早期的設備相比,Pixel 具有非常快的閃存,但沒有大量的備用 CPU 週期,因此從閃存讀取的字節更少但需要更多 CPU 用於 I/O 是一個潛在的瓶頸。
  • 在空載系統上運行的人工基準測試中表現良好的 I/O 更改有時在實際負載下的實際用例中效果不佳(例如 Nexus 6 上的加密)。
  • 基準測試顯示在某些地方有 85% 的回歸。

隨著 SquashFS 的成熟和添加功能以減少 CPU 影響(例如不應壓縮的常用文件白名單),我們將繼續對其進行評估並向設備製造商提供建議。

在沒有 SquashFS 的情況下,您是如何將系統分區的大小減半的?

應用程序存儲在 .apk 文件中,這些文件實際上是 ZIP 檔案。每個 .apk 文件內部都有一個或多個 .dex 文件,其中包含可移植的 Dalvik 字節碼。 .odex 文件(優化的 .dex)與 .apk 文件分開存在,並且可以包含特定於設備的機器代碼。如果 .odex 文件可用,Android 可以以提前編譯的速度運行應用程序,而無需在每次啟動應用程序時等待編譯代碼。 .odex 文件並非絕對必要:Android 實際上可以通過解釋或即時 (JIT) 編譯直接運行 .dex 代碼,但 .odex 文件提供了啟動速度和運行時速度的最佳組合,如果空間可用。

示例:對於運行 Android 7.1 的 Nexus 6P 中的 installed-files.txt,總系統映像大小為 2628MiB(2755792836 字節),按文件類型劃分的總體系統映像大小的最大貢獻者如下:

.odex 1391770312 字節50.5%
.apk 846878259 字節30.7%
.so(本機 C/C++ 代碼) 202162479 字節7.3%
.oat 文件/.art 圖像163892188 字節5.9%
字體38952361 字節1.4%
icu 語言環境數據27468687 字節0.9%

這些數字對於其他設備也類似,因此在 Nexus/Pixel 設備上,.odex 文件佔據了大約一半的系統分區。這意味著我們可以繼續使用 ext4,但在出廠時將 .odex 文件寫入 B 分區,然後在首次啟動時將它們複製到/data 。與 ext4 A/B 一起使用的實際存儲與 SquashFS A/B 相同,因為如果我們使用 SquashFS,我們會在 system_a 而不是 system_b 上提供預選的 .odex 文件。

將 .odex 文件複製到 /data 是否意味著 /system 上保存的空間在 /data 上丟失了?

不完全是。在 Pixel 上,.odex 文件佔用的大部分空間用於應用程序,這些應用程序通常存在於/data上。這些應用程序採用 Google Play 更新,因此系統映像上的 .apk 和 .odex 文件在設備的大部分生命週期內都未使用。當用戶實際使用每個應用程序時,可以完全排除此類文件並替換為小型、配置文件驅動的 .odex 文件(因此不需要為用戶不使用的應用程序提供空間)。有關詳細信息,請參閱 Google I/O 2016 演講The Evolution of Art

由於以下幾個關鍵原因,很難進行比較:

  • 由 Google Play 更新的應用程序在收到第一次更新後始終會將其 .odex 文件放在/data上。
  • 用戶不運行的應用程序根本不需要 .odex 文件。
  • 配置文件驅動編譯生成的 .odex 文件比提前編譯生成的文件更小(因為前者只優化性能關鍵代碼)。

有關 OEM 可用的調整選項的詳細信息,請參閱配置 ART

/data 上沒有 .odex 文件的兩個副本嗎?

稍微複雜一點…… 新的系統鏡像寫好後,新版本的 dex2oat 對新的 .dex 文件運行以生成新的 .odex 文件。這發生在舊系統仍在運行時,因此新舊 .odex 文件同時位於/data上。

OtaDexoptService ( frameworks/base/+/master/services/core/java/com/android/server/pm/OtaDexoptService.java ) 中的代碼在優化每個包之前調用getAvailableSpace以避免過度填充/data 。請注意,此處的可用空間仍然是保守的:它是在達到通常的系統低空間閾值之前剩餘的空間量(以百分比和字節數衡量)。因此,如果/data已滿,則不會有每個 .odex 文件的兩個副本。相同的代碼也有一個 BULK_DELETE_THRESHOLD:如果設備接近填充可用空間(如前所述),則屬於未使用的應用程序的 .odex 文件將被刪除。這是另一個沒有每個 .odex 文件的兩個副本的情況。

/data已滿的最壞情況下,更新會一直等到設備重新啟動進入新系統並且不再需要舊系統的 .odex 文件。 PackageManager 處理這個:( frameworks/base/+/master/services/core/java/com/android/server/pm/PackageManagerService.java#7215 )。新系統成功啟動後, installd ( frameworks/native/+/master/cmds/installd/dexopt.cpp#2422 ) 可以刪除舊系統使用的 .odex 文件,使設備恢復到穩定狀態只有一個副本的地方。

因此,雖然/data可能包含所有 .odex 文件的兩個副本,但 (a) 這是臨時的,並且 (b) 只有在/data上有足夠的可用空間時才會發生。除了在更新期間,只有一個副本。作為 ART 的一般魯棒性功能的一部分,它永遠不會用 .odex 文件填充/data (因為這在非 A/B 系統上也是一個問題)。

所有這些寫入/複製不會增加閃存磨損嗎?

只有一小部分閃存被重寫:完整的 Pixel 系統更新寫入大約 2.3GiB。 (應用程序也會重新編譯,但非 A/B 也是如此。)傳統上,基於塊的完整 OTA 寫入的數據量相似,因此閃存磨損率應該相似。

刷機兩個系統分區會增加出廠刷機時間嗎?

不。像素沒有增加系統映像大小(它只是將空間劃分為兩個分區)。

將 .odex 文件保留在 B 上是否會導致出廠數據重置後重新啟動緩慢?

是的。如果您實際使用過設備、進行了 OTA 並執行了出廠數據重置,則第一次重啟將比其他情況下(1 分 40 秒對 Pixel XL 上的 40 秒)慢,因為 .odex 文件將從B 在第一次 OTA 之後無法複製到/data 。這就是權衡。

與常規啟動相比,出廠數據重置應該是一種罕見的操作,因此所花費的時間不太重要。 (這不會影響從工廠獲取設備的用戶或審閱者,因為在這種情況下 B 分區可用。)使用 JIT 編譯器意味著我們不需要重新編譯所有內容,所以它沒有你那麼糟糕可能會想。也可以使用清單中的coreApp="true"將應用程序標記為需要提前編譯:( frameworks/base/+/master/packages/SystemUI/AndroidManifest.xml#23 )。這當前由system_server使用,因為出於安全原因,它不允許 JIT。

將 .odex 文件保存在 /data 而不是 /system 上是否會導致 OTA 速度變慢後重新啟動?

不會。如上所述,新的 dex2oat 會在舊系統映像仍在運行時運行,以生成新系統所需的文件。在完成該工作之前,該更新不被視為可用。

我們可以(應該)運送一個 32GiB A/B 設備嗎? 16GiB? 8GiB?

32GiB 在 Pixel 上的表現很好,16GiB 中的 320MiB 意味著減少了 2%。同樣,8GiB 中的 320MiB 減少了 4%。顯然 A/B 不是 4GiB 設備的推薦選擇,因為 320MiB 開銷幾乎是總可用空間的 10%。

AVB2.0 是否需要 A/B OTA?

不需要。Android Verified Boot始終需要基於塊的更新,但不一定需要 A/B 更新。

A/B OTA 是否需要 AVB2.0?

不。

A/B OTA 是否會破壞 AVB2.0 的回滾保護?

不,這裡有些混亂,因為如果 A/B 系統無法引導到新的系統映像,它將(在您的引導加載程序確定的重試次數之後)自動恢復到“以前的”系統映像。但這裡的關鍵點是 A/B 意義上的“先前”實際上仍然是“當前”系統映像。一旦設備成功啟動新映像,回滾保護就會啟動並確保您無法返回。但在您實際成功啟動新映像之前,回滾保護不會將其視為當前系統映像。

如果您在系統運行時安裝更新,那不是很慢嗎?

對於非 A/B 更新,目標是盡快安裝更新,因為在應用更新時用戶正在等待並且無法使用他們的設備。對於 A/B 更新,情況正好相反;因為用戶仍在使用他們的設備,所以目標是盡可能減少影響,因此故意緩慢更新。通過 Java 系統更新客戶端中的邏輯(谷歌是 GmsCore,GMS 提供的核心包),Android 還嘗試選擇用戶完全不使用設備的時間。平台支持暫停/恢復更新,客戶端可以在用戶開始使用設備時暫停更新,當設備再次空閒時恢復更新。

進行 OTA 時有兩個階段,在 UI 中清楚地顯示為進度條下的Step 1 of 2Step 2 of 2 。步驟 1 對應於寫入數據塊,而步驟 2 是預編譯 .dex 文件。這兩個階段在性能影響方面完全不同。第一階段是簡單的 I/O。這需要很少的資源(RAM、CPU、I/O),因為它只是緩慢地複制塊。

第二階段運行 dex2oat 來預編譯新的系統鏡像。這顯然對其要求沒有明確的界限,因為它編譯實際的應用程序。顯然,編譯一個大而復雜的應用程序比一個小而簡單的應用程序要多得多。而在第一階段,沒有比其他磁盤塊更大或更複雜的磁盤塊。

該過程類似於 Google Play 在顯示5 個應用更新通知之前在後台安裝應用更新,多年來一直如此。

如果用戶實際上正在等待更新怎麼辦?

GmsCore 中的當前實現不區分後台更新和用戶啟動的更新,但將來可能會這樣做。在用戶明確要求安裝更新或正在觀看更新進度屏幕的情況下,我們將假設他們正在積極等待更新完成來優先考慮更新工作。

如果應用更新失敗會怎樣?

對於非 A/B 更新,如果更新未能應用,用戶通常會留下無法使用的設備。唯一的例外是如果失敗發生在應用程序啟動之前(例如,因為包無法驗證)。對於 A/B 更新,應用更新失敗不會影響當前運行的系統。稍後可以簡單地重試更新。

哪些片上系統 (SoC) 支持 A/B?

截至2017-03-15,我們有以下信息:

Android 7.x 及更早版本Android 8.x 及更高版本
高通根據 OEM 要求所有芯片組都將獲得支持
聯發科根據 OEM 要求所有芯片組都將獲得支持

有關時間表的詳細信息,請諮詢您的 SoC 聯繫人。對於上面未列出的 SoC,請直接聯繫您的 SoC。