diff options
author | Android Partner Docs <noreply@android.com> | 2017-08-22 10:41:24 -0700 |
---|---|---|
committer | Clay Murphy <claym@google.com> | 2017-08-22 15:01:44 -0700 |
commit | f16c42333aa6b2de30a344dd68246d4a33d93e7d (patch) | |
tree | 311af599312cacb21c888aeae828cae59b0d64a1 /en/devices/architecture/hidl-cpp | |
parent | 04426e67ca3ee557a0083f9b3c6ba789021bd7a0 (diff) | |
download | source.android.com-f16c42333aa6b2de30a344dd68246d4a33d93e7d.tar.gz |
Docs: Changes to source.android.com
- 166080694 Devsite localized content from translation request a3d5a7... by Android Partner Docs <noreply@android.com>
- 166079245 Remove duplicate TOC entry to oob-users.html. by mheco <mheco@google.com>
- 166002955 Update builds for Oreo by Android Partner Docs <noreply@android.com>
- 165977566 Fixing bad conversion by hvm <hvm@google.com>
- 165977199 Edit links to point to public source files in AOSP. by cqn <cqn@google.com>
- 165962883 Add codename to CTS downloads page. by gdimino <gdimino@google.com>
- 165955117 Integration of O branch into mainline. by gdimino <gdimino@google.com>
- 165638251 Update July public Android security bulletin to remove QC... by Android Partner Docs <noreply@android.com>
- 165638198 Update June public Android security bulletin to remove QC... by Android Partner Docs <noreply@android.com>
- 165638174 Update May public Android security bulletin to remove QC ... by Android Partner Docs <noreply@android.com>
- 165638096 Update April public Android security bulletin to remove Q... by Android Partner Docs <noreply@android.com>
- 165528993 Update to Keymaster 2 and remove requirements language by daroberts <daroberts@google.com>
- 165511119 Add Bluetooth verification / debug information by cqn <cqn@google.com>
- 165491345 Fixed link broken by file rename. by cqn <cqn@google.com>
- 165381648 Fixed broken image paths and renamed HCI Requirements file. by cqn <cqn@google.com>
- 165365185 Created high-level Bluetooth directory and added HTML ver... by cqn <cqn@google.com>
- 165335694 Devsite localized content from translation request 66a39c... by Android Partner Docs <noreply@android.com>
- 165246927 Update August 2017 bulletin with CVE-2017-0687 by daroberts <daroberts@google.com>
PiperOrigin-RevId: 166080694
Change-Id: I2d3a8d77fa6a66c2099f13ba2e864545328fd17a
Diffstat (limited to 'en/devices/architecture/hidl-cpp')
-rw-r--r-- | en/devices/architecture/hidl-cpp/functions.html | 153 | ||||
-rw-r--r-- | en/devices/architecture/hidl-cpp/index.html | 132 | ||||
-rw-r--r-- | en/devices/architecture/hidl-cpp/interfaces.html | 271 | ||||
-rw-r--r-- | en/devices/architecture/hidl-cpp/packages.html | 202 | ||||
-rw-r--r-- | en/devices/architecture/hidl-cpp/types.html | 323 |
5 files changed, 1081 insertions, 0 deletions
diff --git a/en/devices/architecture/hidl-cpp/functions.html b/en/devices/architecture/hidl-cpp/functions.html new file mode 100644 index 00000000..5d52b31d --- /dev/null +++ b/en/devices/architecture/hidl-cpp/functions.html @@ -0,0 +1,153 @@ +<html devsite> + <head> + <title>Functions</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>Functions in a HIDL interface are mapped to methods in the autogenerated +<code>IFoo</code> C++ class declaration. The name of each function remains the +same in C++; the following sections describe how HIDL arguments and return +values are translated to C++.</p> + +<h2 id=parameters>Function parameters</h2> +<p>The arguments listed in the <code>.hal</code> file map to C++ data types. +Arguments that do not map to a primitive C++ type are passed by const +reference.</p> + +<p>For every HIDL function that has a return value (has a <code>generates</code> +statement), the C++ parameter list for that function has an additional argument: +a callback function that is called with the return values of the HIDL function. +There is <strong>one exception</strong>: If the <code>generates</code> clause +contains a single parameter that directly maps to a C++ primitive, callback +<em>elision</em> is used (the callback is removed and the return value is +returned from the function through a normal <code>return</code> statement).</p> + +<h2 id=return-values>Function return values</h2> +<p>The following functions have return values.</p> + +<h3 id=transport>Transport errors and return type</h3> +<p>The <code>generates</code> statement can result in three types of function +signatures:</p> + +<ul> +<li>For only one return value that is a C++ primitive, the +<code>generates</code> return value is returned by value from the function in a +<code>Return<T></code> object.</li> +<li>For more complicated cases, the <code>generates</code> return value(s) are +returned through the callback parameter provided with the function call itself, +and the function returns <code>Return<void></code>.</li> +<li>For when no <code>generates</code> statement exists, the function returns +<code>Return<void></code>.</li> +</ul> + +<p>RPC calls can occasionally encounter transport errors, e.g. when the server +dies, when transport resources are insufficient to complete the call, or when +the parameters passed do not permit completing the call (such as missing a +required callback function). <code>Return</code> objects store transport error +indications as well as a <code>T</code> value (except +<code>Return<void></code>).</p> + +<p>As the client-side and server-side functions have the same signature, the +server-side function must return a <code>Return</code> type even though its +implementation does not signal transport errors. <code>Return<T></code> +objects are constructed with <code>Return(myTValue)</code> (or can be implicitly +constructed from <code>mTValue</code>, such as in <code>return</code> +statements) and <code>Return<void></code> objects are constructed with +<code>Void()</code>.</p> + +<p><code>Return<T></code> objects have implicit conversion to and from +their <code>T</code> value. The <code>Return</code> object can be checked for +transport errors by calling its <code>isOk()</code> method. This check is not +required; however, if an error occurs and is not checked by the time the +<code>Return</code> object is destroyed, or a <code>T</code> value conversion is +attempted, the client process will be killed and an error logged. If +<code>isOk()</code> indicates a transport error or a call failure due to a logic +error in developer code (such as passing <code>nullptr</code> as a synchronous +callback), then <code>description()</code> can be called on the Return object to +return a string suitable for logging. In such cases, there is no way to +determine how much code may have executed on the server as a result of the +failed call. The method <code>isDeadObject()</code> is also provided. This +method indicates that <code>!isOk()</code> is because the remote object has +crashed or no longer exists. <code>isDeadObject()</code> always implies +<code>!isOk()</code>.</p> + +<h3 id=return-by>Return by value</h3> +<p>If the <code>generates</code> statement maps to a single C++ primitive, no +callback parameter is in the parameter list. Instead, an implementation provides +the return value <code>T</code> in a <code>Return<T></code> object, which +can be implicitly generated from the primitive type <code>T</code>. For +example:</p> + +<pre class="prettyprint"> +Return<uint32_t> someMethod() { + uint32_t return_data = ...; // Compute return_data + return return_data; +}; +</pre> + +<p>The method <code>Return<*>::withDefault</code> is also provided. This +method provides a value in cases where the return value is <code>!isOk()</code>. +This method also automatically marks the return object as okay so the client +process will not be killed.</p> + +<h3 id=return-callback>Return using callback parameter</h3> +<p>A callback can pass the return value of the HIDL function back to the caller. +The prototype of the callback is a <code>std::function</code> object with +parameters (taken from the <code>generates</code> statement) mapped to C++ +types. Its return value is void—the callback itself doesn't return a value.</p> + +<p>The return value of a C++ function with a callback parameter has type +<code>Return<void></code>. The server implementation is responsible only +for providing the return value. As the return values are already transferred +using the callback, the <code>T</code> template parameter is <code>void</code>: +</p> + +<pre class="prettyprint"> +Return<void> someMethod(someMethod_cb _cb); +</pre> + +<p>From their C++ implementation, server implementations should return +<code>Void()</code>, which is a static inlined function returning a +<code>Return<void></code> object. Example of a typical server method +implementation with a callback parameter:</p> + +<pre class="prettyprint"> +Return<void> someMethod(someMethod_cb _cb) { + // Do some processing, then call callback with return data + hidl_vec<uint32_t> vec = ... + _cb(vec); + return Void(); +}; +</pre> + +<h2 id=no-return>Functions without return values</h2> +<p>The C++ signature of a function without a <code>generates</code> statement +will not have a callback parameter in the parameter list. Its return type will +be <code>Return<void>.</code></p> + +<h2 id=oneway>Oneway functions</h2> +<p>Functions marked with the <code>oneway</code> keyword are asynchronous +functions (clients won't block on their execution) and do not have return +values. The C++ signature of a <code>oneway</code> function will not have a +callback parameter in the parameter list, and its C++ return value will be +<code>Return<void></code>.</p> + + </body> +</html> diff --git a/en/devices/architecture/hidl-cpp/index.html b/en/devices/architecture/hidl-cpp/index.html new file mode 100644 index 00000000..af685400 --- /dev/null +++ b/en/devices/architecture/hidl-cpp/index.html @@ -0,0 +1,132 @@ +<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 re-architects the Android OS to define clear interfaces between the +device-independent Android platform and device- and vendor-specific code. +Android already defines many such interfaces in the form of HAL interfaces, +defined as C headers in <code>hardware/libhardware</code>. HIDL replaces these +HAL interfaces with stable, versioned interfaces, which can be client- and +server-side HIDL interfaces in C++ (described below) or +<a href="/devices/architecture/hidl-java/index.html">Java</a>.</p> + +<p>The pages in this section describe C++ implementations of HIDL interfaces, +including details about the files auto-generated from the HIDL <code>.hal</code> +files by the <code>hidl-gen</code> compiler, how these files are packaged, and +how to integrate these files with the C++ code that uses them.</p> + +<h2 id=client-server>Client & server implementations</h2> +<p>HIDL interfaces have client and server implementations:</p> + +<ul> +<li>A <strong>client</strong> of a HIDL interface is the code that uses the +interface by calling methods on it.</li> +<li>A <strong>server</strong> is an implementation of a HIDL interface that +receives calls from clients and returns results (if necessary).</li> +</ul> + +<p>In transitioning from <code>libhardware</code> HALs to HIDL HALs, the HAL +implementation becomes the server and the process calling into the HAL becomes +the client. Default implementations can serve both passthrough and binderized +HALs, and can change over time:</p> + +<p><img src="../images/treble_cpp_legacy_hal_progression.png"></p> +<p><strong>Figure 1.</strong> Development progression for legacy HALs.</p> + +<h2>Creating the HAL client</h2> +<p>Start by including the HAL libraries in the 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>Next, include the HAL header files:</p> + +<pre class="prettyprint"> +#include <android/hardware/nfc/1.0/IFoo.h> +… +// in code: +sp<IFoo> client = IFoo::getService(); +client->doThing(); +</pre> + +<h2>Creating the HAL server</h2> +<p>To create the HAL implementation, you must have the <code>.hal</code> files +that represent your HAL and have already generated makefiles for your HAL using +<code>-Lmakefile</code> or <code>-Landroidbp</code> on <code>hidl-gen</code> +(<code>./hardware/interfaces/update-makefiles.sh</code> does this for internal +HAL files and is a good reference). When transferring over HALs from +<code>libhardware</code>, you can do a lot of this work easily using c2hal.</p> + +<p>To create the necessary files to implement your HAL:</p> + +<pre class="prettyprint"> +PACKAGE=android.hardware.nfc@1.0 +LOC=hardware/interfaces/nfc/1.0/default/ +make hidl-gen -j64 +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>For the HAL to work in passthrough mode (for legacy devices), you must have +the function <em>HIDL_FETCH_IModuleName</em> residing in +<code>/system/lib(64)?/hw/android.hardware.package@3.0-impl(-$OPTIONAL_IDENTIFIER).so</code> +where <code>$OPTIONAL_IDENTIFIER</code> is a string identifying the passthrough +implementation. The passthrough mode requirements are met automatically by the +above commands, which also create the <code>android.hardware.nfc@1.0-impl</code> +target.</p> + +<p>Next, fill out the stubs with functionality and setup a daemon. Example +daemon code (supporting passthrough):</p> + +<pre class="prettyprint"> +#include <hidl/LegacySupport.h> + +int main(int /* argc */, char* /* argv */ []) { + return defaultPassthroughServiceImplementation<INfc>("nfc"); +} +</pre> + +<p><code>defaultPassthroughServiceImplementation</code> will +<code>dlopen()</code> the provided <code>-impl</code> library and provide it as +a binderized service. Example daemon code (for pure binderized service):</p> + +<pre class="prettyprint"> +int main(int /* argc */, char* /* argv */ []) { + Nfc nfc = new Nfc(); + nfc->registerAsService(); +} +</pre> + +<p>This daemon should live in <code>$PACKAGE + "-service"</code> (for example, +<code>android.hardware.nfc@1.0-service</code>). The +<a href="/security/selinux/device-policy.html">sepolicy</a> for a specific class +of HALs is the attribute <code>hal_<module></code> (for instance, +<code>hal_nfc)</code>. This attribute must be applied to the daemon that runs a +particular HAL (if the same process serves multiple HALs, multiple attributes +can be applied to it).</p> + +</body> +</html> diff --git a/en/devices/architecture/hidl-cpp/interfaces.html b/en/devices/architecture/hidl-cpp/interfaces.html new file mode 100644 index 00000000..5047e8d0 --- /dev/null +++ b/en/devices/architecture/hidl-cpp/interfaces.html @@ -0,0 +1,271 @@ +<html devsite> + <head> + <title>Interfaces</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>Every interface defined in a HIDL package has its own autogenerated C++ class +inside its package's namespace. Clients and servers deal with interfaces in +different ways:</p> + +<ul> +<li><strong>Servers</strong> implement interfaces.</li> +<li><strong>Clients</strong> call methods on interfaces.</li> +</ul> + +<p>Interfaces can either be registered by name by the server or passed as +parameters to HIDL-defined methods. For example, framework code may serve an +interface to receive asynchronous messages from the HAL and pass that interface +directly to the HAL without registering it.</p> + +<h2 id=server>Server implementation</h2> +<p>A server implementing the <code>IFoo</code> interface must include the +<code>IFoo</code> header file that was autogenerated:</p> + +<pre class="prettyprint"> +#include <android/hardware/samples/1.0/IFoo.h> +</pre> + +<p>The header is automatically exported by the shared library of the +<code>IFoo</code> interface to link against. Example <code>IFoo.hal</code>:</p> + +<pre class="prettyprint"> +// IFoo.hal +interface IFoo { + someMethod() generates (vec<uint32_t>); + ... +} +</pre> + +<p>Example skeleton for a server implementation of the IFoo interface:</p> + +<pre class="prettyprint"> +// From the IFoo.h header +using android::hardware::samples::V1_0::IFoo; + +class FooImpl : public IFoo { + Return<void> someMethod(foo my_foo, someMethod_cb _cb) { + vec<uint32_t> return_data; + // Compute return_data + _cb(return_data); + return Void(); + } + ... +}; +</pre> + +<p>To make the implementation of a server interface available to a client, you +can:</p> + +<ol> +<li><strong>Register</strong> the interface implementation with the +<code>hwservicemanager</code> (see details below), +<br><br> +OR<br><br> +</li> +<li><strong>Pass</strong> the interface implementation as an argument of an +interface method (for detals, see <a href="#asynchronous">Asynchronous +callbacks</a>).</li> +</ol> + +<p>When registering the interface implementation, the +<code>hwservicemanager</code> process keeps track of registered HIDL interfaces +running on the device by name and version. Servers can register a HIDL interface +implementation by name and clients can request service implementations by name +and version. This process serves the HIDL interface +<code>android.hidl.manager@1.0::IServiceManager</code>.</p> + +<p>Each auto-generated HIDL interface header file (such as <code>IFoo.h</code>) +has a <code>registerAsService()</code> method that can be used to register the +interface implementation with the <code>hwservicemanager</code>. The only +required argument is the name of the interface implementations as clients will +use this name to retrieve the interface from the <code>hwservicemanager</code> +later:</p> + +<pre class="prettyprint"> +::android::sp<IFoo> myFoo = new FooImpl(); +::android::sp<IFoo> myFoo = new FooAnotherImpl(); +myFoo->registerAsService(); +mySecondFoo->registerAsService("another_foo"); +</pre> + +<p>The <code>hwservicemanager</code> treats the combination of +<code>[package@version::interface, instance_name]</code> as unique to enable +different interfaces (or different versions of the same interface) to register +with identical instance names without conflicts. If you call +<code>registerAsService()</code> with the exact same package version, interface, +and instance name, the <code>hwservicemanager</code> drops its reference to the +previously registered service and uses the new one.</p> + +<h2 id=client>Client implementation</h2> +<p>Just as the server does, a client must <code>#include</code> every interface +it refers to:</p> + +<pre class="prettyprint"> +#include <android/hardware/samples/1.0/IFoo.h> +</pre> + +<p>A client can obtain an interface in two ways:</p> + +<ul> +<li>Through <code>I<InterfaceName>::getService</code> (via the +<code>hwservicemanager</code>)</li> +<li>Through an interface method</li> +</ul> + +<p>Each autogenerated interface header file has a static <code>getService</code> +method that can be used to retrieve a service instance from the +<code>hwservicemanager</code>:</p> + +<pre class="prettyprint"> +// getService will return nullptr if the service can't be found +sp<IFoo> myFoo = IFoo::getService(); +sp<IFoo> myAlternateFoo = IFoo::getService("another_foo"); +</pre> + +<p>Now the client has an an <code>IFoo</code> interface, and can call methods to +it as if it were a local class implementation. In reality, the implementation +may run in the same process, a different process, or even on another device +(with HAL remoting). Because the client called <code>getService</code> on an +<code>IFoo</code> object included from version <code>1.0 </code>of the package, +the <code>hwservicemanager</code> returns a server implementation only if that +implementation is compatible with <code>1.0</code> clients. In practice, this +means only server implementations with version <code>1.n</code> (version +<code>x.(y+1)</code> of an interface must extend (inherit from) +<code>x.y</code>).</p> + +<p>Additionally the method <code>castFrom</code> is provided to cast between +different interfaces. This method works by making an IPC call to the remote +interface to make sure the underlying type is the same as the type that is being +requested. If the requested type is unavailable, then <code>nullptr</code> is +returned.</p> + +<pre class="prettyprint"> +sp<V1_0::IFoo> foo1_0 = V1_0::IFoo::getService(); +sp<V1_1::IFoo> foo1_1 = V1_1::IFoo::castFrom(foo1_0); +</pre> + +<h2 id=asynchronous>Asynchronous callbacks</h2> +<p>Many existing HAL implementations talk to asynchronous hardware, which means +they need an asynchronous way to notify clients of new events that have +occurred. A HIDL interface can be used as an asynchronous callback because HIDL +interface functions can take HIDL interface objects as parameters.</p> + +<p>Example interface file <code>IFooCallback.hal</code>:</p> + +<pre class="prettyprint"> +package android.hardware.samples@1.0; +interface IFooCallback { + sendEvent(uint32_t event_id); + sendData(hidl_vec<uint8_t> data); +} +</pre> + +<p>Example new method in <code>IFoo</code> that takes an +<code>IFooCallback</code> parameter:</p> + +<pre class="prettyprint"> +package android.hardware.samples@1.0; +interface IFoo { + struct Foo { + int64_t some_value; + Handle my_handle; + }; + + someMethod(Foo foo) generates (int32_t ret); + another_method() generates (hidl_vec<uint32_t>); + register_callback(IFooCallback callback); +}; +</pre> + +<p>The <em>client</em> using the <code>IFoo</code> interface is the +<em>server</em> of the <code>IFooCallback</code> interface; it provides an +implementation of <code>IFooCallback</code>:</p> + +<pre class="prettyprint"> +class FooCallback : public IFooCallback { + Return<void> sendEvent(uint32_t event_id) { + // process the event from the HAL + } + Return<void> sendData(hidl_vec<uint8_t> data) { + // process data from the HAL + } +}; +</pre> + +<p>It can also simply pass that over an existing instance of the +<code>IFoo</code> interface:</p> +<pre class="prettyprint"> +sp<IFooCallback> myFooCallback = new FooCallback(); +myFoo.registerCallback(myFooCallback); +</pre> + +<p>The server implementing <code>IFoo</code> receives this as an +<code>sp<IFooCallback></code> object. It can store the callback, and call +back into the client whenever it wants to use this interface.</p> + +<h2 id=death>Death recipients</h2> +<p>As service implementations can run in a different process, it can happen +that the process implementing an interface dies while the client stays alive. +Any calls on an interface object hosted in a process that has died will fail +with a transport error (<code>isOK()</code> will return false). The only way to +recover from such a failure is to request a new instance of the service by +calling <code>I<InterfaceName>::getService()</code>. This works only if +the process that crashed has restarted and re-registered its services with the +<code>servicemanager</code> (which is generally true for HAL implementations). +</p> + +<p>Instead of dealing with this reactively, clients of an interface can also +register a <em>death recipient</em> to get a notification when a service dies. +To register for such notifications on a retrieved <code>IFoo</code> interface, a +client can do the following:</p> + +<pre class="prettyprint"> +foo->linkToDeath(recipient, 1481 /* cookie */); +</pre> + +<p>The <code>recipient</code> parameter must be an implementation of the +<code>android::hardware::hidl_death_recipient</code> interface provided by HIDL, +which contains a single method <code>serviceDied()</code> that will be called +from a thread in the RPC threadpool when the process hosting the interface dies: +</p> + +<pre class="prettyprint"> +class MyDeathRecipient : android::hardware::hidl_death_recipient { + virtual void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) { + // Deal with the fact that the service died + } +} +</pre> + +<p>The <code>cookie</code> parameter contains the cookie that was passed in with +<code>linkToDeath()</code>, whereas the <code>who</code> parameter contains a +weak pointer to the object representing the service in the client. With the +sample call given above, <code>cookie</code> equals 1481, and <code>who</code> +equals <code>foo</code>.</p> + +<p>It's also possible to unregister a death recipient after registering it:</p> + +<pre class="prettyprint"> +foo->unlinkToDeath(recipient); +</pre> + + </body> +</html> diff --git a/en/devices/architecture/hidl-cpp/packages.html b/en/devices/architecture/hidl-cpp/packages.html new file mode 100644 index 00000000..2c8e096d --- /dev/null +++ b/en/devices/architecture/hidl-cpp/packages.html @@ -0,0 +1,202 @@ +<html devsite> + <head> + <title>Packages</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 class=note><strong>Note:</strong> This section uses sample <code>.hal</code> +files to illustrate how HIDL language constructs map to C++.</p> + +<p>With few exceptions, HIDL interface packages are located in +<code>hardware/interfaces</code> or the <code>vendor/</code> directory. The +<code>hardware/interfaces</code> top-level maps directly to the +<code>android.hardware</code> package namespace; the version is a subdirectory +under the package (not interface) namespace.</p> + +<p>The <code>hidl-gen</code> compiler compiles the <code>.hal</code> files into +a set of a <code>.h</code> and <code>.cpp</code> files. From these autogenerated +files a shared library that client/server implementations link against is built. +The <code>Android.bp</code> file that builds this shared library is +autogenerated by the <code>hardware/interfaces/update-makefiles.sh</code> +script. Every time you add a new package to <code>hardware/interfaces</code>, or +add/remove <code>.hal</code> files to/from an existing package, you must rerun +the script to ensure the generated shared library is up-to-date.</p> + +<p>For example, the <code>IFoo.hal</code> sample file should be located in +<code>hardware/interfaces/samples/1.0</code>. The sample +<code><strong>IFoo.hal</code></strong> file creates an IFoo interface in the +<strong>samples</strong> package:</p> + +<pre class="prettyprint"> +package android.hardware.samples@1.0; +interface IFoo { + struct Foo { + int64_t someValue; + handle myHandle; + }; + + someMethod() generates (vec<uint32_t>); + anotherMethod(Foo foo) generates (int32_t ret); +}; +</pre> + +<h2 id=generated-files>Generated files</h2> + +<p>Autogenerated files in a HIDL package are linked into a single shared +library with the same name as the package (for example, +<code>android.hardware.samples@1.0</code>). The shared library also exports a +single header, <code>IFoo.h</code>, which can be included by clients and +servers. Using the <code>hidl-gen</code> compiler with the <code>IFoo.hal</code> +interface file as an input, binderized mode has the following autogenerated +files:</p> + +<p><img src="../images/treble_cpp_compiler_generated_files.png"></p> +<p><strong>Figure 1.</strong> Files generated by compiler.</p> + +<ul> +<li><code><strong>IFoo.h</code></strong>. Describes the pure <code>IFoo</code> +interface in a C++ class; it contains the methods and types defined in the +<code>IFoo</code> interface in the <code>IFoo.hal</code> file, translated to C++ +types where necessary. <strong>Does not contain</strong> details related to the +RPC mechanism (e.g., <code>HwBinder</code>) used to implement this interface. +The class is namespaced with the package and version, e.g. +<code>::android::hardware::samples::IFoo::V1_0</code>. Both clients and servers +include this header: Clients for calling methods on it and servers for +implementing those methods.</li> +<li><code><strong>IHwFoo.h</code></strong>. Header file that contains +declarations for functions that serialize data types used in the interface. +Developers should never include his header directly (it does not contain any +classes).</li> +<li><code><strong>BpFoo.h</code></strong>. A class that inherits from +<code>IFoo</code> and describes the <code>HwBinder</code> proxy (client-side) +implementation of the interface. Developers should never refer to this class +directly.</li> +<li><code><strong>BnFoo.h</code></strong>.<strong> </strong>A class that holds a +reference to an <code>IFoo</code> implementation and describes the +<code>HwBinder</code> stub (server-side) implementation of the interface. +Developers should never refer to this class directly.</li> +<li><code><strong>FooAll.cpp</code></strong>. A class that contains the +implementations for both the <code>HwBinder</code> proxy and the +<code>HwBinder</code> stub. When a client calls an interface method, the proxy +automatically marshals the arguments from the client and sends the transaction +to the binder kernel driver, which delivers the transaction to the stub on the +other side (which then calls the actual server implementation).</li> +</ul> + +<p>The files are structured similarly to the files generated by +<code>aidl-cpp</code> (for details, see "Passthrough mode" in the +<a href="/devices/architecture/hidl/index.html">HIDL Overview</a>). The only +autogenerated file that is independent of the RPC mechanism used by HIDL is +<code>IFoo.h</code>; all other files are tied to the HwBinder RPC mechanism used +by HIDL. Therefore, client and server implementations <strong>should never +directly refer to anything other than <code>IFoo</code></strong>. To achieve +this, include only <code>IFoo.h</code> and link against the generated shared +library.</p> + +<p class=note><strong>Note</strong>: HwBinder is only one possible transport; +new transports may be added in the future.</p> + +<h2 id=link-libraries>Linking to shared libraries</h2> +<p>A client or server that uses any interface in a package must include the +shared library of that package in <strong>one (1)</strong> of the following +locations:</p> + +<ul> +<li>In <strong>Android.mk</strong>: +<pre class="prettyprint"> +LOCAL_SHARED_LIBRARIES += android.hardware.samples@1.0 +</pre> +</li> + +<li>In <strong>Android.bp</strong>: +<pre class="prettyprint"> +shared_libs: [ + /* ... */ + "android.hardware.samples@1.0", +], +</pre> +</li> +</ul> + +<p>For specific libraries:</p> + +<table> + +<tr> +<th><code>libhidlbase</code></th> +<td>Includes standard HIDL data-types. Unless your interface consists only of +primitives that map directly to C++ primitives, you must also link this library: +<pre class="prettyprint"> +LOCAL_SHARED_LIBRARIES += libhidlbase +</pre> +</td> +</tr> + +<tr> +<th><code>libhidltransport</code></th> +<td>Handles the transport of HIDL calls over different RPC/IPC mechanisms. You +must always link this library: +<pre class="prettyprint"> +LOCAL_SHARED_LIBRARIES += libhidltransport +</pre> +</td> +</tr> + +<tr> +<th><code>libhwbinder</code></th> +<td>You must also link to this library: +<pre class="prettyprint"> +LOCAL_SHARED_LIBRARIES += libhwbinder +</pre> +</td> +</tr> + +<tr> +<th><code>libfmq</code></th> +<td>To use Fast Message Queue IPC, you must also link to this library. +<pre class="prettyprint"> +LOCAL_SHARED_LIBRARIES += libfmq +</pre> +</td> +</tr> + +</tbody> +</table> + +<h2 id=namespaces>Namespaces</h2> +<p>HIDL functions and types such as <code>Return<T></code> and +<code>Void()</code> are declared in namespace <code>::android::hardware</code>. +The C++ namespace of a package is determined by the package name and version. +For example, a package <strong>mypackage</strong> with version 1.2 under +<code>hardware/interfaces</code> has the following qualities:</p> + +<ul> +<li><strong>C++ namespace</strong> is +<code>::android::hardware::mypackage::V1_2</code></li> +<li><strong>Fully qualified name </strong>of <code>IMyInterface</code> in that +package is: <code>::android::hardware::mypackage::V1_2::IMyInterface</code>. +(<code>IMyInterface</code> is an identifier, not part of the namespace).</li> +<li><strong>Types</strong> defined in the package's <code>types.hal</code> file +are identified as: +<code>::android::hardware::mypackage::V1_2::MyPackageType</code></li> +</ul> + + </body> +</html> diff --git a/en/devices/architecture/hidl-cpp/types.html b/en/devices/architecture/hidl-cpp/types.html new file mode 100644 index 00000000..1d93df74 --- /dev/null +++ b/en/devices/architecture/hidl-cpp/types.html @@ -0,0 +1,323 @@ +<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>HIDL data declarations generate C++ standard-layout data structures. These +structures can be placed anywhere that feels natural (on the stack, at file or +global scope, or on the heap) and can be composed in the same fashion. Client +code calls HIDL proxy code passing in const references and primitive types, +while the stub and proxy code hides the details of serialization.</p> + +<p class=note><strong>Note:</strong> At no point is developer-written code +required to explicitly serialize or deserialize data structures.</p> + +<p>The table below maps HIDL primitives to C++ data types:</p> + +<table> +<tbody> +<tr> +<th><strong>HIDL Type</strong></th> +<th><strong>C++ Type</strong></th> +<th><strong>Header/Library</strong></th> +</tr> + +<tr> +<td><pre>enum</pre></td> +<td><pre>enum class</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>uint8_t..uint64_t</pre></td> +<td><pre>uint8_t..uint64_t</pre></td> +<td><pre><stdint.h></pre></td> +</tr> + +<tr> +<td><pre>int8_t..int64_t</pre></td> +<td><pre>int8_t..int64_t</pre></td> +<td><pre><stdint.h></pre></td> +</tr> + +<tr> +<td><pre>float</pre></td> +<td><pre>float</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>double</pre></td> +<td><pre>double</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>vec<T></pre></td> +<td><pre>hidl_vec<T></pre></td> +<td><pre>libhidlbase</pre></td> +</tr> + +<tr> +<td><pre>T[S1][S2]...[SN]</pre></td> +<td><pre>T[S1][S2]...[SN]</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>string</pre></td> +<td><pre>hidl_string</pre></td> +<td><pre>libhidlbase</pre></td> +</tr> + +<tr> +<td><pre>handle</pre></td> +<td><pre>hidl_handle</pre></td> +<td><pre>libhidlbase</pre></td> +</tr> + +<tr> +<td><pre>opaque</pre></td> +<td><pre>uint64_t</pre></td> +<td><pre><stdint.h></pre> +</td> +</tr> + +<tr> +<td><pre>struct</pre></td> +<td><pre>struct</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>union</pre></td> +<td><pre>union</pre></td> +<td></td> +</tr> + +<tr> +<td><pre>fmq_sync</pre></td> +<td><pre>MQDescriptorSync</pre></td> +<td><pre>libhidlbase</pre></td> +</tr> + +<tr> +<td><pre>fmq_unsync</pre></td> +<td><pre>MQDescriptorUnsync</pre></td> +<td><pre>libhidlbase</pre></td> +</tr> + +</tbody> +</table> + +<p>The sections below describe data types in more detail.</p> + +<h2 id=enum>enum</h2> +<p>An enum in HIDL becomes an enum in C++. For example:</p> +<pre class="prettyprint"> +enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 }; +</pre> + +<p>… becomes:</p> +<pre class="prettyprint"> +enum class Mode : uint8_t { WRITE = 1, READ = 2 }; +</pre> + +<h2 id=bitfield>bitfield<T></h2> +<p><code>bitfield<T></code> (where <code>T</code> is a user-defined enum) +becomes the underlying type of that enum in C++. In the above example, +<code>bitfield<Mode></code> becomes <code>uint8_t</code>.</p> + +<h2 id=vect>vec<T></h2> +<p>The <code>hidl_vec<T></code> class template is part of +<code>libhidlbase</code> and can be used to pass a vector of any HIDL type with +an arbitrary size. The comparable fixed size container is +<code>hidl_array</code>. A <code>hidl_vec<T></code> can also be +initialized to point to an external data buffer of type <code>T</code>, using +the <code>hidl_vec::setToExternal()</code> function.</p> + +<p>In addition to emitting/inserting the struct appropriately in the generated +C++ header, the use of <code>vec<T></code> generates some convenience +functions to translate to/from <code>std::vector</code> and bare <code>T</code> +pointers. If the <code>vec<T></code> is used as a parameter, the function +using it will be overloaded (two prototypes will be generated) to accept and +pass both the HIDL struct and a <code>std::vector<T></code> type for that +parameter.</p> + +<h2 id=arrays>array</h2> +<p>Constant arrays in hidl are represented by the <code>hidl_array</code> class +in <code>libhidlbase</code>. A <code>hidl_array<T, S1, S2, …, +SN></code> represents an N dimensional fixed size array +<code>T[S1][S2]…[SN]</code>.</p> + +<h2 id=string>string</h2> +<p>The <code>hidl_string</code> class (part of <code>libhidlbase</code>) can be +used to pass strings over HIDL interfaces and is defined in +<code>/system/libhidl/base/include/hidl/HidlSupport.h</code>. The first storage +location in the class is a pointer to its character buffer.</p> + +<p><code>hidl_string</code> knows how to convert to and from +<code>std::string and char*</code> (C-style string) using +<code>operator=</code>, implicit casts, and <code>.c_str()</code> function. +HIDL string structs has the appropriate copy constructors and assignment +operators to:</p> + +<ul> +<li>Load the HIDL string from an <code>std::string</code> or a C string.</li> +<li>Create a new <code>std::string</code> from a HIDL string.</li> +</ul> + +<p>In addition, HIDL strings have conversion constructors so C strings +(<code>char *</code>) and C++ strings (<code>std::string</code>) can be used on +methods that take a HIDL string.</p> + +<h2 id=struct>struct</h2> +<p>A <code>struct</code> in HIDL can contain only fixed-size data types and no +functions. HIDL struct definitions map directly to standard-layout +<code>struct</code>s in C++, ensuring that <code>struct</code>s have a +consistent memory layout. A struct can include HIDL types, including +<code>handle</code>, <code>string</code>, and <code>vec<T></code>, that +point to separate variable-length buffers.</p> + +<h2 id=handle>handle</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 being used to look +up allocated memory within a process. Otherwise, bad handles may cause bad +memory access or memory corruption.</p> + +<p>The <code>handle</code> type is represented by the <code>hidl_handle</code> +structure in C++, which is a simple wrapper around a pointer to a +<code>const native_handle_t</code> object (this has been present in Android for +a long time).</p> + +<pre> +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>By default, <code>hidl_handle</code> does <strong>not</strong> take ownership +of the <code>native_handle_t</code> pointer it wraps. It merely exists to safely +store a pointer to a <code>native_handle_t</code> such that it can be used in +both 32- and 64-bit processes.</p> + +<p>Scenarios in which the <code>hidl_handle</code> does own its enclosed file +descriptors include:</p> +<ul> +<li>Following a call to the <code>setTo(native_handle_t* handle, bool +shouldOwn)</code> method with the <code>shouldOwn</code> parameter set to +<code>true</code></li> +<li>When the <code>hidl_handle</code> object is created by copy construction +from another <code>hidl_handle</code> object</li> +<li>When the <code>hidl_handle</code> object is copy-assigned from another +<code>hidl_handle</code> object</li> +</ul> + +<p><code>hidl_handle</code> provides both implicit and explicit conversions +to/from <code>native_handle_t* </code>objects. The main use for the +<code>handle</code> type in HIDL is to pass file descriptors over HIDL +interfaces. A single file descriptor is therefore represented by a +<code>native_handle_t</code> with no <code>int</code>s and a single +<code>fd</code>. If the client and server live in a different process, the RPC +implementation will automatically take care of the file descriptor to ensure +both processes can operate on the same file.</p> + +<p>Although a file descriptor received in a <code>hidl_handle</code> by a +process will be valid in that process, it will not persist beyond the receiving +function (it will be closed once the function returns). A process that wants to +retain persistent access to the file descriptor must <code>dup()</code> the +enclosed file descriptors, or copy the entire <code>hidl_handle</code> object. +</p> + +<h2 id=memory>memory</h2> +<p>The HIDL <code>memory</code> type maps to the <code>hidl_memory</code> class +in <code>libhidlbase</code>, which represents unmapped shared memory. This is +the object that must be passed between processes to share memory in HIDL. To +use shared memory:</p> + +<ol> +<li>Obtain an instance of <code>IAllocator</code> (currently only instance +"ashmem" is available) and use it to allocate shared memory.</li> +<li><code>IAllocator::allocate()</code> returns a <code>hidl_memory</code> +object that can be passed through HIDL RPC and be mapped into a process using +<code>libhidlmemory</code>'s <code>mapMemory</code> function.</li> +<li><code>mapMemory</code> returns a reference to an +<code>sp<IMemory></code> object that can be used to access the memory. +(<code>IMemory</code> and <code>IAllocator</code> are defined in +<code>android.hidl.memory@1.0</code>.)</li> +</ol> + +<p>An instance of <code>IAllocator</code> can be used to allocate memory:</p> +<pre class="prettyprint"> +#include <android/hidl/allocator/1.0/IAllocator.h> +#include <android/hidl/memory/1.0/IMemory.h> +#include <hidlmemory/mapping.h> +using ::android::hidl::allocator::V1_0::IAllocator; +using ::android::hidl::memory::V1_0::IMemory; +using ::android::hardware::hidl_memory; +.... + sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem"); + ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) { + if (!success) { /* error */ } + // now you can use the hidl_memory object 'mem' or pass it around + })); +</pre> + +<p>Actual changes to the memory must be done through an <code>IMemory</code> +object, either on the side that created <code>mem</code> or on the side that +receives it over HIDL RPC.</p> + +<pre class="prettyprint"> +// Same includes as above + +sp<IMemory> memory = mapMemory(mem); +void* data = memory->getPointer(); +memory->update(); +// update memory however you wish after calling update and before calling commit +data[0] = 42; +memory->commit(); +// … +memory->update(); // the same memory can be updated multiple times +// … +memory->commit(); +</pre> + +<h2 id=interfaces>interface</h2> +<p>Interfaces can be passed as objects. The word <em>interface</em> can be used +as syntactic sugar for the type <code>android.hidl.base@1.0::IBase</code>; +in addition, the current interface and any imported interfaces will be defined +as a type.</p> + +<p>Variables that hold Interfaces should be strong pointers: +<code>sp<IName></code>. HIDL functions that take interface parameters +will convert raw pointers to strong pointers, causing non-intuitive behavior +(the pointer can be cleared unexpectedly). To avoid problems, always store HIDL +interfaces as a <code>sp<></code>.</p> + + </body> +</html> |