aboutsummaryrefslogtreecommitdiff
path: root/en/devices/architecture/hidl/types.html
blob: 1f36262de4df2f2ab6f598e65171d02aa1c11630 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
<html devsite>
  <head>
    <title>Data Types</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>This section describes HIDL data types. For implementation details, see
<a href="/devices/architecture/hidl-cpp/index.html">HIDL C++</a> (for C++
implementations) or <a href="/devices/architecture/hidl-java/index.html">HIDL
Java</a> (for Java implementations).</p>

<p>Similarities to C++ include:</p>
<ul>
<li><code>structs</code> use C++ syntax; <code>unions</code> support C++ syntax
by default. Both must be named; anonymous structs and unions are not supported.
</li>
<li>Typedefs are allowed in HIDL (as they are in C++).</li>
<li>C++-style comments are allowed and are copied to the generated header file.
</li>
</ul>

<p>Similarities to Java include:</p>
<ul>
<li>For each file, HIDL defines a Java-style namespace that must begin with
<code>android.hardware.</code>. The generated C++ namespace is
<code>::android::hardware::&#8230;</code>.</li>
<li>All definitions of the file are contained within a Java-style
<code>interface</code> wrapper.</li>
<li>HIDL array declarations follow the Java style, not the C++ style. Example:
<pre class="prettyprint">
struct Point {
    int32_t x;
    int32_t y;
};
Point[3] triangle;   // sized array
</pre>
</li>
<li>Comments are similiar to the javadoc format.</li>
</ul>

<h2 id=represent>Data representation</h2>
<p>A <code>struct</code> or <code>union</code> composed of
<a href="http://en.cppreference.com/w/cpp/language/data_members#Standard_layout">Standard-Layout</a>
(a subset of the requirement of plain-old-data types) has a consistent memory
layout in generated C++ code, enforced with explicit alignment attributes on
<code>struct</code> and <code>union</code> members.</p>

<p>Primitive HIDL types, as well as <code>enum</code> and <code>bitfield</code>
types (which always derive from primitive types), map to standard C++ types
such as <code>std::uint32_t</code> from
<a href="http://en.cppreference.com/w/cpp/types/integer">cstdint</a>.</p>

<p>As Java does not support unsigned types, unsigned HIDL types are mapped to
the corresponding signed Java type. <em>Structs</em> map to Java classes;
<em>arrays</em> map to Java arrays; <em>unions</em> are not currently supported
in Java. <em>Strings</em> are stored internally as UTF8. Since Java supports
only UTF16 strings, string values sent to or from a Java implementation are
translated, and may not be identical on re-translation as the character sets do
not always map smoothly.</p>

<p>Data received over IPC in C++ is marked <code>const</code> and is in
read-only memory that persists only for the duration of the function call. Data
received over IPC in Java has already been copied into Java objects, so it can
be retained without additional copying (and may be modified).</p>

<h2 id=annotations>Annotations</h2>
<p>Java-style annotations may be added to type declarations. Annotations are
parsed by the Vendor Test Suite (VTS) backend of the HIDL compiler but none of
such parsed annotations are actually understood by the HIDL compiler. Instead,
parsed VTS annotations are handled by the VTS Compiler (VTSC).</p>

<p>Annotations use Java syntax: <code>@annotation</code> or
<code>@annotation(value)</code> or <code>@annotation(id=value, id=value…)</code>
where value may be either a constant expression, a string, or a list of values
inside <code>{}</code>, just as in Java. Multiple annotations of the same name
can be attached to the same item.</p>

<h2 id=forward>Forward declarations</h2>
<p>In HIDL, structs may not be forward-declared, making user-defined,
self-referential data types impossible (e.g., you cannot describe a linked list
or a tree in HIDL). Most existing (pre-Android O) HALs have limited use of
forward declarations, which can be removed by rearranging data structure
declarations.</p>

<p>This restriction allows data structures to be copied by-value with a simple
deep-copy, rather than keeping track of pointer values that may occur multiple
times in a self-referential data structure. If the same data is passed twice,
such as with two method parameters or <code>vec&lt;T&gt;</code>'s that point to
the same data, two separate copies are made and delivered.</p>

<h2 id=nested>Nested declarations</h2>
<p>HIDL supports nested declarations to as many levels as desired (with one
exception noted below). For example:</p>

