| <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> mySecondFoo = new FooAnotherImpl(); |
| status_t status = myFoo->registerAsService(); |
| status_t anotherStatus = 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 : public 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> |