blob: 4ffc2f609b6de9a211859655185879a3a4942d6d [file] [log] [blame]
<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="hals">HAL 匹配</h2>
<p>HAL 匹配规则可以识别清单文件中被视为受相应兼容性矩阵的所有者支持的 <code>hal</code> 元素的版本。</p>
<ul>
<li>多个 <code>version</code> 元素使用 <strong>OR</strong> 进行连接(请参见下面的相机示例)。</li>
<li>多个同名的 <code>&lt;hal&gt;</code> 元素使用 <strong>AND</strong> 进行连接。</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">&lt;hal&gt;
&lt;name&gt;android.hardware.drm
&lt;version&gt;1.0&lt;/version&gt;
&lt;version&gt;3.1-2&lt;/version&gt;
&lt;interface&gt;
&lt;name&gt;IDrmFactory&lt;/name&gt;
&lt;instance&gt;default&lt;/instance&gt;
&lt;instance&gt;specific&lt;/instance&gt;
&lt;/interface&gt;
&lt;/hal&gt;
&lt;hal&gt;
&lt;name&gt;android.hardware.drm
&lt;version&gt;2.0&lt;/version&gt;
&lt;interface&gt;
&lt;name&gt;ICryptoFactory&lt;/name&gt;
&lt;instance&gt;default&lt;/instance&gt;
&lt;/interface&gt;
&lt;/hal&gt;
</pre>
<p>供应商必须实现以下 HAL 之一:</p>
<pre>
android.hardware.drm@1.x::IDrmFactory/default //where x &gt;= 0
android.hardware.drm@1.x::IDrmFactory/specific //where x &gt;= 0
</pre>
<pre>
android.hardware.drm@3.y::IDrmFactory/default //where y &gt;= 1
android.hardware.drm@3.y::IDrmFactory/specific //where y &gt;= 1
</pre>
<p>…并且还必须实现以下 HAL:</p>
<pre>
android.hardware.drm@2.z::ICryptoFactory/default //where z &gt;= 0
</pre>
<h2 id="kernel">内核匹配</h2>
<p>框架兼容性矩阵的 <code>&lt;kernel&gt;</code> 部分说明了框架对设备上 Linux 内核的要求。该信息用于在 OTA 时与设备的 VINTF 对象报告的内核相关<a href="/devices/architecture/vintf/objects.html#runtime-collectible-information">信息</a>进行匹配。</p>
<p>矩阵可以包括多个 <code>&lt;kernel&gt;</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>&lt;kernel&gt;</code> 部分视为设备内核(即 <code>version="${ver}.${major_rev}.${matrix_minor_rev}")</code>),而忽略其他部分。此外,内核的次要修订版本必须是兼容性矩阵 (<code>${kernel_minor_rev} &gt;=
${matrix_minor_rev}</code>) 中的值。如果没有 <code>&lt;kernel&gt;</code> 部分满足这些要求,则不匹配。</p>
<p>如果 <code>&lt;kernel&gt;</code> 部分匹配,则该过程接下来会尝试将 <code>config</code> 元素与 <code>/proc/config.gz</code> 进行匹配。对于兼容性矩阵中的每个配置元素,系统将查找 <code>/proc/config.gz</code> 以查看该配置是否存在。如果某个配置项在匹配的 <code>&lt;kernel&gt;</code> 部分的兼容性矩阵中设置为 <code>n</code>,便不得在 <code>/proc/config.gz</code> 中出现。最后,不在兼容性矩阵中的配置项不一定会包含在 <code>/proc/config.gz</code> 中。
</p>
<p>匹配示例:</p>
<ul>
<li><code>&lt;value type="string"&gt;bar&lt;/value&gt;</code><code>"bar"</code> 匹配。引号在兼容性矩阵中会被忽略,但会包含在 <code>/proc/config.gz</code> 中。</li>
<li><code>&lt;value type="int"&gt;4096&lt;/value&gt;</code><code>4096</code><code>0x1000</code><code>0X1000</code> 匹配。</li>
<li><code>&lt;value type="int"&gt;0x1000&lt;/value&gt;</code><code>4096</code><code>0x1000</code><code>0X1000</code> 匹配。</li>
<li><code>&lt;value type="int"&gt;0X1000&lt;/value&gt;</code><code>4096</code><code>0x1000</code><code>0X1000</code> 匹配。</li>
<li><code>&lt;value type="tristate"&gt;y&lt;/value&gt;</code><code>y</code> 匹配。</li>
<li><code>&lt;value type="tristate"&gt;m&lt;/value&gt;</code><code>m</code> 匹配。</li>
<li><code>&lt;value type="tristate"&gt;n&lt;/value&gt;</code> 表示配置项不得存在于 <code>/proc/config.gz</code> 中。</li>
<li><code>&lt;value type="range"&gt;1-0x3&lt;/value&gt;</code><code>1</code><code>2</code><code>3</code> 或十六进制对等数字匹配。
</li>
</ul>
<h4><strong>示例</strong>:成功的内核匹配</h4>
<p>框架兼容性矩阵包含以下内核信息:</p>
<pre class="prettyprint">
&lt;kernel version="3.18.51"&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_TRI&lt;/key&gt;
&lt;value type="tristate"&gt;y&lt;/value&gt;
&lt;/config&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_NOEXIST&lt;/key&gt;
&lt;value type="tristate"&gt;n&lt;/value&gt;
&lt;/config&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_DEC&lt;/key&gt;
&lt;value type="int"&gt;4096&lt;/value&gt;
&lt;/config&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_HEX&lt;/key&gt;
&lt;value type="int"&gt;0XDEAD&lt;/value&gt;
&lt;/config&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_STR&lt;/key&gt;
&lt;value type="string"&gt;str&lt;/value&gt;
&lt;/config&gt;
&lt;config&gt;
&lt;key&gt;CONFIG_EMPTY&lt;/key&gt;
&lt;value type="string"&gt;&lt;/value&gt;
&lt;/config&gt;
&lt;/kernel&gt;
</pre>
<p>首先匹配内核版本。如果 <code>uname()</code> 中的设备报告:</p>
<ul>
<li>3.10.73(除非有一个含有 <code>&lt;kernel version="3.10.x"&gt;</code> 的单独内核部分且其中的 <code>x &lt;= 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>&lt;kernel version="4.1.x"&gt;</code> 的单独内核部分且其中的 <code>x &lt;= 22</code>,否则与矩阵不匹配)</li>
</ul>
<p>选择适当的 <code>&lt;kernel&gt;</code> 部分后,对于值不为 <code>n</code> 的每个 <code>&lt;config&gt;</code> 项,我们预计对应条目会存在于 <code>/proc/config.gz</code> 中;对于值为 <code>n</code> 的每个 <code>&lt;config&gt;</code> 项,我们预计对应条目不会存在于 <code>/proc/config.gz</code> 中。我们预计 <code>&lt;value&gt;</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>&lt;sepolicy-version&gt;</code> 定义了每个主要版本的次要版本的封闭范围。设备报告的 sepolicy 版本必须属于这些范围之一才能与框架兼容。匹配规则类似于 HAL 版本;如果 sepolicy 版本高于或等于范围内的最低版本,则匹配。最高版本仅供参考。</li>
<li><code>&lt;kernel-sepolicy-version&gt;</code>(即 policydb 版本)必须与设备报告的 <code>security_policyvers()</code> 完全匹配。
</li>
</ul>
<h4><strong>示例</strong>:成功的 SE 策略匹配</h4>
<p>框架兼容性矩阵指明了以下 sepolicy 信息:
</p>
<pre class="prettyprint">
&lt;sepolicy&gt;
&lt;kernel-sepolicy-version&gt;30&lt;/kernel-sepolicy-version&gt;
&lt;sepolicy-version&gt;25.0&lt;/sepolicy-version&gt;
&lt;sepolicy-version&gt;26.0-3&lt;/sepolicy-version&gt;
&lt;/sepolicy&gt;
</pre>
<p>在设备上:</p>
<ul>
<li><code>security_policyvers()</code> 返回的值必须恰好等于 30。否则,不匹配。</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 &gt;= 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 &gt;= 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">
&lt;avb&gt;
&lt;vbmeta-version&gt;2.1&lt;/vbmeta-version&gt;
&lt;/avb&gt;
</pre>
<p>在设备上:</p>
<pre class="prettyprint">
ro.boot.avb_version == 1.0 &amp;&amp;
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 &amp;&amp;
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 &amp;&amp;
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 &amp;&amp;
ro.boot.vbmeta.avb_version == 2.1 <font style="font-family: Roboto, Arial, Helvetica, sans-serif; background-color: green; color: white"> match </font>
</pre>
</body></html>