aboutsummaryrefslogtreecommitdiff
path: root/zh-cn/devices/architecture/hidl-java/index.html
blob: 47693bd88b1b12dd5ca4b6bc7e7ae3e2d5785774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<html devsite><head>
    <title>HIDL Java</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 接口替换为稳定的带版本接口,可以采用 Java(如下所述),也可以是采用 <a href="/devices/architecture/hidl-cpp/index.html">C++</a> 的客户端和服务器端 HIDL 接口。</p>

<p>HIDL 接口主要通过本机代码使用,因此 HIDL 专注于自动生成高效的 C++ 代码。不过,HIDL 接口也必须能够直接通过 Java 使用,因为有些 Android 子系统(如 Telephony)很可能具有 Java HIDL 接口。</p>

<p>本部分介绍了 HIDL 接口的 Java 前端,详细说明了如何创建、注册和使用服务,以及使用 Java 编写的 HAL 和 HAL 客户端如何与 HIDL RPC 系统进行交互。</p>

<h2 id="client">作为客户端</h2>
<p>要访问软件包 <code>android.hardware.foo</code> 版本 1.0 中服务名称注册为 <code>foo-bar</code> 的接口 IFoo,请执行以下操作:</p>

<ol>
<li>添加库:

<ul>
<li>将以下内容添加到 Android.mk 中:
<pre class="prettyprint">LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java</pre>

<strong>或</strong><br />
</li>

<li>将以下内容添加到 Android.bp 中:
<pre class="prettyprint">
static_libs: [
    /* … */
    "android.hardware.foo-V1.0-java",
],
</pre>
</li>
</ul>
</li>
<li>将以下内容添加到您的 Java 文件中:
<pre class="prettyprint">
import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);
</pre>
<p class="caution"><strong>警告</strong>:不含参数的 Java <code>getService</code> 将不会等待服务启动。</p>
</li>
</ol>

<h2 id="service">提供服务</h2>
<p>Java 中的框架代码可能需要提供接口才能接收来自 HAL 的异步回调。</p>

<p class="warning"><strong>警告</strong>:请勿用 Java 实现驱动程序 (HAL)。我们强烈建议您用 C++ 实现驱动程序。</p>

<p class="warning"><strong>警告</strong>:Java 驱动程序必须与其客户端处于不同的进程中(不支持同一进程通信)。</p>

<p>对于 1.0 版软件包 <code>android.hardware.foo</code> 中的接口 <code>IFooCallback</code>,您可以按照以下步骤用 Java 实现接口。</p>

<ol>
<li>用 HIDL 定义您的接口。</li>
<li>打开 <code>/tmp/android/hardware/foo/IFooCallback.java</code> 作为参考。</li>
<li>为您的 Java 实现创建一个新模块。</li>
<li>检查抽象类 <code>android.hardware.foo.V1_0.IFooCallback.Stub</code>,然后编写一个新类以对其进行扩展,并实现抽象方法。</li>
</ol>

<h3 id="autogen">查看自动生成的文件</h3>
<p>要查看自动生成的文件,请运行以下命令:</p>
<pre class="prettyprint">
hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
</pre>

<p>这些命令会生成目录 <code>/tmp/android/hardware/foo/1.0</code>。对于文件 <code>hardware/interfaces/foo/1.0/IFooCallback.hal</code>,这会生成文件 <code>/tmp/android/hardware/foo/1.0/IFooCallback.java</code>,其中包含 Java 接口、代理代码和存根(代理和存根均与接口吻合)。</p>

<p><code>-Lmakefile</code> 会生成在构建时运行此命令的规则,并允许您包含 <code>android.hardware.foo-V1.0-java</code> 并链接到相应的文件。您可以在 <code>hardware/interfaces/update-makefiles.sh</code> 中找到自动为充满接口的项目执行此操作的脚本。
本示例中的路径是相对路径;硬件/接口可能是代码树下的一个临时目录,让您能够先开发 HAL 然后再进行发布。</p>

<h2 id="service">运行服务</h2>
<p>HAL 提供了一个接口 <code>IFoo</code>,它必须通过接口 <code>IFooCallback</code> 对框架进行异步回调。<code>IFooCallback</code> 接口不按名称注册为可检测到的服务;相反,<code>IFoo</code> 必须包含一个诸如 <code>setFooCallback(IFooCallback x)</code> 的方法。</p>

<p>要通过软件包 <code>android.hardware.foo</code> 版本 1.0 设置 <code>IFooCallback</code>,请将 <code>android.hardware.foo-V1.0-java</code> 添加到 <code>Android.mk</code> 中。运行服务的代码为:</p>

<pre class="prettyprint">
import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service you will be receiving callbacks from.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);
</pre>

<h2 id="extensions">接口扩展</h2>
<p>假设指定服务在所有设备上实现了接口 <code>IFoo</code>,那么该服务在特定设备上可能会提供在接口扩展 <code>IBetterFoo</code> 中实现的附加功能,即:</p>

<pre class="prettyprint">
interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};
</pre>

<p>感知到扩展接口的调用代码可以使用 <code>castFrom()</code> Java 方法将基本接口安全地转换为扩展接口:</p>

<pre class="prettyprint">
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service only implements the base interface.
}
</pre>

</body></html>