GKI 版本控制

本頁介紹通用內核映像 (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(甜點)版本號。

比較AndroidRelease字段時,會從字符串中提取數字部分進行比較。

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 客戶端以與任何其他分區相同的方式檢查啟動映像版本。