diff options
Diffstat (limited to 'en/devices/architecture/hidl/services.html')
-rw-r--r-- | en/devices/architecture/hidl/services.html | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/en/devices/architecture/hidl/services.html b/en/devices/architecture/hidl/services.html new file mode 100644 index 00000000..647555b7 --- /dev/null +++ b/en/devices/architecture/hidl/services.html @@ -0,0 +1,219 @@ +<html devsite> + <head> + <title>Services & Data Transfer</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 how to register and discover services and how to send +data to a service by calling methods defined in interfaces in <code>.hal</code> +files.</p> + +<h2 id=register>Registering services</h2> +<p>HIDL interface servers (objects implementing the interface) can be registered +as named services. The registered name need not be related to the interface or +package name. If no name is specified, the name "default" is used; this should +be used for HALs that do not need to register two implementations of the same +interface. For example, the C++ call for service registration defined in each +interface is:</p> + +<pre class="prettyprint"> +registerAsService(); +registerAsService("another_foo_service"); // if needed +</pre> + +<p>The version of a HIDL interface is included in the interface itself. It is +automatically associated with service registration and can be retrieved via a +method call (<code>android::hardware::IInterface::getInterfaceVersion()</code>) +on every HIDL interface. Server objects need not be registered and can be passed +via HIDL method parameters to another process that will make HIDL method calls +into the server.</p> + +<h2 id=discover>Discovering services</h2> +<p>Requests by client code are made for a given interface by name and by +version, calling <code>getService</code> on the desired HAL class:</p> + +<pre class="prettyprint"> +sp<V1_1::IFooService> service = V1_1::IFooService::getService(); +sp<V1_1::IFooService> alternateService = 1_1::IFooService::getService("another_foo_service"); +</pre> + +<p>Each version of a HIDL interface is treated as a separate interface. Thus, +<code>IFooService</code> version 1.1 and <code>IFooService</code> version 2.2 +can both be registered as "foo_service" and +<code>getService("foo_service")</code> on either interface gets the registered +service for that interface. This is why, in most cases, no name parameter needs +to be supplied for registration or discovery (meaning name "default").</p> + +<p>The Vendor Interface Object also plays a part in the transport method of the +returned interface. For an interface <code>IFoo</code> in package +<code>android.hardware.foo@1.0</code>, the returned interface by +<code>IFoo::getService</code> always use the transport method declared for +<code>android.hardware.foo</code> in the device manifest if the entry exists; +and if the transport method is not available, nullptr is returned.</p> + +<h2 id=death>Service death notifications</h2> +<p>Clients who want to be notified when a service dies can receive death +notifications delivered by the framework. To receive notifications, the client +must:</p> +<ol> +<li>Subclass the HIDL class/interface <code>hidl_death_recipient</code> (in C++ +code, not in HIDL).</li> +<li>Override its <code>serviceDied()</code> method.</li> +<li>Instantiate an object of the <code>hidl_death_recipient</code> subclass. +</li> +<li>Call the <code>linkToDeath()</code> method on the service to monitor, +passing in the <code>IDeathRecipient</code>'s interface object.</li> +</ol> + +<p>A pseudocode example (C++ and Java are similar):</p> + +<pre class="prettyprint"> +class IMyDeathReceiver : hidl_death_recipient { + virtual void serviceDied(uint64_t cookie, + wp<IBase>& service) override { + log("RIP service %d!", cookie); // Cookie should be 42 + } +}; +.... +IMyDeathReceiver deathReceiver = new IMyDeathReceiver(); +m_importantService->linkToDeath(deathReceiver, 42); +</pre> + +<p>The same death recipient may be registered on multiple different services. +</p> + +<h2 id=data-transwer>Data transfer</h2> +<p>Data may be sent to a service by calling methods defined in interfaces in +<code>.hal</code> files. There are two kinds of methods:</p> + +<ul> +<li><strong>Blocking</strong> methods wait until the server has produced a +result.</li> +<li><strong>Oneway</strong> methods send data in only one direction and do not +block. If the amount of data in-flight in RPC calls exceeds implementation +limits, the calls may either block or return an error indication (behavior is +not yet determined).</li> +</ul> + +<p>A method that does not return a value but is not declared as +<code>oneway</code> is still blocking.</p> + +<p>All methods declared in a HIDL interface are called in a single direction, +either from the HAL or into the HAL. The interface does not specify which +direction it will be called in. Architectures that need calls to originate from +the HAL should provide two (or more) interfaces in the HAL package and serve the +appropriate interface from each process. The words <em>client</em> and +<em>server</em> are used with respect to the calling direction of the interface +(i.e. the HAL can be a server of one interface and a client of another +interface).</p> + +<h3 id=callbacks>Callbacks</h3> +<p>The word <em>callback</em> refers to two different concepts, distinguished by +<em>synchronous callback</em> and <em>asynchronous callback</em>.</p> + +<p><em>Synchronous callbacks</em> are used in some HIDL methods that return +data. A HIDL method that returns more than one value (or returns one value of +non-primitive type) returns its results via a callback function. If only one +value is returned and it is a primitive type, a callback is not used and the +value is returned from the method. The server implements the HIDL methods and +the client implements the callbacks.</p> + +<p><em>Asynchronous callbacks</em> allow the server of a HIDL interface to +originate calls. This is done by passing an instance of a second interface +through the first interface. The client of the first interface must act as the +server of the second. The server of the first interface can call methods on the +second interface object. For example, a HAL implementation may send information +asynchronously back to the process that is using it by calling methods on an +interface object created and served by that process. Methods in interfaces used +for asynchronous callback may be blocking (and may return values to the caller) +or <code>oneway</code>. For an example, see "Asynchronous callbacks" in +<a href="/devices/architecture/hidl-cpp/interfaces.html">HIDL C++</a>.</p> + +<p>To simplify memory ownership, method calls and callbacks take only +<code>in</code> parameters and do not support <code>out</code> or +<code>inout</code> parameters.</p> + +<h3 id=limits>Per-transaction limits</h3> +<p>Per-transaction limits may be imposed on the amount of data sent in HIDL +methods and callbacks. The limits are yet to be determined but may be as small +as 4K. Calls exceeding these limits return failure immediately. Another +limitation is the resources available to the HIDL infrastructure to handle +multiple simultaneous transactions. Multiple transactions can be in-flight +simultaneously due to multiple threads or processes sending calls to a process +or multiple <code>oneway</code> calls that are not handled quickly by the +receiving process.</p> + +<p>In a well-designed interface, exceeding these resource limitations should not +happen; if it does, the call which exceeded them may either block until +resources become available or signal a transport error. Each occurrence of +exceeding per-transaction limits or overflowing HIDL implementation resources by +aggregate in-flight transactions is logged to facilitate debugging.</p> + +<h3 id=method-implement>Method implementations</h3> +<p>HIDL generates header files declaring the necessary types, methods, and +callbacks in the target language (C++ or Java). The prototype of HIDL-defined +methods and callbacks is the same for both client and server code. The HIDL +system provides <strong>proxy</strong> implementations of the methods on the +caller side that organize the data for IPC transport, and <strong>stub</strong> +code on the callee side that passes the data into developer implementations of +the methods.</p> + +<p>The caller of a function (HIDL method or callback) has ownership of the data +structures passed into the function, and retains ownership after the call; in +all cases the callee does not need to free or release the storage.</p> + +<ul> +<li>In C++, the data may be read-only (attempts to write to it may cause a +segmentation fault) and are valid for the duration of the call. The client can +deep-copy the data to propagate it beyond the call.</li> +<li>In Java, the code receives a local copy of the data (a normal Java object), +which it may keep and modify or allow to be garbage-collected.</li> +</ul> + +<h3 id=non-rpc>Non-RPC data transfer</h3> +<p>HIDL has two ways to transfer data without using an RPC call: shared +memory and a Fast Message Queue (FMQ), both supported only in C++.</p> + +<ul> +<li><strong>Shared memory</strong>. The built-in HIDL type <code>memory</code> +is used to pass an object representing shared memory that has been allocated. +Can be used in a receiving process to map the shared memory.</li> +<li><strong>Fast Message Queue (FMQ)</strong>. HIDL provides a templated message +queue type that implements no-wait message-passing. It does not use the kernel +or scheduler in passthrough or binderized mode (inter-device communication will +not have these properties). Typically, the HAL sets up its end of the queue, +creating an object that can be passed through RPC via a parameter of built-in +HIDL type <code>MQDescriptorSync</code> or <code>MQDescriptorUnsync</code>. This +object can be used by the receiving process to set up the other end of the queue. +<ul> +<li><em>Sync</em> queues are not allowed to overflow, and can only have one +reader.</li> +<li><em>Unsync</em> queues are allowed to overflow, and can have many readers, +each of which must read data in time or lose it.</li> +</ul> +Neither type is allowed to underflow (read from an empty queue will fail), and +each type can only have one writer.</li></ul> + +<p>For more details on FMQ, see +<a href="/devices/architecture/hidl/fmq.html">Fast Message Queue (FMQ)</a>.</p> + + </body> +</html> |