blob: c236a1719e2c25317110f5ec97e27403365a756b [file] [log] [blame]
<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 &lt;android/hardware/samples/1.0/IFoo.h&gt;
</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&lt;uint32_t&gt;);
...
}
</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&lt;void&gt; someMethod(foo my_foo, someMethod_cb _cb) {
vec&lt;uint32_t&gt; 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&lt;IFoo&gt; myFoo = new FooImpl();
::android::sp&lt;IFoo&gt; mySecondFoo = new FooAnotherImpl();
status_t status = myFoo-&gt;registerAsService();
status_t anotherStatus = mySecondFoo-&gt;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 &lt;android/hardware/samples/1.0/IFoo.h&gt;
</pre>
<p>A client can obtain an interface in two ways:</p>
<ul>
<li>Through <code>I&lt;InterfaceName&gt;::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&lt;IFoo&gt; myFoo = IFoo::getService();
sp&lt;IFoo&gt; 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&lt;V1_0::IFoo&gt; foo1_0 = V1_0::IFoo::getService();
sp&lt;V1_1::IFoo&gt; 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&lt;uint8_t&gt; 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&lt;uint32_t&gt;);
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&lt;void&gt; sendEvent(uint32_t event_id) {
// process the event from the HAL
}
Return&lt;void&gt; sendData(hidl_vec&lt;uint8_t&gt; 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&lt;IFooCallback&gt; myFooCallback = new FooCallback();
myFoo.registerCallback(myFooCallback);
</pre>
<p>The server implementing <code>IFoo</code> receives this as an
<code>sp&lt;IFooCallback&gt;</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&lt;InterfaceName&gt;::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-&gt;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&lt;::android::hidl::base::V1_0::IBase&gt;&amp; 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-&gt;unlinkToDeath(recipient);
</pre>
</body>
</html>