两对兼容性矩阵和清单旨在进行协调,以验证框架和供应商实现是否可以相互协同工作。当框架兼容性矩阵与设备清单之间以及框架清单与设备兼容性矩阵之间匹配时,便会成功通过此验证。
系统会在构建时、在 OTA 更新软件包生成时、启动时以及 VTS 兼容性测试中完成此验证。
下面几部分将详细介绍各种组件使用的匹配规则。
框架兼容性矩阵版本匹配
如需使设备清单与框架兼容性矩阵相匹配,manifest.target-level
指定的 Shipping FCM 版本必须与 compatibility-matrix.level
指定的 FCM 版本完全相同。否则,这二者将不匹配。
如果使用 libvintf
请求框架兼容性矩阵,则此匹配始终都会成功,因为 libvintf
会打开设备清单,检索 Shipping FCM 版本,并返回该 Shipping FCM 版本的框架兼容性矩阵(以及更高 FCM 版本的兼容性矩阵中的一些可选 HAL)。
HAL 匹配
HAL 匹配规则可以识别清单文件中被视为受相应兼容性矩阵的所有者支持的 hal
元素的版本。
HIDL 和原生 HAL
HIDL 和原生 HAL 的匹配规则如下。
- 多个
<hal>
元素具有 AND 关系。 <hal>
元素可以具有<hal optional="true">
,用以将它们标记为不需要。- 同一个
<hal>
中的多个<version>
元素具有 OR 关系。如果指定了两个或两个以上版本,则只需要实现其中一个版本(请参见下面的 DRM 示例)。 - 当需要
<hal>
时,同一个<hal>
中的多个<instance>
和<regex-instance>
元素具有 AND 关系(请参见下面的 <ahref="#drm">DRM 示例)。</ahref="#drm">
示例:模块的成功 HAL 匹配
对于 2.5 版的 HAL,匹配规则如下:
矩阵 | 匹配清单 |
---|---|
2.5 |
2.5-2.∞. 在兼容性矩阵中,2.5 是 2.5-5 的简写形式。 |
2.5-7 |
2.5-2.∞. 表示以下含义:
2.5-7 ,则该设备与此框架保持兼容。 |
示例:DRM 模块的成功 HAL 匹配
框架兼容性矩阵指明了 DRM HAL 的以下版本信息:
<hal> <name>android.hardware.drm <version>1.0</version> <version>3.1-2</version> <interface> <name>IDrmFactory</name> <instance>default</instance> <instance>specific</instance> </interface> </hal> <hal> <name>android.hardware.drm <version>2.0</version> <interface> <name>ICryptoFactory</name> <instance>default</instance> <regex-instance>[a-z]+/[0-9]+</regex-instance> </interface> </hal>
供应商必须实现以下实例之一:
android.hardware.drm@1.x::IDrmFactory/default // where x >= 0 android.hardware.drm@1.x::IDrmFactory/specific // where x >= 0
android.hardware.drm@3.y::IDrmFactory/default // where y >= 1 android.hardware.drm@3.y::IDrmFactory/specific // where y >= 1
并且还必须实现以下所有实例:
android.hardware.drm@2.z::ICryptoFactory/default // where z >= 0 android.hardware.drm@2.z::ICryptoFactory/${INSTANCE} // where z >= 0 and ${INSTANCE} matches [a-z]+/[0-9]+ // e.g. legacy/0
AIDL HAL
Android 11(不包括 Android 11)之后的所有 Android 版本都支持 VINTF 中的 AIDL HAL 版本。AIDL HAL 的匹配规则类似于 HIDL 和原生 HAL 的匹配规则,只是没有主要版本,并且每个 HAL 实例只有一个版本(如果未指定版本,则为 1
)。
- 多个
<hal>
元素具有 AND 关系。 <hal>
元素可以具有<hal optional="true">
,用以将它们标记为不需要。- 当需要
<hal>
时,同一个<hal>
中的多个<instance>
和<regex-instance>
元素具有 AND 关系(请参见下面的<ahref="#vibrator">振动器示例)。</ahref="#vibrator">
示例:模块的成功 HAL 匹配
对于 5 版的 HAL,匹配规则如下:
矩阵 | 匹配清单 |
---|---|
5 |
5-∞. 在兼容性矩阵中,5 是 5-5 的简写形式。 |
5-7 |
5-∞. 表示以下含义:
5-7 ,则该设备与此框架保持兼容。 |
示例:多个模块的成功 HAL 匹配
框架兼容性矩阵指明了振动器和相机 HAL 的以下版本信息:
<hal> <name>android.hardware.vibrator <version>1-2</version> <interface> <name>IVibrator</name> <instance>default</instance> <instance>specific</instance> </interface> </hal> <hal> <name>android.hardware.camera <version>5</version> <interface> <name>ICamera</name> <instance>default</instance> <regex-instance>[a-z]+/[0-9]+</regex-instance> </interface> </hal>
供应商必须实现以下所有实例:
android.hardware.vibrator.IVibrator/default // version >= 1 android.hardware.vibrator.IVibrator/specific // version >= 1 android.hardware.camera.ICamera/default // version >= 5 android.hardware.camera.ICamera/${INSTANCE} // with version >= 5, where ${INSTANCE} matches [a-z]+/[0-9]+ // e.g. legacy/0
内核匹配
框架兼容性矩阵的 <kernel>
部分描述了框架对设备 Linux 内核的要求。该信息用于与设备的 VINTF 对象报告的内核相关信息进行匹配。
匹配内核分支
每个内核分支后缀(例如 5.4-r
)会映射到唯一的内核 FCM 版本(例如 5)。映射与版本字母(例如 R)和 FCM 版本(例如 5)之间的映射相同。
如果满足以下任一条件,VTS 测试会强制设备在设备清单 /vendor/etc/vintf/manifest.xml
中明确指定内核 FCM 版本:
-
内核 FCM 版本与目标 FCM 版本不同。例如,上述设备的目标 FCM 版本为 4,其内核 FCM 版本为 5(内核分支后缀为
r
)。 -
内核 FCM 版本高于或等于 5(内核分支后缀为
r
)。
VTS 测试强制要求:如果指定了内核 FCM 版本,内核 FCM 版本应大于或等于设备清单中的目标 FCM 版本。
示例:确定内核分支
如果设备具有目标 FCM 版本 4(在 Android 10 中发布),但从 4.19-r
分支运行内核,设备清单应指定以下内容:
<manifest version="2.0" type="device" target-level="4"> <kernel target-level="5" /> </manifest>
VINTF 对象会根据 4.19-r
内核分支上的要求检查内核兼容性,该内核分支在 FCM 版本 5 中指定。这些要求都是从 Android 源代码树中的 kernel/configs/r/android-4.19
构建的。
示例:确定 GKI 的内核分支
如果设备使用通用内核映像 (GKI),并且来自 /proc/version
的内核版本字符串如下所示:
5.4.42-android12-0-00544-ged21d463f856
然后,VINTF 对象会从内核版本获取 Android 版本,并据此确定内核 FCM 版本。在此示例中,android12
表示内核 FCM 版本 6(在 Android 12 中发布)。
如需详细了解如何解析内核版本字符串,请参阅 GKI 版本控制。
匹配内核版本
矩阵可以包括多个 <kernel>
部分,每个部分使用不同的 version
属性,格式如下:
${ver}.${major_rev}.${kernel_minor_rev}
VINTF 对象仅将 FCM 中版本匹配且具有相同 ${ver}
和 ${major_rev}
的 <kernel>
部分视为设备内核(即version="${ver}.${major_rev}.${matrix_minor_rev}")
),而忽略其他部分。此外,内核的次要修订版本必须是兼容性矩阵 (${kernel_minor_rev} >=
${matrix_minor_rev}
) 中的值。如果没有 <kernel>
部分满足这些要求,则不匹配。
示例:选择匹配要求
假设 /system/etc/vintf
中的 FCM 声明了以下要求(标头和页脚标记被省略):
<!-- compatibility_matrix.3.xml --> <kernel version="4.4.107" level="3"/> <!-- See kernel/configs/p/android-4.4/ for 4.4-p requirements --> <kernel version="4.9.84" level="3"/> <!-- See kernel/configs/p/android-4.9/ for 4.9-p requirements --> <kernel version="4.14.42" level="3"/> <!-- See kernel/configs/p/android-4.14/ for 4.14-p requirements --> <!-- compatibility_matrix.4.xml --> <kernel version="4.9.165" level="4"/> <!-- See kernel/configs/q/android-4.9/ for 4.9-q requirements --> <kernel version="4.14.105" level="4"/> <!-- See kernel/configs/q/android-4.14/ for 4.14-q requirements --> <kernel version="4.19.42" level="4"/> <!-- See kernel/configs/q/android-4.19/ for 4.19-q requirements --> <!-- compatibility_matrix.5.xml --> <kernel version="4.14.180" level="5"/> <!-- See kernel/configs/r/android-4.14/ for 4.14-r requirements --> <kernel version="4.19.123" level="5"/> <!-- See kernel/configs/r/android-4.19/ for 4.19-r requirements --> <kernel version="5.4.41" level="5"/> <!-- See kernel/configs/r/android-5.4/ for 5.4-r requirements -->
目标 FCM 版本、内核 FCM 版本和内核版本一起从 FCM 中选择内核要求:
目标 FCM 版本 | 内核 FCM 版本 | 内核版本 | 匹配结果 |
---|---|---|---|
3 (P) | 未指定 | 4.4.106 | 不匹配(次要版本不一致) |
3 (P) | 未指定 | 4.4.107 | 4.4-p |
3 (P) | 未指定 | 4.19.42 | 4.19-q (请参见下面的备注) |
3 (P) | 未指定 | 5.4.41 | 5.4-r (请参见下面的备注) |
3 (P) | 3 (P) | 4.4.107 | 4.4-p |
3 (P) | 3 (P) | 4.19.42 | 不匹配(无 4.19-p 内核分支) |
3 (P) | 4 (Q) | 4.19.42 | 4.19-q |
4 (Q) | 未指定 | 4.4.107 | 不匹配(无 4.4-q 内核分支) |
4 (Q) | 未指定 | 4.9.165 | 4.9-q |
4 (Q) | 未指定 | 5.4.41 | 5.4-r (请参见下面的备注) |
4 (Q) | 4 (Q) | 4.9.165 | 4.9-q |
4 (Q) | 4 (Q) | 5.4.41 | 不匹配(无 5.4-q 内核分支) |
4 (Q) | 5 (R) | 4.14.105 | 4.14-r |
4 (Q) | 5 (R) | 5.4.41 | 5.4-r |
5 (R) | 未指定 | 任意 | VTS 失败(必须为目标 FCM 版本 5 指定内核 FCM 版本) |
5 (R) | 4 (Q) | 任意 | VTS 失败(内核 FCM 版本 < 目标 FCM 版本) |
5 (R) | 5 (R) | 4.14.180 | 4.14-r |
匹配内核配置
如果 <kernel>
部分匹配,则该过程接下来会尝试将 config
元素与 /proc/config.gz
进行匹配。对于兼容性矩阵中的每个配置元素,系统将查找 /proc/config.gz
以查看该配置是否存在。如果某个配置项在匹配的 <kernel>
部分的兼容性矩阵中设置为 n
,便不得在 /proc/config.gz
中出现。最后,不在兼容性矩阵中的配置项不一定会包含在 /proc/config.gz
中。
示例:匹配内核配置
<value type="string">bar</value>
与"bar"
匹配。引号在兼容性矩阵中会被忽略,但会包含在/proc/config.gz
中。<value type="int">4096</value>
与4096
、0x1000
或0X1000
匹配。<value type="int">0x1000</value>
与4096
、0x1000
或0X1000
匹配。<value type="int">0X1000</value>
与4096
、0x1000
或0X1000
匹配。<value type="tristate">y</value>
与y
匹配。<value type="tristate">m</value>
与m
匹配。<value type="tristate">n</value>
表示配置项不得存在于/proc/config.gz
中。<value type="range">1-0x3</value>
与1
、2
、3
或十六进制对等数字匹配。
示例:成功的内核匹配
FCM 版本 1 的框架兼容性矩阵包含以下内核信息:
<kernel version="4.14.42"> <config> <key>CONFIG_TRI</key> <value type="tristate">y</value> </config> <config> <key>CONFIG_NOEXIST</key> <value type="tristate">n</value> </config> <config> <key>CONFIG_DEC</key> <value type="int">4096</value> </config> <config> <key>CONFIG_HEX</key> <value type="int">0XDEAD</value> </config> <config> <key>CONFIG_STR</key> <value type="string">str</value> </config> <config> <key>CONFIG_EMPTY</key> <value type="string"></value> </config> </kernel>
首先匹配内核分支。内核分支在设备清单的 manifest.kernel.target-level
中指定,如果未指定,则默认为 manifest.level
。如果设备清单中的内核分支:
- 为 1,则继续执行下一步并检查内核版本。
- 为 2,则与矩阵不匹配。VINTF 对象会从 FCM 版本的矩阵读取内核要求。
然后,匹配内核版本。如果 uname()
中的设备报告:
- 4.9.84(除非有一个含有
<kernel version="4.9.x">
的单独内核部分且其中的x <= 84
,否则与矩阵不匹配) - 4.14.41(与矩阵不匹配,小于
version
) - 4.14.42(与矩阵匹配)
- 4.14.43(与矩阵匹配)
- 4.1.22(除非有一个含有
<kernel version="4.1.x">
的单独内核部分且其中的x <= 22
,否则与矩阵不匹配)
选择适当的 <kernel>
部分后,对于值不为 n
的每个 <config>
项,我们预计对应条目会存在于 /proc/config.gz
中;对于值为 n
的每个 <config>
项,我们预计对应条目不会存在于 /proc/config.gz
中。我们预计 <value>
的内容与等号后面的文本(包括引号)完全匹配,直到换行符或 #
,开头和结尾的空格被截断。
以下内核配置是成功匹配的示例:
# comments don't matter CONFIG_TRI=y # CONFIG_NOEXIST shouldn't exist CONFIG_DEC = 4096 # trailing comments and whitespaces are fine CONFIG_HEX=57005 # 0XDEAD == 57005 CONFIG_STR="str" CONFIG_EMPTY="" # empty string must have quotes CONFIG_EXTRA="extra config items are fine too"
以下内核配置是不成功匹配的示例:
CONFIG_TRI="y" # mismatch: quotes CONFIG_NOEXIST=y # mismatch: CONFIG_NOEXIST exists CONFIG_HEX=0x0 # mismatch; value doesn't match CONFIG_DEC="" # mismatch; type mismatch (expect int) CONFIG_EMPTY=1 # mismatch; expects "" # mismatch: CONFIG_STR is missing
SE 策略匹配
SE 策略需要以下匹配:
<sepolicy-version>
定义了每个主要版本的次要版本的封闭范围。设备报告的 sepolicy 版本必须属于这些范围之一才能与框架兼容。匹配规则类似于 HAL 版本;如果 sepolicy 版本高于或等于范围内的最低版本,则匹配。最高版本仅供参考。<kernel-sepolicy-version>
(即 policydb 版本)必须低于设备报告的security_policyvers()
。
示例:成功的 SE 策略匹配
框架兼容性矩阵指明了以下 sepolicy 信息:
<sepolicy> <kernel-sepolicy-version>30</kernel-sepolicy-version> <sepolicy-version>25.0</sepolicy-version> <sepolicy-version>26.0-3</sepolicy-version> </sepolicy>
在设备上:
security_policyvers()
返回的值必须大于或等于 30。否则,不匹配。例如:- 如果设备返回 29,则不匹配。
- 如果设备返回 31,则匹配。
- SE 策略版本必须为 25.0-∞ 和 26.0-∞ 其中之一。否则,不匹配(“
26.0
”后面的“-3
”仅供参考)。
AVB 版本匹配
AVB 版本包含 MAJOR 版本和 MINOR 版本,格式为 MAJOR.MINOR(例如 1.0 和 2.1)。有关详细信息,请参阅版本管理和兼容性。AVB 版本具有以下系统属性:
ro.boot.vbmeta.avb_version
是引导加载程序中的libavb
版本ro.boot.avb_version
是 Android 操作系统中的libavb
版本 (init/fs_mgr
)
仅当已使用对应的 libavb 验证 AVB 元数据(并且返回 OK)时,才会显示该系统属性。如果验证失败(或根本没有执行验证),则不会显示该系统属性。
兼容性匹配将比较以下内容:
- sysprop
ro.boot.vbmeta.avb_version
与框架兼容性矩阵中的avb.vbmeta-version
;ro.boot.vbmeta.avb_version.MAJOR == avb.vbmeta-version.MAJOR
ro.boot.vbmeta.avb_version.MINOR >= avb.vbmeta-version.MINOR
- sysprop
ro.boot.avb_version
与框架兼容性矩阵中的avb.vbmeta-version
。ro.boot.avb_version.MAJOR == avb.vbmeta-version.MAJOR
ro.boot.avb_version.MINOR >= avb.vbmeta-version.MINOR
引导加载程序或 Android OS 可能包含 libavb
库的两个副本,每个副本具有不同的 MAJOR 版本,用于升级设备和启动设备。在这种情况下,可以共享同一个未签名的系统映像,但最终的签名系统映像则不同(具有不同的 avb.vbmeta-version
):
图 1. AVB 版本匹配(/system 为 P,其他所有分区均为 O)。
图 2. AVB 版本匹配(所有分区均为 P)。
示例:成功的 AVB 版本匹配
框架兼容性矩阵指明了以下 AVB 信息:
<avb> <vbmeta-version>2.1</vbmeta-version> </avb>
在设备上:
ro.boot.avb_version == 1.0 && ro.boot.vbmeta.avb_version == 2.1 mismatch
ro.boot.avb_version == 2.1 && ro.boot.vbmeta.avb_version == 3.0 mismatch
ro.boot.avb_version == 2.1 && ro.boot.vbmeta.avb_version == 2.3 match
ro.boot.avb_version == 2.3 && ro.boot.vbmeta.avb_version == 2.1 match
在 OTA 期间匹配 AVB 版本
对于搭载 Android 9 或更低版本的设备,在更新到 Android 10 期间,系统会将框架兼容性矩阵中的 AVB 版本要求与设备上的当前 AVB 版本进行匹配。如果 AVB 版本在 OTA 期间进行主要版本升级(例如,从 0.0 升级到 1.0),那么 OTA 中的 VINTF 兼容性检查不会反映 OTA 之后的兼容性。
为了缓解这个问题,原始设备制造商 (OEM) 可以在 OTA 软件包 (compatibility.zip
) 中放置一个假 AVB 版本来通过检查。为此,请执行以下操作:
- 择优挑选以下 CL 并将其添加到 Android 9 源代码树中:
- 为设备定义
BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE
。其值应该等于 OTA 之前的 AVB 版本,即设备启动时的 AVB 版本。 - 重新构建 OTA 软件包。
这些更改会自动将 BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE
作为 compatibility-matrix.avb.vbmeta-version
放置在以下文件中:
- 设备上的
/system/compatibility_matrix.xml
(未在 Android 9 中使用) - OTA 软件包中
compatibility.zip
内的system_matrix.xml
这些更改不会影响其他框架兼容性矩阵,包括 /system/etc/vintf/compatibility_matrix.xml
。在 OTA 之后,/system/etc/vintf/compatibility_matrix.xml
中的新值将用于进行兼容性检查。
VNDK 版本匹配
设备兼容性矩阵在 compatibility-matrix.vendor-ndk.version
中声明所需的 VNDK 版本。如果设备兼容性矩阵没有 <vendor-ndk>
标记,系统将不会实施任何要求,因此始终将其视为匹配项。
如果设备兼容性矩阵具有 <vendor-ndk>
标记,系统便会从框架在框架清单中提供的 VNDK 供应商快照集中查找具有匹配 <version>
的 <vendor-ndk>
条目。如果不存在此类条目,则没有匹配项。
如果确实存在此类条目,设备兼容性矩阵中枚举的库集必须是框架清单中声明的一组库的子集;否则,系统不会将此类条目视为匹配项。
- 一种特殊情况是,如果设备兼容性矩阵中未枚举任何库,系统会始终将该条目视为匹配项,因为空集是任何集的子集。
示例:成功的 VNDK 版本匹配
如果设备兼容性矩阵在 VNDK 上声明了以下要求:
<!-- Example Device Compatibility Matrix --> <vendor-ndk> <version>27</version> <library>libjpeg.so</library> <library>libbase.so</library> </vendor-ndk>
在框架清单中,系统仅会考虑具有版本 27 的条目。
<!-- Framework Manifest Example A --> <vendor-ndk> <version>27</version> <library>libjpeg.so</library> <library>libbase.so</library> <library>libfoo.so</library> </vendor-ndk>
示例 A 是匹配项,因为 VNDK 版本 27 在框架清单中,并且 {libjpeg.so, libbase.so, libfoo.so} ⊇ {libjpeg.so, libbase.so}
。
<!-- Framework Manifest Example B --> <vendor-ndk> <version>26</version> <library>libjpeg.so</library> <library>libbase.so</library> </vendor-ndk> <vendor-ndk> <version>27</version> <library>libbase.so</library> </vendor-ndk>
示例 B 不是匹配项。即使 VNDK 版本 27 在框架清单中,该快照中的框架也不支持 libjpeg.so
。VNDK 版本 26 将被忽略。
系统 SDK 版本匹配
设备兼容性矩阵在 compatibility-matrix.system-sdk.version
中声明一组所需的系统 SDK 版本。只有当该集合是所提供的系统 SDK 版本(在框架清单的 manifest.system-sdk.version
中声明)的子集时,才存在匹配项。
- 一种特殊情况是,如果设备兼容性矩阵中未枚举任何系统 SDK 版本,则系统会始终将该条目视为匹配项,因为空集是任何集的子集。
示例:成功的系统 SDK 版本匹配
如果设备兼容性矩阵在系统 SDK 上声明了以下要求:
<!-- Example Device Compatibility Matrix --> <system-sdk> <version>26</version> <version>27</version> </system-sdk>
然后,框架必须提供系统 SDK 版本 26 和 27 才能匹配。
<!-- Framework Manifest Example A --> <system-sdk> <version>26</version> <version>27</version> </system-sdk>
示例 A 是匹配项。
<!-- Framework Manifest Example B --> <system-sdk> <version>26</version> <version>27</version> <version>28</version> </system-sdk>
示例 B 是匹配项。
<!-- Framework Manifest Example C --> <system-sdk> <version>26</version> </system-sdk>
示例 C 不是匹配项,因为未提供系统 SDK 版本 27。