The two pairs of compatibility matrices and manifests are meant to be reconciled to verify that the framework and vendor implementation can work with each other. This verification is successful upon a match between the framework compatibility matrix and the device manifest, as well as between the framework manifest and the device compatibility matrix.
This verification is done at build time, at OTA update package generation time, at boot time, and in VTS compatibility tests.
The following sections detail matching rules used by various components.
Framework compatibility matrix version matches
To match a device manifest with a framework compatibility matrix,
the Shipping FCM version specified by manifest.target-level
must be exactly equal to the FCM version specified by
compatibility-matrix.level
. Otherwise there's no match.
When the framework compatibility matrix is requested with libvintf
, this match is
always successful because libvintf
opens the device manifest, retrieves the Shipping
FCM Version, and returns the framework compatibility matrix at that Shipping FCM Version (plus some
optional HALs from compatibility matrices at higher FCM Versions).
HAL matches
The HAL-match rule identifies the versions of hal
elements in a
manifest file that are considered to be supported by the owner of the corresponding
compatibility matrix.
HIDL and native HALs
The match rules for HIDL and native HALs are as follows.
- Multiple
<hal>
elements are evaluated with a single AND relationship. <hal>
elements can have<hal optional="true">
to mark them as not required.- Multiple
<version>
elements within the same<hal>
have the OR relationship. If two or more are specified, only one of the versions needs to be implemented. (See the DRM example below.) - Multiple
<instance>
and<regex-instance>
elements within the same<hal>
are evaluated with a single AND relationship when the<hal>
is required. (See theDRM example below.)
Example: Successful HAL match for a module
For a HAL at version 2.5, the match rule is as follows:
Matrix | Matching Manifest |
---|---|
2.5 |
2.5-2.∞. In the compatibility matrix, 2.5 is the shorthand for
2.5-5 . |
2.5-7 |
2.5-2.∞. Indicates the following:
2.5-7 in its compatibility matrix. |
Example: Successful HAL match for DRM module
The framework compatibility matrix states the following version information for 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>
A vendor must implement ONE of the following instances; either
android.hardware.drm@1.x::IDrmFactory/default // where x >= 0 android.hardware.drm@1.x::IDrmFactory/specific // where x >= 0OR
android.hardware.drm@3.y::IDrmFactory/default // where y >= 1 android.hardware.drm@3.y::IDrmFactory/specific // where y >= 1
AND must also implement all of these instances:
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 HALs
All Android versions later than Android 11 (excluding Android
11) supports versions for AIDL HALs in VINTF.
The match rules for AIDL HALs are similar to those of HIDL and native HALs, except that
there're no major versions, and there is exactly one version per HAL instance (1
if
version is unspecified).
- Multiple
<hal>
elements are evaluated with a single AND relationship. <hal>
elements can have<hal optional="true">
to mark them as not required.- Multiple
<instance>
and<regex-instance>
elements within the same<hal>
are evaluated with a single AND relationship when the<hal>
is required. (See thevibrator example below.)
Example: Successful HAL match for a module
For a HAL at version 5, the match rule is as follows:
Matrix | Matching Manifest |
---|---|
5 |
5-∞. In the compatibility matrix, 5 is the shorthand for
5-5 . |
5-7 |
5-∞. Indicates the following:
5-7 in its compatibility matrix. |
Example: Successful HAL match for multiple modules
The framework compatibility matrix states the following version information for vibrator and camera HALs:
<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>
A vendor must implement all of these instances:
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 matches
The <kernel>
section of the framework compatibility matrix
describes the framework's requirements of the Linux kernel on the device. This
information is meant to be matched against the
information
about the kernel that gets reported by the device's VINTF object.
Match kernel branches
Each kernel branch suffix (for example, 5.4-r
) is mapped to a unique
kernel FCM version (for example, 5). The mapping is the same as the mapping between release letters
(for example, R) and FCM versions (for example, 5).
VTS tests enforce that the device explicitly specifies the kernel FCM version in the
device manifest, /vendor/etc/vintf/manifest.xml
, if one of the following is true:
-
The kernel FCM version is different from the target FCM version. For example, the
aforementioned device has a target FCM version 4, and its kernel FCM version is 5 (kernel
branch suffix
r
). -
The kernel FCM version is greater than or equal to 5 (kernel branch suffix
r
).
VTS tests enforce that, if the kernel FCM version is specified, the kernel FCM version is greater than or equal to the target FCM version in the device manifest.
Example: Determine the kernel branch
If the device has target FCM version 4 (released in Android 10), but
runs kernel from the 4.19-r
branch, the device manifest should specify the following:
<manifest version="2.0" type="device" target-level="4"> <kernel target-level="5" /> </manifest>
The VINTF object checks kernel compatibility against requirements on 4.19-r
kernel
branch, which is specified in FCM version 5. These requirements are built from
kernel/configs/r/android-4.19
in the Android source tree.
Example: Determine the kernel branch for GKI
If the device uses the Generic Kernel Image (GKI), and the kernel release string from
/proc/version
is the following:
5.4.42-android12-0-00544-ged21d463f856
Then, the VINTF object obtains the Android release from the kernel release, and use it to determine
the kernel FCM version. In this example, android12
means kernel FCM version 6
(released in Android 12).
For details on how the kernel release string is parsed, see GKI versioning.
Match kernel versions
A matrix can include multiple <kernel>
sections, each with
a different version
attribute using the format:
${ver}.${major_rev}.${kernel_minor_rev}
The VINTF object considers only the <kernel>
section from the
FCM with matching FCM version with the same
${ver}
and ${major_rev}
as the device kernel (i.e.,
version="${ver}.${major_rev}.${matrix_minor_rev}")
; other sections
are ignored. In addition, the minor revision from the kernel must be a value
from the compatibility matrix (${kernel_minor_rev} >=
${matrix_minor_rev}
;). If no <kernel>
section meets
these requirements, it's a non-match.
Example: Select requirements for matching
Consider the following hypothetical case where FCMs in /system/etc/vintf
declare the
following requirements (header and footer tags are omitted):
<!-- 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 -->
The target FCM version, the kernel FCM version, and the kernel version together select the kernel requirements from the FCMs:
Target FCM version | Kernel FCM version | Kernel version | Match with |
---|---|---|---|
3 (P) | unspecified | 4.4.106 | No match (minor version mismatch) |
3 (P) | unspecified | 4.4.107 | 4.4-p |
3 (P) | unspecified | 4.19.42 | 4.19-q (see note below) |
3 (P) | unspecified | 5.4.41 | 5.4-r (see note below) |
3 (P) | 3 (P) | 4.4.107 | 4.4-p |
3 (P) | 3 (P) | 4.19.42 | No match (no 4.19-p kernel branch) |
3 (P) | 4 (Q) | 4.19.42 | 4.19-q |
4 (Q) | unspecified | 4.4.107 | No match (no 4.4-q kernel branch) |
4 (Q) | unspecified | 4.9.165 | 4.9-q |
4 (Q) | unspecified | 5.4.41 | 5.4-r (see note below) |
4 (Q) | 4 (Q) | 4.9.165 | 4.9-q |
4 (Q) | 4 (Q) | 5.4.41 | No match (no 5.4-q kernel branch) |
4 (Q) | 5 (R) | 4.14.105 | 4.14-r |
4 (Q) | 5 (R) | 5.4.41 | 5.4-r |
5 (R) | unspecified | any | VTS fails (Must specify the kernel FCM version for the target FCM version 5) |
5 (R) | 4 (Q) | any | VTS fails (kernel FCM version < target FCM version) |
5 (R) | 5 (R) | 4.14.180 | 4.14-r |
Match kernel configurations
If the <kernel>
section does match, the process continues
by attempting to match config
elements against
/proc/config.gz
. For each config element in the compatibility
matrix, it looks up /proc/config.gz
to see if the config is
present. When a config item is set to n
in the compatibility
matrix for the matching <kernel>
section, it must be absent
from /proc/config.gz
. Finally, a config item not in the
compatibility matrix might or might not be present in /proc/config.gz
.
Example: Match kernel configurations
<value type="string">bar</value>
matches"bar"
. Quotes are omitted in the compatibility matrix but present in/proc/config.gz
.<value type="int">4096</value>
matches4096
or0x1000
or0X1000
.<value type="int">0x1000</value>
matches4096
or0x1000
or0X1000
.<value type="int">0X1000</value>
matches4096
or0x1000
or0X1000
.<value type="tristate">y</value>
matchesy
.<value type="tristate">m</value>
matchesm
.<value type="tristate">n</value>
means the config item must NOT exist in/proc/config.gz
.<value type="range">1-0x3</value>
matches1
,2
, or3
, or hexadecimal equivalent.
Example: Successful kernel match
A framework compatibility matrix with FCM version 1 has the following kernel information:
<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>
The kernel branch is matched first. The kernel branch is specified in the device manifest
in manifest.kernel.target-level
, which defaults to manifest.level
if the former isn't specified. If the kernel branch in the device manifest:
- is 1, proceeds to the next step and checks kernel version.
- is 2, no match to matrix. VINTF objects reads kernel requirements from matrix at FCM version 2 instead.
Then, the kernel version is matched. If a device in uname()
reports:
- 4.9.84 (no match to matrix unless there's a separate kernel section with
<kernel version="4.9.x">
, wherex <= 84
) - 4.14.41 (no match to matrix, smaller than
version
) - 4.14.42 (match to matrix)
- 4.14.43 (match to matrix)
- 4.1.22 (no match to matrix unless there's a separate kernel section
with
<kernel version="4.1.x">
wherex <= 22
)
After the appropriate <kernel>
section is selected, for
each <config>
item with value other than n
, we
expect the corresponding entry to be present in /proc/config.gz
;
for each <config>
item with value n
, we expect
the corresponding entry to not be present in /proc/config.gz
. We
expect the content of <value>
to exactly match the text after
the equal sign (including quotes), up to the newline character or
#
, with leading and trailing whitespace truncated.
The following kernel configuration is an example of a successful match:
# 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"
The following kernel configuration is an example of an unsuccessful match:
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 policy matches
SE policy requires the following matches:
<sepolicy-version>
defines a closed range of minor versions for every major version. The sepolicy version reported by the device must fall within one of these ranges to be compatible with the framework. Match rules are similar to HAL versions; it is a match if the sepolicy version is higher or equal to the minimum version for the range. The maximum version is purely informational.<kernel-sepolicy-version>
i.e. policydb version. Must be less than thesecurity_policyvers()
reported by the device.
Example: Successful SE policy match
The framework compatibility matrix states the following sepolicy information:
<sepolicy> <kernel-sepolicy-version>30</kernel-sepolicy-version> <sepolicy-version>25.0</sepolicy-version> <sepolicy-version>26.0-3</sepolicy-version> </sepolicy>
On the device:
- The value returned by
security_policyvers()
must be greater than or equal to 30. Otherwise it isn't a match. For example:- If a device returns 29, it isn't a match.
- If a device returns 31, it is a match.
- SE Policy version must be one of 25.0-∞ or 26.0-∞. Otherwise it isn't a
match. (The "
-3
" after "26.0
" is purely informational.)
AVB version matches
The AVB version contains a MAJOR version and MINOR version, with the format as MAJOR.MINOR (e.g., 1.0, 2.1). For details, refer to Versioning and Compatibility. AVB version has the following system properties:
ro.boot.vbmeta.avb_version
is thelibavb
version in bootloaderro.boot.avb_version
is thelibavb
version in Android OS (init/fs_mgr
)
The system property appears only when the corresponding libavb has been used to verify AVB metadata (and returns OK). It is absent if a verification failure occurred (or no verification occurred at all).
A compatibility match compares the following:
- sysprop
ro.boot.vbmeta.avb_version
withavb.vbmeta-version
from framework compatibility matrix;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
withavb.vbmeta-version
from framework compatibility matrix.ro.boot.avb_version.MAJOR == avb.vbmeta-version.MAJOR
ro.boot.avb_version.MINOR >= avb.vbmeta-version.MINOR
The bootloader or Android OS might contain two copies of libavb
libraries, each with a different MAJOR version for upgrade devices and launch
devices. In this case, the same unsigned system image can be shared but
the final signed system images are different (with different
avb.vbmeta-version
):
Figure 1. AVB version matches (/system is P, all other partitions are O).
Figure 2. AVB version matches (all partitions are P).
Example: Successful AVB version match
The framework compatibility matrix states the following AVB information:
<avb> <vbmeta-version>2.1</vbmeta-version> </avb>
On the device:
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
Match AVB version during OTA
For devices launched with Android 9 or lower, when updating to Android 10, the AVB version requirements in the framework compatibility matrix are matched against the current AVB version on the device. If the AVB version has a major version upgrade during an OTA (for example, from 0.0 to 1.0), the VINTF check for compatibility in OTA doesn't reflect the compatibility after the OTA.
To mitigate the issue, an OEM can place a fake AVB version in the OTA package
(compatibility.zip
) to pass the check. To do so:
- Cherry-pick the following CLs to the Android 9 source tree:
- Define
BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE
for the device. Its value should equal the AVB version before the OTA, that is, the AVB version of the device when it was launched. - Rebuild the OTA package.
These changes automatically place
BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE
as
compatibility-matrix.avb.vbmeta-version
in the following files:
/system/compatibility_matrix.xml
(which isn't used in Android 9) on the devicesystem_matrix.xml
incompatibility.zip
in the OTA package
These changes don't affect other framework compatibility matrices, including
/system/etc/vintf/compatibility_matrix.xml
. After the OTA, the new value in
/system/etc/vintf/compatibility_matrix.xml
is used for compatibility checks instead.
VNDK version matches
The device compatibility matrix declares the required VNDK version in
compatibility-matrix.vendor-ndk.version
. If the device
compatibility matrix doesn't have a <vendor-ndk>
tag, no
requirements are imposed, and hence it's always considered a match.
If the device compatibility matrix does have a <vendor-ndk>
tag, a <vendor-ndk>
entry with a matching
<version>
is looked up from the set of VNDK vendor snapshots
that's provided by the framework in the framework manifest. If such an entry doesn't
exist, there's no match.
If such an entry does exist, the set of libraries enumerated in the device compatibility matrix must be a subset of the set of libraries stated in the framework manifest; otherwise, the entry isn't considered a match.
- As a special case, if no libraries are enumerated in the device compatibility matrix, the entry is always considered a match, because empty set is a subset of any set.
Example: Successful VNDK version match
If the device compatibility matrix states the following requirement on VNDK:
<!-- Example Device Compatibility Matrix --> <vendor-ndk> <version>27</version> <library>libjpeg.so</library> <library>libbase.so</library> </vendor-ndk>
In the framework manifest, only the entry with version 27 is considered.
<!-- Framework Manifest Example A --> <vendor-ndk> <version>27</version> <library>libjpeg.so</library> <library>libbase.so</library> <library>libfoo.so</library> </vendor-ndk>
Example A is a match, because VNDK version 27 is in the framework manifest,
and {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>
Example B isn't a match. Even though VNDK version 27 is in the framework
manifest, libjpeg.so
isn't supported by the framework in that
snapshot. VNDK version 26 is ignored.
System SDK version matches
The device compatibility matrix declares a set of required System SDK
version in compatibility-matrix.system-sdk.version
. There's a
match only if the set is a subset of provided System SDK versions as declared
in manifest.system-sdk.version
in the framework manifest.
- As a special case, if no System SDK versions are enumerated in the device compatibility matrix, it's always considered a match, because empty set is a subset of any set.
Example: Successful System SDK version match
If the device compatibility matrix states the following requirement on System SDK:
<!-- Example Device Compatibility Matrix --> <system-sdk> <version>26</version> <version>27</version> </system-sdk>
Then, the framework must provide System SDK version 26 and 27 to match.
<!-- Framework Manifest Example A --> <system-sdk> <version>26</version> <version>27</version> </system-sdk>
Example A is a match.
<!-- Framework Manifest Example B --> <system-sdk> <version>26</version> <version>27</version> <version>28</version> </system-sdk>
Example B is a match.
<!-- Framework Manifest Example C --> <system-sdk> <version>26</version> </system-sdk>
Example C isn't a match, because System SDK version 27 isn't provided.