本頁介紹通用內核映像 (GKI) 的版本控制方案。通用內核映像 (GKI)具有稱為內核版本的唯一標識符。內核版本由內核模塊接口(KMI)版本和子級別組成。內核版本特定於要發布的映像,而 KMI 版本代表構建版本的接口。一個 KMI 版本可以支持多個內核版本。內核版本僅與一個 KMI 版本相關聯。在內核模塊接口必須更改的不太可能發生的情況下,將迭代 KMI 生成以反映 KMI 版本的更改。
術語摘要
下表總結了本頁和 GKI 更新中使用的重要術語。
姓名 | 象徵 | 例子 | 描述 |
---|---|---|---|
內核發布 | wxy-zzz-k-後綴 | 5.4.42-android12-0-foo | GKI 版本的唯一標識符。這是uname 返回的值。 |
KMI 版本 | wx-zzz-k | 5.4-android12-0 | 描述 GKI 和動態可加載內核模塊 (DLKM) 之間的內核模塊接口 (KMI)。 |
子級 | 是的 | 42 | 描述同一 KMI 版本中內核版本的發布順序。 |
下表列出了其他相關術語作為參考。
姓名 | 象徵 | 例子 | 描述 |
---|---|---|---|
wxy | wxy | 5.4.42 | 有關詳細信息,請參閱Linux 內核 Makefile (搜索“KERNELRELEASE”)。 wxy在本文檔中直接使用。這通常也稱為三部分版本號。 VINTF 中使用的術語kernel version可能會與其他術語混淆,尤其是w 。 此變量在libkver中稱為kernel_version_tuple 。 此元組不得因任何更新(包括 OTA 或主線)而減少。 |
內核分支 | zzz-wx | 安卓12-5.4 | 該術語用於通用內核分支類型。 |
版本 | w | 5 | 本文檔中未使用該術語。此變量在libkver中稱為版本。 |
補丁級別 | X | 4 | 本文檔中未使用該術語。此變量在libkver 中稱為 patch_level 。 |
安卓版本 | zzz | 安卓12 | 這是與內核關聯的 Android(甜點)版本號。 比較 Android 版本號不得因任何更新(包括 OTA 或主線)而減少。 |
KMI 生成 | ķ | 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 二進製文件具有相同的內核版本,則它們必須按字節相同。
內核版本由 KMI 版本、子級別和後綴組成。出於本文檔的目的,KMI 生成後的後綴將被忽略。
KMI 版本
定義
KMI 版本定義如下:
KmiVersion :=
Version.PatchLevel-AndroidRelease-KmiGeneration
w .x -zzz -k
請注意,子級別y
不是 KMI 版本的一部分。對於Kernel release中的示例,KMI 版本為:
5.4-android12-0
描述
KMI 版本描述了 GKI 和動態可加載內核模塊 (DLKM) 之間的內核模塊接口 (KMI)。
如果兩個內核版本具有相同的 KMI 版本,則它們實現相同的內核模塊接口。與一個兼容的 DLKM 也與另一個兼容。
任何 OTA 更新都不得降低 KMI 版本。
子級
子級別y
描述了同一 KMI 版本中內核版本的發布順序。
對於具有相同 KMI 版本但分別具有子級別 Y1 和 Y2 的兩個內核版本:
- 如果 Y1 小於或等於 Y2,則運行 Y1 的設備可以接收到 Y2 的更新。
- 如果 Y1 大於 Y2,則運行 Y1 的設備無法更新為 Y2。
也就是說,如果 KMI 版本沒有變化,則子級別不得因任何 OTA 更新而降低。
從設備確定內核版本
完整的內核版本可以通過執行uname -r
或使用以下代碼片段的uname(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
的輸出用以下正則表達式解析(假設 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 客戶端以與任何其他分區相同的方式檢查啟動映像版本。