diff options
Diffstat (limited to 'en/devices/architecture/hidl/types.html')
-rw-r--r-- | en/devices/architecture/hidl/types.html | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/en/devices/architecture/hidl/types.html b/en/devices/architecture/hidl/types.html new file mode 100644 index 00000000..1f36262d --- /dev/null +++ b/en/devices/architecture/hidl/types.html @@ -0,0 +1,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::…</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<T></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<vec<vec<int8_t>>> multidimVector; + + vec<bool[4]> 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<T></code> and only one level deep (no +<code>vec<vec<IFoo>></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<T> 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<IMyInterface></code>. They cannot be members of +nested vecs, structs, arrays, or unions.</p> + +<h2 id=mqdescriptor>MQDescriptorSync & 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<T> type template</h2> +<p><code>bitfield<T></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<T></code> appears as the underlying type of T. For +example:</p> + +<pre class="prettyprint"> +enum Flag : uint8_t { + HAS_FOO = 1 << 0, + HAS_BAR = 1 << 1, + HAS_BAZ = 1 << 2 +}; +typedef bitfield<Flag> 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 &data[0] */ + int numInts; /* number of ints at &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<T> type template</h2> +<p>The <code>vec<T></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<></code> of +<code>vec<T></code> will point to an array of the +<code>vec<T></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<IFoo></code>, <code>vec<interface></code> is supported +only as a top-level parameter)</li> +<li>Handles</li> +<li>bitfield<U></li> +<li>vec<U>, where U is in this list except interface (e.g. +<code>vec<vec<IFoo>></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<T></code> represents dynamically-sized +arrays with the data stored in a separate buffer; such instances are represented +with an instance of the <code>vec<T></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<uint32_t> r; // Error: can't contain a vec<T> +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> |