GKI 版本管理架構

本頁說明通用核心映像檔 (GKI) 的版本管理機制。通用核心映像檔 (GKI) 具有稱為核心版本的專屬 ID。核心發行版本包含核心模組介面 (KMI) 版本和子層級。核心版本是針對發布的映像檔,而 KMI 版本則代表發布版本建構時使用的介面。KMI 版本可支援多個核心版本。核心版本只會與一個 KMI 版本綁定。萬一核心模組介面必須變更,系統會疊代 KMI 生成作業,以反映 KMI 版本變更。

條款摘要

下表摘要說明本頁面和 GKI 更新使用的重要術語。

名稱 符號 示例 說明
核心發布版本 w.x.y-zzz-k-suffix 5.4.42-android12-0-foo GKI 版本的專屬 ID。這是 uname 傳回的值。
KMI 版本 w.x-zzz-k 5.4-android12-0 說明 GKI 和可動態載入的核心模組 (DLKM) 之間的 KMI。
Sublevel y 42 說明相同 KMI 版本內的核心發布順序。

下表列出其他相關字詞,供您參考。

名稱 符號 示例 說明
w.x.y w.x.y 5.4.42

詳情請參閱 Linux 核心 Makefile (搜尋「KERNELRELEASE」)。

w.x.y 會直接用於整份文件。這也稱為三部分版本號碼。VINTF 中使用的「核心版本」一詞可能會與其他術語混淆,尤其是「w」

這個變數在 libkver 中稱為 kernel_version_tuple

任何更新 (包括 OTA 或主線) 都不得減少這個元組。

核心分支版本 zzz-w.x android12-5.4 這個詞彙用於 常見的 Kernel 分支類型
版本 w 鍵 5 本文未採用這個字詞。這個變數在 libkver 中稱為「version」
修補程式等級 x 4 本文未採用這個字詞。這個變數在 libkver 中稱為 patch_level
Android 版本 zzz android12

這是與核心相關聯的 Android (甜點) 版本號碼。

比較 AndroidRelease 欄位時,系統會從字串中擷取數字部分進行比較。

任何更新 (包括 OTA 或主線) 都不得降低 Android 版本號碼。

產生 KMI k 鍵 0

這是額外新增的號碼,用於處理不太可能發生的事件。如果修正安全性錯誤需要變更同一 Android 版本中的 KMI,KMI 生成次數就會增加。

KMI 生成號碼開頭為 0。

版本管理設計

核心發布版本

定義

對於隨附 GKI 出貨的裝置,核心版本定義如下:

KernelRelease :=
Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix
w      .x         .y       -zzz           -k            -something

詳情請參閱「從裝置判斷核心版本」。

以下是核心版本的範例。

5.4.42-android12-0-00544-ged21d463f856

說明

核心版本是 GKI 版本的專屬 ID。如果兩個 GKI 二進位檔的 Kernel 版本相同,則必須完全相同 (以位元組為單位)。

核心版本包含 KMI 版本、子層和後置字串。為方便說明,本文將忽略 KMI 生成後的後置字元。

KMI 版本

定義

KMI 版本定義如下:

KmiVersion :=
Version.PatchLevel-AndroidRelease-KmiGeneration
w      .x         -zzz           -k

請注意,子層級 y 並不屬於 KMI 版本。以「核心發布版本」中的範例為例,KMI 版本為:

5.4-android12-0

說明

KMI 版本說明 GKI 與可動態載入的核心模組 (DLKM) 之間的 KMI。

如果兩個核心版本具有相同的 KMI 版本,則會實作相同的核心模組介面。與其中一個 DLKM 相容的 DLKM 也會與另一個相容。

任何 OTA 更新都不得降低 KMI 版本。

Sublevel

子層級 y 說明相同 KMI 版本內的核心發布順序。

如果兩個核心版本具有相同的 KMI 版本,但分別具有子層級 Y1 和 Y2:

  • 如果 Y1 小於或等於 Y2,搭載 Y1 的裝置可以更新至 Y2。
  • 如果 Y1 大於 Y2,搭載 Y1 的裝置就無法更新至 Y2。

也就是說,如果 KMI 版本沒有變更,任何 OTA 更新都不得降低子層級。

從裝置判斷核心版本

如要查看完整核心版本,請執行 uname -runame(2) 使用下列程式碼片段:

std::string get_kernel_release() {
  struct utsname buf;
  return uname(&buf) == 0 ? buf.release : "";
}

輸出範例如下:

5.4.42-android12-0-00544-ged21d463f856

為方便說明,本文將忽略 KMI 生成後的任何內容,只擷取核心資訊。更正式地說,uname -r 的輸出內容會使用下列 regex 剖析 (假設 zzz 一律以「android」開頭):

^(?P<w>\d+)[.](?P<x>\d+)[.](?P<y>\d+)-(?P<z>android\d+)-(?P<k>\d+).*$

遭忽略的資訊可能包括:ci.android.com 建構版本號碼、基線核心上的修補程式數量,以及 Git 提交的 SHA 雜湊。

libkver

libkver 程式庫提供 C++ 介面,可剖析核心版本或 KMI 版本字串。如需 libkver 公開的 API 清單,請參閱 packages/modules/Gki/libkver/include/kver

VINTF 檢查

如果是 Android 11 以下版本,裝置製造商會在裝置資訊清單中手動指定 KMI 版本的 Android 版本部分。詳情請參閱「VINTF 核心比對規則」。

從 Android S 開始,KMI 版本的 Android 發布部分可從核心擷取,並在建構期間插入裝置資訊清單。

由於核心設定需求通常不會變更,因此不需要在相容性矩陣中編碼 k。不過,如果需要變更核心設定需求,請務必注意下列事項:

  • 相容性矩陣中對應的需求已移除。
  • 新增額外的 VTS 測試,以檢查 KMI 生成條件的新需求。

OTA 中繼資料中的啟動映像檔版本

即使透過 OTA 更新更新啟動映像檔,也必須以 OTA 酬載格式 payload.bin 包裝。OTA 酬載會為每個分割區編碼 version 欄位。update_engine 處理 OTA 酬載時,會比較這個欄位,確保分割區不會降級。

為避免混淆,OTA 中繼資料中開機磁碟分割區的 version 欄位稱為 boot image version

由於 ramdisk 一律從頭建構,因此使用 ramdisk 時間戳記就足以描述整個開機映像檔。除非您日後要將舊的開機映像檔縫合到新的核心二進位檔,否則不需要在開機映像檔版本中編碼核心版本。

在 OTA 更新之前,OTA 用戶端會以與其他任何分割區相同的方式,檢查開機映像檔版本。