| <html devsite><head> |
| <title>HIDL C++</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>Android O 对 Android 操作系统的架构重新进行了设计,以在独立于设备的 Android 平台与特定于设备和供应商的代码之间定义清晰的接口。Android 已经以 HAL 接口的形式(在 <code>hardware/libhardware</code> 中定义为 C 标头)定义了许多此类接口。HIDL 将这些 HAL 接口替换为稳定的带版本接口,它们可以是采用 C++(如下所述)或 <a href="/devices/architecture/hidl-java/index.html">Java</a> 的客户端和服务器端 HIDL 接口。</p> |
| |
| <p>本部分中的几页内容介绍了 HIDL 接口的 C++ 实现,其中详细说明了 <code>hidl-gen</code> 编译器基于 HIDL <code>.hal</code> 文件自动生成的文件,这些文件如何打包,以及如何将这些文件与使用它们的 C++ 代码集成。</p> |
| |
| <h2 id="client-server">客户端和服务器实现</h2> |
| <p>HIDL 接口具有客户端和服务器实现:</p> |
| |
| <ul> |
| <li>HIDL 接口的<strong>客户端</strong>实现是指通过在该接口上调用方法来使用该接口的代码。</li> |
| <li><strong>服务器</strong>实现是指 HIDL 接口的实现,它可接收来自客户端的调用并返回结果(如有必要)。</li> |
| </ul> |
| |
| <p>在从 <code>libhardware</code> HAL 转换为 HIDL HAL 的过程中,HAL 实现成为服务器,而调用 HAL 的进程则成为客户端。默认实现可提供直通和绑定式 HAL,并可能会随着时间而发生变化:</p> |
| |
| <p><img src="../images/treble_cpp_legacy_hal_progression.png"/></p> |
| <p><strong>图 1.</strong> 旧版 HAL 的发展历程。</p> |
| |
| <h2>创建 HAL 客户端</h2> |
| <p>首先将 HAL 库添加到 makefile 中:</p> |
| |
| <ul> |
| <li>Make:<code>LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0</code></li> |
| <li>Soong:<code>shared_libs: [ …, android.hardware.nfc@1.0 ]</code></li> |
| </ul> |
| |
| <p>接下来,添加 HAL 头文件:</p> |
| |
| <pre class="prettyprint"> |
| #include <android/hardware/nfc/1.0/IFoo.h> |
| … |
| // in code: |
| sp<IFoo> client = IFoo::getService(); |
| client->doThing(); |
| </pre> |
| |
| <h2>创建 HAL 服务器</h2> |
| <p>要创建 HAL 实现,您必须具有表示 HAL 的 <code>.hal</code> 文件并已在 <code>hidl-gen</code> 上使用 <code>-Lmakefile</code> 或 <code>-Landroidbp</code> 为 HAL 生成 makefile(<code>./hardware/interfaces/update-makefiles.sh</code> 会为内部 HAL 文件执行这项操作,这是一个很好的参考)。从 <code>libhardware</code> 通过 HAL 传输时,您可以使用 c2hal 轻松完成许多此类工作。</p> |
| |
| <p>要创建必要的文件来实现您的 HAL,请使用以下代码:</p> |
| |
| <pre class="prettyprint"> |
| PACKAGE=android.hardware.nfc@1.0 |
| LOC=hardware/interfaces/nfc/1.0/default/ |
| m -j hidl-gen |
| hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ |
| -randroid.hidl:system/libhidl/transport $PACKAGE |
| hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ |
| -randroid.hidl:system/libhidl/transport $PACKAGE |
| </pre> |
| |
| <p>为了让 HAL 在直通模式下发挥作用(对于旧版设备),您必须具备 <em>HIDL_FETCH_IModuleName</em> 函数(位于 <code>/system/lib(64)?/hw/android.hardware.package@3.0-impl($OPTIONAL_IDENTIFIER).so</code> 下),其中 <code>$OPTIONAL_IDENTIFIER</code> 是一个标识直通实现的字符串。直通模式要求会通过上述命令自动满足,这些命令也会创建 <code>android.hardware.nfc@1.0-impl</code> 目标,但是可以使用任何扩展。例如,<code>android.hardware.nfc@1.0-impl-foo</code> 就是使用 <code>-foo</code> 区分自身。</p> |
| |
| <p>接下来,使用相应功能填写存根并设置守护进程。守护进程代码(支持直通)示例:</p> |
| |
| <pre class="prettyprint"> |
| #include <hidl/LegacySupport.h> |
| |
| int main(int /* argc */, char* /* argv */ []) { |
| return defaultPassthroughServiceImplementation<INfc>("nfc"); |
| } |
| </pre> |
| |
| <p><code>defaultPassthroughServiceImplementation</code> 将对提供的 <code>-impl</code> 库执行 <code>dlopen()</code> 操作,并将其作为绑定式服务提供。守护进程代码(对于纯绑定式服务)示例:</p> |
| |
| <pre class="prettyprint"> |
| int main(int /* argc */, char* /* argv */ []) { |
| // This function must be called before you join to ensure the proper |
| // number of threads are created. The threadpool will never exceed |
| // size one because of this call. |
| ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); |
| |
| sp<infc> nfc = new Nfc(); |
| const status_t status = nfc->registerAsService(); |
| if (status != ::android::OK) { |
| return 1; // or handle error |
| } |
| |
| // Adds this thread to the threadpool, resulting in one total |
| // thread in the threadpool. We could also do other things, but |
| // would have to specify 'false' to willJoin in configureRpcThreadpool. |
| ::android::hardware::joinRpcThreadpool(); |
| return 1; // joinRpcThreadpool should never return |
| } |
| </infc></pre> |
| |
| <p>此守护进程通常存在于 <code>$PACKAGE + "-service-suffix"</code>(例如 <code>android.hardware.nfc@1.0-service</code>)中,但也可以位于任何位置。HAL 的特定类的 <a href="/security/selinux/device-policy.html">sepolicy</a> 是属性 <code>hal_<module></code>(例如 <code>hal_nfc)</code>)。您必须将此属性应用到运行特定 HAL 的守护进程(如果同一进程提供多个 HAL,则可以将多个属性应用到该进程)。</p> |
| |
| </body></html> |