| <html devsite><head> |
| <title>匹配规则</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p>两对兼容性矩阵和清单旨在 <a href="/devices/tech/ota/index.html">OTA</a> 时进行协调,以验证框架和供应商实现是否可以相互协同工作。当框架兼容性矩阵与设备清单之间以及框架清单与设备兼容性矩阵之间匹配时,便成功通过此验证。下面几部分将详细介绍各种组件使用的匹配规则。</p> |
| |
| <h2 id="fcm-version">框架兼容性矩阵版本匹配</h2> |
| <p>要使设备清单与框架兼容性矩阵相匹配,<code>manifest.target-level</code> 指定的装运 FCM 版本必须与 <code>compatibility-matrix.level</code> 指定的 FCM 版本完全相同。否则,这二者将不匹配。</p> |
| |
| <p>如果使用 <code>libvintf</code> 请求框架兼容性矩阵,则此匹配始终都会成功,因为 <code>libvintf</code> 会打开设备清单,检索装运 FCM 版本,并返回该装运 FCM 版本的框架兼容性矩阵(以及更高 FCM 版本的兼容性矩阵中的一些可选 HAL)。</p> |
| |
| <h2 id="hals">HAL 匹配</h2> |
| <p>HAL 匹配规则可以识别清单文件中被视为受相应兼容性矩阵的所有者支持的 <code>hal</code> 元素的版本。</p> |
| <ul> |
| <li>多个 <code><hal></code> 元素具有 <strong>AND</strong> 关系。</li> |
| <li>同一个 <code><hal></code> 中的多个 <code><version></code> 元素具有 <strong>OR</strong> 关系。如果指定了两个或两个以上版本,则只需要实现其中一个版本(请参见下面的 DRM 示例)。</li> |
| <li>同一个 <code><hal></code> 中的多个 <code><instance></code> 和 <code><regex-instance></code> 元素具有 <strong>AND</strong> 关系(请参见下面的 DRM 示例)。</li> |
| </ul> |
| |
| <h4><strong>示例</strong>:相机模块的成功 HAL 匹配</h4> |
| <p>对于 2.5 版的 HAL,匹配规则如下:</p> |
| |
| <table> |
| <tbody><tr> |
| <th>矩阵</th> |
| <th>匹配清单</th> |
| </tr> |
| <tr> |
| <td><code>2.5</code></td> |
| <td>2.5-2.∞. 2.5-5 的简写形式。</td> |
| </tr> |
| <tr> |
| <td><code>2.5-7</code></td> |
| <td>2.5-2.∞. 表示以下含义: |
| <br /> |
| <ul> |
| <li>2.5 是要求的最低版本,这意味着提供 HAL 2.0-2.4 的清单不兼容。</li> |
| <li>2.7 是可以请求的最高版本,这意味着兼容性矩阵(框架或设备)的所有者将不会请求超过 2.7 的版本。请求版本 2.7 时,匹配清单的所有者仍然可以提供版本 2.10(以此为例)。兼容性矩阵所有者只知道请求的服务与 API 版本 2.7 兼容。</li> |
| <li>-7 仅供参考,不影响 OTA 更新流程。</li> |
| </ul> |
| 因此,如果某个设备的清单文件中的 HAL 版本为 2.10,而某个框架的兼容性矩阵中指明 <code>camera:</code><code>2.5-7</code>,则该设备与该框架保持兼容。</td> |
| </tr> |
| </tbody></table> |
| |
| <h4><strong>示例</strong>:DRM 模块的成功 HAL 匹配</h4> |
| <p>框架兼容性矩阵指明了 DRM HAL 的以下版本信息:</p> |
| |
| <pre class="prettyprint"><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> |
| </pre> |
| |
| <p>供应商必须实现以下实例之一:</p> |
| |
| <pre> |
| android.hardware.drm@1.x::IDrmFactory/default // where x >= 0 |
| android.hardware.drm@1.x::IDrmFactory/specific // where x >= 0 |
| </pre> |
| |
| 或 |
| |
| <pre> |
| android.hardware.drm@3.y::IDrmFactory/default // where y >= 1 |
| android.hardware.drm@3.y::IDrmFactory/specific // where y >= 1 |
| </pre> |
| |
| <p>…并且还必须实现以下所有实例:</p> |
| |
| <pre> |
| 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 |
| </pre> |
| |
| <h2 id="kernel">内核匹配</h2> |
| <p>框架兼容性矩阵的 <code><kernel></code> 部分说明了框架对设备上 Linux 内核的要求。该信息用于在 OTA 时与设备的 VINTF 对象报告的内核相关<a href="/devices/architecture/vintf/objects.html#runtime-collectible-information">信息</a>进行匹配。</p> |
| |
| <p>矩阵可以包括多个 <code><kernel></code> 部分,每个部分使用不同的 <code>version</code> 属性,格式如下:</p> |
| |
| <pre class="prettyprint">${ver}.${major_rev}.${kernel_minor_rev}</pre> |
| |
| <p>OTA 只会将具有相同 <code>${ver}</code> 和 <code>${major_rev}</code> 的 <code><kernel></code> 部分视为设备内核(即 <code>version="${ver}.${major_rev}.${matrix_minor_rev}")</code>),而忽略其他部分。此外,内核的次要修订版本必须是兼容性矩阵 (<code>${kernel_minor_rev} >= |
| ${matrix_minor_rev}</code>) 中的值。如果没有 <code><kernel></code> 部分满足这些要求,则不匹配。</p> |
| |
| <p>如果 <code><kernel></code> 部分匹配,则该过程接下来会尝试将 <code>config</code> 元素与 <code>/proc/config.gz</code> 进行匹配。对于兼容性矩阵中的每个配置元素,系统将查找 <code>/proc/config.gz</code> 以查看该配置是否存在。如果某个配置项在匹配的 <code><kernel></code> 部分的兼容性矩阵中设置为 <code>n</code>,便不得在 <code>/proc/config.gz</code> 中出现。最后,不在兼容性矩阵中的配置项不一定会包含在 <code>/proc/config.gz</code> 中。 |
| </p> |
| |
| <p>匹配示例:</p> |
| <ul> |
| <li><code><value type="string">bar</value></code> 与 <code>"bar"</code> 匹配。引号在兼容性矩阵中会被忽略,但会包含在 <code>/proc/config.gz</code> 中。</li> |
| <li><code><value type="int">4096</value></code> 与 <code>4096</code>、<code>0x1000</code> 或 <code>0X1000</code> 匹配。</li> |
| <li><code><value type="int">0x1000</value></code> 与 <code>4096</code>、<code>0x1000</code> 或 <code>0X1000</code> 匹配。</li> |
| <li><code><value type="int">0X1000</value></code> 与 <code>4096</code>、<code>0x1000</code> 或 <code>0X1000</code> 匹配。</li> |
| <li><code><value type="tristate">y</value></code> 与 <code>y</code> 匹配。</li> |
| <li><code><value type="tristate">m</value></code> 与 <code>m</code> 匹配。</li> |
| <li><code><value type="tristate">n</value></code> 表示配置项不得存在于 <code>/proc/config.gz</code> 中。</li> |
| <li><code><value type="range">1-0x3</value></code> 与 <code>1</code>、<code>2</code>、<code>3</code> 或十六进制对等数字匹配。 |
| </li> |
| </ul> |
| |
| <h4><strong>示例</strong>:成功的内核匹配</h4> |
| <p>框架兼容性矩阵包含以下内核信息:</p> |
| |
| <pre class="prettyprint"> |
| <kernel version="3.18.51"> |
| <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> |
| </pre> |
| |
| <p>首先匹配内核版本。如果 <code>uname()</code> 中的设备报告:</p> |
| <ul> |
| <li>3.10.73(除非有一个含有 <code><kernel version="3.10.x"></code> 的单独内核部分且其中的 <code>x <= 73</code>,否则与矩阵不匹配)</li> |
| <li>3.18.50(与矩阵不匹配,小于 <code>version</code>)</li> |
| <li>3.18.51(与矩阵匹配)</li> |
| <li>3.18.52(与矩阵匹配)</li> |
| <li>4.1.22(除非有一个含有 <code><kernel version="4.1.x"></code> 的单独内核部分且其中的 <code>x <= 22</code>,否则与矩阵不匹配)</li> |
| </ul> |
| |
| <p>选择适当的 <code><kernel></code> 部分后,对于值不为 <code>n</code> 的每个 <code><config></code> 项,我们预计对应条目会存在于 <code>/proc/config.gz</code> 中;对于值为 <code>n</code> 的每个 <code><config></code> 项,我们预计对应条目不会存在于 <code>/proc/config.gz</code> 中。我们预计 <code><value></code> 的内容与等号后面的文本(包括引号)完全匹配,直到换行符或 <code>#</code>,开头和结尾的空格被截断。</p> |
| |
| <p>以下内核配置是成功匹配的示例:</p> |
| |
| <pre class="prettyprint"> |
| # comments don't matter |
| CONFIG_TRI=y |
| # CONFIG_NOEXIST should not 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" |
| </pre> |
| |
| <p>以下内核配置是不成功匹配的示例:</p> |
| |
| <pre class="prettyprint"> |
| 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 |
| </pre> |
| |
| <h2 id="se-policy">SE 策略匹配</h2> |
| <p>SE 策略需要以下匹配:</p> |
| <ul> |
| <li><code><sepolicy-version></code> 定义了每个主要版本的次要版本的封闭范围。设备报告的 sepolicy 版本必须属于这些范围之一才能与框架兼容。匹配规则类似于 HAL 版本;如果 sepolicy 版本高于或等于范围内的最低版本,则匹配。最高版本仅供参考。</li> |
| <li><code><kernel-sepolicy-version></code>(即 policydb 版本)必须低于设备报告的 <code>security_policyvers()</code>。 |
| </li> |
| </ul> |
| |
| <h4><strong>示例</strong>:成功的 SE 策略匹配</h4> |
| <p>框架兼容性矩阵指明了以下 sepolicy 信息: |
| </p> |
| |
| <pre class="prettyprint"> |
| <sepolicy> |
| <kernel-sepolicy-version>30</kernel-sepolicy-version> |
| <sepolicy-version>25.0</sepolicy-version> |
| <sepolicy-version>26.0-3</sepolicy-version> |
| </sepolicy> |
| </pre> |
| |
| <p>在设备上:</p> |
| <ul> |
| <li><code>security_policyvers()</code> 返回的值必须大于或等于 30。否则,不匹配。例如: |
| <ul> |
| <li>如果设备返回 29,则不匹配。</li> |
| <li>如果设备返回 31,则匹配。</li> |
| </ul> |
| </li> |
| <li>SE 策略版本必须为 25.0-∞ 和 26.0-∞ 其中之一。否则,不匹配。(“<code>26.0</code>”后面的“<code>-3</code>”仅供参考。)</li> |
| </ul> |
| |
| <h2 id="avb-version">AVB 版本匹配</h2> |
| <p>AVB 版本包含 MAJOR 版本和 MINOR 版本,格式为 MAJOR.MINOR(例如 1.0 和 2.1)。有关详细信息,请参阅<a href="https://android.googlesource.com/platform/external/avb/#Versioning-and-compatibility" class="external">版本管理和兼容性</a>。AVB 版本具有以下系统属性:</p> |
| <ul> |
| <li><code>ro.boot.vbmeta.avb_version</code> 是引导加载程序中的 <code>libavb</code> 版本</li> |
| <li><code>ro.boot.avb_version</code> 是 Android 操作系统中的 <code>libavb</code> 版本 (<code>init/fs_mgr</code>)</li> |
| </ul> |
| |
| <p>仅当已使用对应的 libavb 验证 AVB 元数据(并且返回 OK)时,才会显示该系统属性。如果验证失败(或根本没有执行验证),则不会显示该系统属性。</p> |
| |
| <p>兼容性匹配将比较以下内容:</p> |
| <ul> |
| <li>sysprop <code>ro.boot.vbmeta.avb_version</code> 与框架兼容性矩阵中的 <code>avb.vbmeta-version</code>; |
| <ul> |
| <li><code>ro.boot.vbmeta.avb_version.MAJOR == avb.vbmeta-version.MAJOR</code></li> |
| <li><code>ro.boot.vbmeta.avb_version.MINOR >= avb.vbmeta-version.MINOR</code></li> |
| </ul> |
| </li> |
| <li>sysprop <code>ro.boot.avb_version</code> 与框架兼容性矩阵中的 <code>avb.vbmeta-version</code>。 |
| <ul> |
| <li><code>ro.boot.avb_version.MAJOR == avb.vbmeta-version.MAJOR</code></li> |
| <li><code>ro.boot.avb_version.MINOR >= avb.vbmeta-version.MINOR</code></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p>引导加载程序或 Android 操作系统可能包含 <code>libavb</code> 库的两个副本,每个副本具有不同的 MAJOR 版本,用于升级设备和启动设备。<em></em><em></em>在这种情况下,可以共享同一个未签名的系统映像,但最终的签名系统映像则不同(具有不同的 <code>avb.vbmeta-version</code>):</p> |
| |
| <img src="../images/treble_vintf_avb_o_p.png"/> |
| <figcaption><strong>图 1. </strong>AVB 版本匹配(<code>/system</code> 为 P,其他所有分区均为 O)。</figcaption> |
| <br /> |
| <br /> |
| <img src="../images/treble_vintf_avb_p.png"/> |
| <figcaption><strong>图 2.</strong> AVB 版本匹配(所有分区均为 P)。</figcaption> |
| |
| <h4><strong>示例</strong>:成功的 AVB 版本匹配</h4> |
| <p>框架兼容性矩阵指明了以下 AVB 信息:</p> |
| |
| <pre class="prettyprint"> |
| <avb> |
| <vbmeta-version>2.1</vbmeta-version> |
| </avb> |
| </pre> |
| |
| <p>在设备上:</p> |
| |
| <pre class="prettyprint"> |
| ro.boot.avb_version == 1.0 && |
| ro.boot.vbmeta.avb_version == 2.1 <font style="font-family: Roboto, Arial, Helvetica, sans-serif; background-color: red; color: white"> mismatch </font> |
| </pre> |
| |
| <pre class="prettyprint"> |
| ro.boot.avb_version == 2.1 && |
| ro.boot.vbmeta.avb_version == 3.0 <font style="font-family: Roboto, Arial, Helvetica, sans-serif; background-color: red; color: white"> mismatch </font> |
| </pre> |
| |
| <pre class="prettyprint"> |
| ro.boot.avb_version == 2.1 && |
| ro.boot.vbmeta.avb_version == 2.3 <font style="font-family: Roboto, Arial, Helvetica, sans-serif; background-color: green; color: white"> match </font> |
| </pre> |
| |
| <pre class="prettyprint"> |
| ro.boot.avb_version == 2.3 && |
| ro.boot.vbmeta.avb_version == 2.1 <font style="font-family: Roboto, Arial, Helvetica, sans-serif; background-color: green; color: white"> match </font> |
| </pre> |
| |
| <h3 id="avb-version-ota">在 OTA 期间匹配 AVB 版本</h3> |
| <p>对于搭载 Android 9 或更低版本的设备,在 OTA 期间,系统会将框架兼容性矩阵中的 AVB 版本要求与设备上的当前 AVB 版本进行匹配。如果 AVB 版本在 OTA 期间进行主要版本升级(例如,从 0.0 升级到 1.0),则 OTA 中的检查不会反映 OTA 之后的兼容性。</p> |
| <p>为了缓解这个问题,原始设备制造商 (OEM) 可以在 OTA 软件包 (<code>compatibility.zip</code>) 中放置一个假 AVB 版本来通过检查。为此,请执行以下操作:</p> |
| <ol> |
| <li>择优挑选以下 CL 并将其添加到 Android 9 源代码树中: |
| <ul> |
| <li><a href="https://android-review.googlesource.com/732261" class="external">CL 732261</a></li> |
| <li><a href="https://android-review.googlesource.com/732262" class="external">CL 732262</a></li> |
| </ul> |
| </li> |
| <li>为设备定义 <code>BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE</code>。其值应该等于 OTA 之前的 AVB 版本,即设备启动时的 AVB 版本。</li> |
| <li>重新构建 OTA 软件包。</li> |
| </ol> |
| <p>这些更改会自动将 <code>BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE</code> 作为 <code>compatibility-matrix.avb.vbmeta-version</code> 放置在以下文件中: |
| </p><ul> |
| <li>设备上的 <code>/system/compatibility_matrix.xml</code>(未在 Android 9 中使用)</li> |
| <li>OTA 软件包中 <code>compatibility.zip</code> 内的 <code>system_matrix.xml</code></li> |
| </ul> |
| 这些更改不会影响其他框架兼容性矩阵,包括 <code>/system/etc/vintf/compatibility_matrix.xml</code>。在 OTA 之后,<code>/system/etc/vintf/compatibility_matrix.xml</code> 中的新值将用于进行兼容性检查。 |
| <p></p> |
| |
| <h2 id="vndk">VNDK 版本匹配</h2> |
| <p>设备兼容性矩阵在 <code>compatibility-matrix.vendor-ndk.version</code> 中声明所需的 VNDK 版本。如果设备兼容性矩阵没有 <code><vendor-ndk></code> 标记,则系统不会实施任何要求,因此始终将其视为匹配项。</p> |
| <p>如果设备兼容性矩阵具有 <code><vendor-ndk></code> 标记,则系统会从框架在框架清单中提供的 VNDK 供应商快照集中查找具有匹配 <code><version></code> 的 <code><vendor-ndk></code> 条目。如果不存在此类条目,则没有匹配项。</p> |
| <p>如果确实存在此类条目,则设备兼容性矩阵中枚举的库集必须是框架清单中声明的一组库的子集;否则,系统不会将此类条目视为匹配项。</p> |
| <ul> |
| <li>一种特殊情况是,如果设备兼容性矩阵中未枚举任何库,则系统会始终将该条目视为匹配项,因为空集是任何集的子集。</li> |
| </ul> |
| |
| <h4><strong>示例</strong>:成功的 VNDK 版本匹配</h4> |
| <p>如果设备兼容性矩阵在 VNDK 上声明了以下要求: |
| </p> |
| |
| <pre class="prettyprint"> |
| <!-- Example Device Compatibility Matrix --> |
| <vendor-ndk> |
| <version>27</version> |
| <library>libjpeg.so</library> |
| <library>libbase.so</library> |
| </vendor-ndk> |
| </pre> |
| |
| <p>在框架清单中,系统仅会考虑具有版本 27 的条目。</p> |
| |
| <pre class="prettyprint"> |
| <!-- Framework Manifest Example A --> |
| <vendor-ndk> |
| <version>27</version> |
| <library>libjpeg.so</library> |
| <library>libbase.so</library> |
| <library>libfoo.so</library> |
| </vendor-ndk> |
| </pre> |
| |
| <p>示例 A 是匹配项,因为 VNDK 版本 27 在框架清单中,并且 <code>{libjpeg.so, libbase.so, libfoo.so} ⊇ {libjpeg.so, libbase.so}</code>。 |
| </p> |
| |
| <pre class="prettyprint"> |
| <!-- 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> |
| </pre> |
| |
| <p>示例 B 不是匹配项。即使 VNDK 版本 27 在框架清单中,该快照中的框架也不支持 <code>libjpeg.so</code>。VNDK 版本 26 将被忽略。</p> |
| |
| <h2 id="vsdk">系统 SDK 版本匹配</h2> |
| <p>设备兼容性矩阵在 <code>compatibility-matrix.system-sdk.version</code> 中声明一组所需的系统 SDK 版本。只有当该集合是所提供的系统 SDK 版本(在框架清单的 <code>manifest.system-sdk.version</code> 中声明)的子集时,才存在匹配项。</p> |
| <ul> |
| <li>一种特殊情况是,如果设备兼容性矩阵中未枚举任何系统 SDK 版本,则系统会始终将该条目视为匹配项,因为空集是任何集的子集。</li> |
| </ul> |
| |
| <h4><strong>示例</strong>:成功的系统 SDK 版本匹配</h4> |
| <p>如果设备兼容性矩阵在系统 SDK 上声明了以下要求: |
| </p> |
| |
| <pre class="prettyprint"> |
| <!-- Example Device Compatibility Matrix --> |
| <system-sdk> |
| <version>26</version> |
| <version>27</version> |
| </system-sdk> |
| </pre> |
| |
| <p>然后,框架必须提供系统 SDK 版本 26 和 27 才能匹配。</p> |
| |
| <pre class="prettyprint"> |
| <!-- Framework Manifest Example A --> |
| <system-sdk> |
| <version>26</version> |
| <version>27</version> |
| </system-sdk> |
| </pre> |
| |
| <p>示例 A 是匹配项。</p> |
| |
| <pre class="prettyprint"> |
| <!-- Framework Manifest Example B --> |
| <system-sdk> |
| <version>26</version> |
| <version>27</version> |
| <version>28</version> |
| </system-sdk> |
| </pre> |
| |
| <p>示例 B 是匹配项。</p> |
| |
| <pre class="prettyprint"> |
| <!-- Framework Manifest Example C --> |
| <system-sdk> |
| <version>26</version> |
| </system-sdk> |
| </pre> |
| |
| <p>示例 C 不是匹配项,因为未提供系统 SDK 版本 27。</p> |
| |
| </body></html> |