常見問題

Google 是否在任何裝置上使用過 A/B OTA?

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

為什麼 A/B OTA 比較好?

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

A/B 如何影響 2016 Pixel 分割區大小?

下表包含出貨 A/B 配置與內部測試的非 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 檔案內都有一個或多個包含可移植 Dalvik 字節碼的 .dex 檔案。 .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 更新的應用程式在收到第一次更新後,總是會在/data上儲存其 .odex 檔案。
  • 用戶不運行的應用程式根本不需要 .odex 檔案。
  • 設定檔驅動編譯產生的 .odex 檔案比提前編譯更小(因為前者僅最佳化效能關鍵型程式碼)。

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

/data 上不是有兩個 .odex 檔案副本嗎?

有點複雜......新的系統映像寫入後,新版本的dex2oat針對新的.dex檔案運行以產生新的.odex檔案。這種情況發生在舊系統仍在運行時,因此新舊 .odex 檔案同時位於/data上。

OtaDexoptService ( frameworks/base/+/main/services/core/java/com/android/server/pm/OtaDexoptService.java ) 中的程式碼在最佳化每個套件之前呼叫getAvailableSpace以避免過度填充/data 。請注意,此處的可用空間仍然是保守的:它是在達到通常的系統低空間閾值之前剩餘的空間量(以百分比和位元組數來衡量)。因此,如果/data已滿,則每個 .odex 檔案不會有兩個副本。相同的程式碼還有一個 BULK_DELETE_THRESHOLD:如果裝置接近填滿可用空間(如上所述),則屬於未使用的應用程式的 .odex 檔案將被刪除。這是另一種情況,每個 .odex 檔案都沒有兩個副本。

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

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

所有這些寫入/複製不會增加快閃記憶體磨損嗎?

僅重寫快閃記憶體的一小部分:完整的 Pixel 系統更新寫入約 2.3GiB。 (應用程式也會重新編譯,但非 A/B 也是如此。)傳統上,基於區塊的完整 OTA 寫入的資料量相似,因此快閃記憶體磨損率應該相似。

刷新兩個系統分割區是否會增加工廠刷新時間?

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

將 .odex 檔案保留在 B 上是否會導致恢復出廠設定後重新啟動速度變慢?

是的。如果您實際使用過設備、進行了 OTA 並執行了出廠資料重置,則第一次重新啟動將比其他情況下慢(Pixel XL 上為 1 分 40 秒 vs 40 秒),因為 .odex 檔案將遺失B 在第一個OTA 之後,因此無法複製到/data 。這就是權衡。

與常規啟動相比,恢復出廠資料應該是一個很少見的操作,因此所花費的時間不太重要。 (這不會影響從工廠獲得設備的用戶或審查者,因為在這種情況下,B 分區可用。)使用 JIT 編譯器意味著我們不需要重新編譯所有內容,因此它沒有您那麼糟糕可能會想。也可以在清單中使用coreApp="true"將應用程式標記為需要事先編譯:( frameworks/base/+/main/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%。顯然,在 4GiB 裝置上,A/B 不是建議選擇,因為 320MiB 開銷幾乎佔總可用空間的 10%。

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

不需要。Android驗證啟動始終需要基於區塊的更新,但不一定是 A/B 更新。

A/B OTA 需要 AVB2.0 嗎?

不。

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

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

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

對於非 A/B 更新,目標是盡快安裝更新,因為使用者正在等待並且在應用程式更新時無法使用其裝置。對於 A/B 更新,情況正好相反;因為用戶仍在使用他們的設備,盡可能少的影響是目標,所以更新故意放慢。透過 Java 系統更新用戶端(對 Google 來說是 GmsCore,GMS 提供的核心套件)中的邏輯,Android 也會嘗試選擇使用者完全不使用其裝置的時間。平台支援暫停/恢復更新,用戶端可以在用戶開始使用裝置時暫停更新,並在裝置再次空閒時恢復更新。

進行 OTA 時有兩個階段,在 UI 中清楚地顯示為進度條下的第 1 步(共 2 步)第 2 步(共 2 步) 。步驟1對應寫入資料塊,而步驟2是預編譯.dex檔。這兩個階段對性能的影響有很大不同。第一階段是簡單的 I/O。這幾乎不需要資源(RAM、CPU、I/O),因為它只是緩慢地複製區塊。

第二階段執行 dex2oat 預先編譯新的系統映像。這顯然對其要求沒有那麼明確的界限,因為它編譯實際的應用程式。顯然,編譯一個大型而複雜的應用程式比編譯一個小型而簡單的應用程式需要更多的工作;而在階段 1 中,沒有任何磁碟區塊比其他區塊更大或更複雜。

這個過程類似於 Google Play 在背景安裝應用程式更新,然後顯示5 個應用程式更新通知,多年來一直這樣做。

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

GmsCore 中的目前實作不區分後台更新和使用者啟動的更新,但將來可能會這樣做。如果使用者明確要求安裝更新或正在觀看更新進度螢幕,我們將假設他們正在積極等待更新完成,從而確定更新工作的優先順序。

如果應用程式更新失敗會發生什麼?

對於非 A/B 更新,如果更新應用程式失敗,使用者通常會遇到無法使用的裝置。唯一的例外是,如果故障發生在應用程式啟動之前(例如,因為套件無法驗證)。對於 A/B 更新,應用程式更新失敗不會影響目前運行的系統。稍後可以重試更新。

哪些系統單晶片 (SoC) 支援 A/B?

截至2017年3月15日,我們掌握的資訊如下:

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

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