两对兼容性矩阵和清单旨在 OTA 更新时进行协调,以验证框架和供应商实现是否可以相互协同工作。当框架兼容性矩阵与设备清单之间以及框架清单与设备兼容性矩阵之间匹配时,便成功通过此验证。下面几部分将详细介绍各种组件使用的匹配规则。
框架兼容性矩阵版本匹配
如需使设备清单与框架兼容性矩阵相匹配,manifest.target-level
指定的 Shipping FCM 版本必须与 compatibility-matrix.level
指定的 FCM 版本完全相同。否则,这二者将不匹配。
如果使用 libvintf
请求框架兼容性矩阵,则此匹配始终都会成功,因为 libvintf
会打开设备清单,检索 Shipping FCM 版本,并返回该 Shipping FCM 版本的框架兼容性矩阵(以及更高 FCM 版本的兼容性矩阵中的一些可选 HAL)。
HAL 匹配
HAL 匹配规则可以识别清单文件中被视为受相应兼容性矩阵的所有者支持的 hal
元素的版本。
- 多个
<hal>
元素具有 AND 关系。 - 同一个
<hal>
中的多个<version>
元素具有 OR 关系。如果指定了两个或两个以上版本,则只需要实现其中一个版本(请参见下面的 DRM 示例)。 - 同一个
<hal>
中的多个<instance>
和<regex-instance>
元素具有 AND 关系(请参见下面的 DRM 示例)。
示例:相机模块的成功 HAL 匹配
对于 2.5 版的 HAL,匹配规则如下:
矩阵 | 匹配清单 |
---|---|
2.5 |
2.5-2.∞. 2.5-5 的简写形式。 |
2.5-7 |
2.5-2.∞. 表示以下含义:
camera: 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
内核匹配
框架兼容性矩阵的 <kernel>
部分描述了框架对设备 Linux 内核的要求。该信息用于在 OTA 时与设备的 VINTF 对象报告的内核相关信息进行匹配。
矩阵可以包括多个 <kernel>
部分,每个部分使用不同的 version
属性,格式如下:
${ver}.${major_rev}.${kernel_minor_rev}
OTA 仅将具有相同 ${ver}
和 ${major_rev}
的 <kernel>
部分视为设备内核(即version="${ver}.${major_rev}.${matrix_minor_rev}")
),而忽略其他部分。此外,内核的次要修订版本必须是兼容性矩阵 (${kernel_minor_rev} >=
${matrix_minor_rev}
) 中的值。如果没有 <kernel>
部分满足这些要求,则不匹配。
如果 <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
或十六进制对等数字匹配。
示例:成功的内核匹配
框架兼容性矩阵包含以下内核信息:
<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>
首先匹配内核版本。如果 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 操作系统可能包含 libavb
库的两个副本,每个副本具有不同的 MAJOR 版本,用于升级设备和启动设备。在这种情况下,可以共享同一个未签名的系统映像,但最终的签名系统映像则不同(具有不同的 avb.vbmeta-version
):

/system
为 P,其他所有分区均为 O)。
示例:成功的 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 或更低版本的设备,在 OTA 期间,系统会将框架兼容性矩阵中的 AVB 版本要求与设备上的当前 AVB 版本进行匹配。如果 AVB 版本在 OTA 期间进行主要版本升级(例如,从 0.0 升级到 1.0),则 OTA 中的检查不会反映 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。