blob: 545bbcbbaf6fb62b79f97bf805ed168ceb9671a8 [file] [log] [blame]
<html devsite><head>
<title>HIDL 框架向后兼容性验证</title>
<meta name="project_path" value="/_project.yaml"/>
<meta name="book_path" value="/_book.yaml"/>
</head>
<body>
<!--
Copyright 2018 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/architecture/#hidl">HIDL HAL</a> 可保证 Android 核心系统(也称为 system.img 或框架)向后兼容。虽然<a href="/compatibility/vts">供应商测试套件 (VTS)</a> 测试可确保 HAL 按预期运行(例如,针对所有 1.2 实现运行 1.1 HAL 测试),但仍需要进行框架测试,以确保提供受支持的 HAL(1.0、1.1 或 1.2)时该框架适用于该 HAL。</p>
<p>要详细了解 HAL 接口定义语言 (HIDL),请参阅 <a href="/devices/architecture/hidl">HIDL</a><a href="/devices/architecture/hidl/versioning">HIDL 版本控制</a><a href="/devices/architecture/vintf/fcm#hal-version-deprecation">HIDL HAL 弃用</a></p>
<h2 id="about-HAL-upgrades">关于 HAL 升级</h2>
<p>HAL 升级分为两类:主要和次要。<em></em><em></em>大多数系统仅包含一个 HAL 实现,但支持多个实现。例如:</p>
<pre>android.hardware.teleport@1.0 # initial interface
android.hardware.teleport@1.1 # minor version upgrade
android.hardware.teleport@1.2 # another minor version upgrade
...
android.hardware.teleport@2.0 # major version upgrade
...</pre>
<p>系统分区通常包含一个框架守护进程(如 <code>teleportd</code>),用于管理与特定 HAL 实现组进行的通信。作为一种替代方法,系统可能会包含一个用于实现便捷客户端行为的系统库(如 <code>android.hardware.configstore-utils</code>)。在上面的示例中,无论设备上安装了哪个版本的 HAL,<code>teleportd</code> 都必须能够正常运行。</p>
<h2 id="google-maintained-versions">Google 维护的版本</h2>
<p>如果存在主要版本升级(1.0、2.0、3.0 等),则至少必须有一台 Google 维护的设备来维护各主要版本的实现,直到该版本弃用为止。如果 Google 维护的所有设备均未搭载特定主要版本,则 Google 会继续维护该主要版本的旧实现。</p>
<p>这种维护会增加一点额外的开销,因为创建新实现(如 2.0)时,旧实现(如 1.2)将保留且默认处于不使用的状态。</p>
<h2 id="testing-minor-version-upgrades">测试次要版本升级</h2>
<p>如要测试框架中次要版本的向后兼容性,则需要一种自动生成次要版本实现的方法。鉴于 Google 维护的版本存在一定限制,<code>hidl-gen</code> 只会(且只能)生成采用 1.(x+n) 实现并提供 1.x 实现的适配器;它无法根据 2.0 实现生成 1.0 实现(以主要版本的定义为准)。</p>
<p>例如,要针对 1.2 实现运行 1.1 测试,则必须能够模拟具有 1.1 实现的情况。1.2 接口可自动用作 1.1 实现,但行为上存在一些细微差别(例如,框架会手动检查所属的具体版本或对自身调用 <code>castFrom</code>)。</p>
<p>基本做法如下所示:</p>
<ol>
<li>在 Android 移动设备上安装 x.(y+n) 接口。</li>
<li>安装并启用目标为 x.y 的适配器。</li>
<li>测试设备,验证它能否按预期运行旧版次要版本。</li>
</ol>
<p>这些适配器完全隐藏了如下事实:实现实际上由 1.2 接口提供支持,并且仅提供 1.1 接口(适配器采用 1.2 接口并让其看起来像 1.1 接口)。</p>
<h3 id="example-workflow">工作流程示例</h3>
<p>在此示例中,Android 设备运行 <code>android.hardware.foo@1.1::IFoo/default</code>。要确保客户端在 <code>android.hardware.foo@1.0::IFoo/default</code> 上正常运行,请执行以下操作:</p>
<ol>
<li>在终端中,运行以下命令:
<pre>$ PACKAGE=android.hidl.allocator@1.0-adapter
$ INTERFACE=IAllocator
$ INSTANCE=ashmem
$ THREAD_COUNT=1 # can see current thread use on `lshal -i -e`
$ m -j $PACKAGE
$ /data/nativetest64/$PACKAGE/$PACKAGE $INTERFACE $INSTANCE $THREAD_COUNT
Trying to adapt down android.hidl.allocator@1.0-adapter/default
Press any key to disassociate adapter.</pre>
</li>
<li>使用 <code>adb shell stop</code>(或 <code>start</code>)重启客户端,或者仅终止相应进程。</li>
<li>测试完成后,取消关联适配器。</li>
<li>通过重启设备或重启客户端来恢复系统状态。</li>
</ol>
<h3 id="additional-targets">其他目标</h3>
<p>对于编译系统中使用 <code>hidl_interface</code> 指定的每个接口,<code>hidl-gen</code> 会自动为其适配器添加额外的编译目标。对于软件包 <code>a.b.c@x.y</code>,还需添加额外的 C++ 目标 <code>a.b.c@x.y-adapter</code></p>
<aside class="note"><strong>注意</strong>:无需提供任何 Java 适配器,因为 C++ 适配器始终可用于封装 Java 服务。</aside>
<p><code>a.b.c@x.y</code> 的适配器将一些实现 <code>a.b.c@x.(y+n)::ISomething/instance-name</code> 用作输入,并且必须注册 <code>a.b.c@x.y::ISomething/instance-name</code>,还必须取消注册 <code>y+n</code> 实现。</p>
<p>假设有如下示例接口:</p>
<pre>// IFoo.hal
package a.b.c@1.0;
interface IFoo {
doFoo(int32_t a) generates (int64_t b);
doSubInterface() generates (IFoo a);
};</pre>
<p><code>a.b.c@1.0-adapter</code> 提供的代码与以下示例类似:</p>
<pre>// autogenerated code
// in namespace a::b::c::V1_0::IFoo
struct MockFoo {
// takes some subclass of V1_0. May be V1_1, V1_2, etc...
MockFoo(V1_0::IFoo impl) mImpl(impl) {}
Return&lt;int64_t&gt; doFoo(int32_t a) {
return this-&gt;mImpl-&gt;doFoo(a);
}
Return&lt;V1_0::ICallback&gt; doSubInterface() {
// getMockForBinder returns MockCallback instance
// that corresponds to a particular binder object
// It can't return a new object every time or
// clients using interfacesSame will have
// divergent behavior when using the mock.
auto _hidl_out = this-&gt;mImpl-&gt;doSubInterface();
return getMockForBinder(_hidl_out);
}
};</pre>
<p>数据值会精确地转发到自动生成的模拟类以及从中转出,子接口除外(它们会返回)。这些接口必须封装在相应的最新回调对象中。</p>
</body></html>