<pre class="prettyprint">
interface IFoo {
    uint32_t[3][4][5][6] multidimArray;

    vec&lt;vec&lt;vec&lt;int8_t&gt;&gt;&gt; multidimVector;

    vec&lt;bool[4]&gt; arrayVec;

    struct foo {
        struct bar {
            uint32_t val;
        };
        bar b;
    }
    struct baz {
        foo f;
        foo.bar fb; // HIDL uses dots to access nested type names
    }
    …
</pre>

<p>The exception is that interface types can only be embedded in
<code>vec&lt;T&gt;</code> and only one level deep (no
<code>vec&lt;vec&lt;IFoo&gt;&gt;</code>).</p>

<h2 id=raw-pointer>Raw pointer syntax</h2>
<p>The HIDL language does not use <strong>*</strong> and does not support the
full flexibility of C/C++ raw pointers. For details on how HIDL encapsulates
pointers and arrays/vectors, see <a href="#vec">vec&lt;T&gt; template</a>.</p>

<h2 id=interfaces>Interfaces</h2>
<p>The <code>interface</code> keyword has two usages.</p>

<ul>
<li>It opens the definition of an interface in a .hal file.</li>
<li>It can be used as a special type in struct/union fields, method parameters,
and returns. It is viewed as a general interface and synonym to
<code>android.hidl.base@1.0::IBase</code>.</li>
</ul>

<p>For example, <code>IServiceManager</code> has the following method:</p>
<pre class="prettyprint">
get(string fqName, string name) generates (interface service);
</pre>

<p>The method promises to lookup <em>some interface</em> by name. It is also
identical to replace interface with <code>android.hidl.base@1.0::IBase</code>.
</p>

<p>Interfaces can be only passed in two ways: as top-level parameters, or as
members of a <code>vec&lt;IMyInterface&gt;</code>. They cannot be members of
nested vecs, structs, arrays, or unions.</p>

<h2 id=mqdescriptor>MQDescriptorSync &amp; MQDescriptorUnsync</h2>
<p>The <code>MQDescriptorSync</code> and <code>MQDescriptorUnsync</code> types
pass a synchronized or unsynchronized Fast Message Queue (FMQ) descriptors
across a HIDL interface. For details, see
<a href="/devices/architecture/hidl-cpp/index.html">HIDL C++</a> (FMQs are not
supported in Java).</p>

<h2 id=memory>memory type</h2>
<p>The <code>memory</code> type is used to represent unmapped shared memory in
HIDL. It is only supported in C++. A value of this type can be used on the
receiving end to initialize an <code>IMemory</code> object, mapping the memory
and making it usable. For details, see
<a href="/devices/architecture/hidl-cpp/index.html">HIDL C++</a>.</p>

<p class=warning><strong>Warning:</strong> Structured data placed in shared
memory MUST be a type whose format will never change for the lifetime of the
interface version passing the <code>memory</code>. Otherwise, HALs may suffer
fatal compatibility problems.</p>

<h2 id=pointer>pointer type</h2>
<p>The <code>pointer</code> type is for HIDL internal use only.</p>

<h2 id=bitfield>bitfield&lt;T&gt; type template</h2>
<p><code>bitfield&lt;T&gt;</code> in which <code>T</code> is a
<a href="#enum">user-defined enum</a> suggests the value is a bitwise-OR of the
enum values defined in <code>T</code>. In generated code,
<code>bitfield&lt;T&gt;</code> appears as the underlying type of T. For
example:</p>

<pre class="prettyprint">
enum Flag : uint8_t {
    HAS_FOO = 1 &lt;&lt; 0,
    HAS_BAR = 1 &lt;&lt; 1,
    HAS_BAZ = 1 &lt;&lt; 2
};
typedef bitfield&lt;Flag&gt; Flags;
setFlags(Flags flags) generates (bool success);
</pre>

<p>The compiler handles the type Flags the same as <code>uint8_t</code>.</p>

<p>Why not use
<code>(u)int8_t</code>/<code>(u)int16_t</code>/<code>(u)int32_t</code>/<code>(u)int64_t</code>?
Using <code>bitfield</code> provides additional HAL information to the reader,
who now knows that <code>setFlags</code> takes a bitwise-OR value of Flag (i.e.
knows that calling <code>setFlags</code> with 16 is invalid). Without
<code>bitfield</code>, this information is conveyed only via documentation. In
addition, VTS can actually check if the value of flags is a bitwise-OR of Flag.
</p>

<h2 id=handle-primitive>handle primitive type</h2>

<p class=warning><strong>WARNING:</strong> Addresses of any kind (even physical
device addresses) must never be part of a native handle. Passing this
information between processes is dangerous and makes them susceptible to attack.
Any values passed between processes must be validated before they are used to
look up allocated memory within a process. Otherwise, bad handles may cause bad
memory access or memory corruption.</p>

<p>HIDL semantics are copy-by-value, which implies that parameters are copied.
Any large pieces of data, or data that needs to be shared between processes
(such as a sync fence), are handled by passing around file descriptors pointing
to persistent objects: <code>ashmem</code> for shared memory, actual files, or
anything else that can hide behind a file descriptor. The binder driver
duplicates the file descriptor into the other process.</p>

<h3 id=handle_t>native_handle_t</h3>
<p>Android supports <code>native_handle_t</code>, a general handle concept
defined in <code>libcutils</code>.</p>

<pre class="prettyprint">
typedef struct native_handle
{
  int version;        /* sizeof(native_handle_t) */
  int numFds;         /* number of file-descriptors at &amp;data[0] */
  int numInts;        /* number of ints at &amp;data[numFds] */
  int data[0];        /* numFds + numInts ints */
} native_handle_t;
</pre>

<p>A native handle is a collection of ints and file descriptors that gets passed
around by value. A single file descriptor can be stored in a native handle with
no ints and a single file descriptor. Passing handles using native handles
encapsulated with the <code>handle</code> primitive type ensures that native
handles are directly included in HIDL.</p>

<p>As a <code>native_handle_t</code> has variable size, it cannot be included
directly in a struct. A handle field generates a pointer to a separately
allocated <code>native_handle_t</code>.</p>

<p>In earlier versions of Android, native handles were created using the same
functions present in
<a href="https://android.googlesource.com/platform/system/core/+/master/libcutils/native_handle.c">libcutils</a>.
In Android O, these functions are now copied to the
<code>android::hardware::hidl</code> namespace or moved to the NDK. HIDL
autogenerated code serializes and deserializes these functions automatically,
without involvement from user-written code.</p>

<h3 id=ownership>Handle and file descriptor ownership</h3>
<p>When you call a HIDL interface method that passes (or returns) a
<code>hidl_handle</code> object (either top-level or part of a compound type),
the ownership of the file descriptors contained in it is as follows:</p>

<ul>
<li>When passing a <code>hidl_handle</code> object as an argument, the caller
retains ownership of the file descriptors contained in the
<code>native_handle_t</code> it wraps, and must close them when it is done with
them. Likewise, when returning a <code>hidl_handle</code> object (by passing it
into a <code>_cb</code> function), the process returning it retains ownership of
the file descriptors contained in the <code>native_handle_t</code> it wraps, and
must close them when it is done with them.</li>
<li>When receiving a <code>hidl_handle</code> object, the
<strong>transport</strong> owns the file descriptors inside the
<code>native_handle_t</code> it wraps; the receiver can use them as-is during
the transaction callback, but must clone the native handle if it wants to keep
using its file descriptors beyond the callback. The transport will automatically
<code>close()</code> the file descriptors when the transaction is done.</li>
</ul>

<p>HIDL does not support handles in Java (as Java doesn't support handles at
all).</p>

<h2 id=sized-arrays>Sized arrays</h2>
<p>For sized arrays in HIDL structs, their elements can be of any type a struct
can contain:</p>

<pre class="prettyprint">
struct foo {
uint32_t[3] x; // array is contained in foo
};
</pre>

<h2 id=strings>Strings</h2>
<p>Strings appear differently in C++ and Java, but the underlying transport
storage type is a C++ structure. For details, see
<a href="/devices/architecture/hidl-cpp/types.html">HIDL C++ Data Types</a> or
<a href="/devices/architecture/hidl-java/types.html">HIDL Java Data Types</a>.
</p>

<p class=note><strong>Note:</strong> Passing a string to or from Java through a
HIDL interface (including Java to Java) will cause character set conversions
that may not exactly preserve the original encoding.</p>

<h2 id=vec>vec&lt;T&gt; type template</h2>
<p>The <code>vec&lt;T&gt;</code> template represents a variable-sized buffer
containing instances of <code>T</code>. <code>T</code> can be any HIDL-provided
or user-defined type except handle. (A <code>vec&lt;&gt;</code> of
<code>vec&lt;T&gt;</code> will point to an array of the
<code>vec&lt;T&gt;</code> structs, not an array of the inner T buffers.)</p>

<p><code>T</code> can be one of the following:</p>
<ul>
<li>Primitive types (e.g. uint32_t)</li>
<li>Strings</li>
<li>User-defined enums</li>
<li>User-defined structs</li>
<li>Interfaces, or the <code>interface</code> keyword
(<code>vec&lt;IFoo&gt;</code>, <code>vec&lt;interface&gt;</code> is supported
only as a top-level parameter)</li>
<li>Handles</li>
<li>bitfield&lt;U&gt;</li>
<li>vec&lt;U&gt;, where U is in this list except interface (e.g.
<code>vec&lt;vec&lt;IFoo&gt;&gt;</code> is not supported)</li>
<li>U[] (sized array of U), where U is in this list except interface</li>
</ul>

<h2 id=user>User-defined types</h2>
<p>This section describes user-defined types.</p>

<h3 id=enum>Enum</h3>
<p>HIDL does not support anonymous enums. Otherside, enums in HIDL are similar
to C++11:</p>
<pre class="prettyprint">
enum name : type { enumerator , enumerator = constexpr , …  }
</pre>

<p>Enums are defined in terms of one of the primitive types in HIDL, or as an
extension of other enums. For example:</p>
<pre class="prettyprint">
enum Color : uint32_t { RED = 0, GREEN, BLUE = 2 } // GREEN == 1
</pre>

<p>Values of enums are referred to with the colon syntax (not dot syntax as
nested types). The syntax is <code>Type:VALUE_NAME</code>. No need to specify
type if the value is referred in the same enum type or child types. Example:</p>
<pre class="prettyprint">
enum Grayscale : uint32_t { BLACK = 0, WHITE = BLACK + 1 };
enum Color : Grayscale { RED = WHITE + 1 };
enum Unrelated : uint32_t { FOO = Color:RED + 1 };
</pre>

<h3 id=struct>Struct</h3>
<p>HIDL does not support anonymous structs. Otherwise, structs in HIDL are very
similar to C.</p>

<p>HIDL does not support variable-length data structures contained wholly within
a struct.  This includes the indefinite-length array that is sometimes used as
the last field of a struct in C/C++ (sometimes seen with a size of
<code>[0]</code>). HIDL <code>vec&lt;T&gt;</code> represents dynamically-sized
arrays with the data stored in a separate buffer; such instances are represented
with an instance of the <code>vec&lt;T&gt;</code> in the <code>struct</code>.
</p>

<p>Similarly, <code>string</code> can be contained in a <code>struct</code>
(associated buffers are separate). In the generated C++, instances of the HIDL
handle type are represented via a pointer to the actual native handle as
instances of the underlying data type are variable-length.</p>

<h3 id=union>Union</h3>
<p>HIDL does not support anonymous unions. Otherwise, unions are similar to C.
</p>

<p>Unions cannot contain fix-up types (pointers, file descriptors, binder
objects, etc.). They do not need special fields or associated types and are
simply copied via <code>memcpy()</code> or equivalent. An union may not directly
contain (or contain via other data structures) anything that requires setting
binder offsets (i.e., handle or binder-interface references). For example:</p>

<pre class="prettyprint">
union UnionType {
uint32_t a;
//  vec&lt;uint32_t&gt; r;  // Error: can't contain a vec&lt;T&gt;
uint8_t b;1
};
fun8(UnionType info); // Legal
</pre>

<p>Unions can also be declared inside of structs. For example:</p>
<pre class="prettyprint">
struct MyStruct {
    union MyUnion {
      uint32_t a;
      uint8_t b;
    }; // declares type but not member

    union MyUnion2 {
      uint32_t a;
      uint8_t b;
    } data; // declares type but not member
  }
</pre>

  </body>
</html>