In Android 8.0 the Android OS was re-architected to define clear interfaces
between the device-independent Android platform, and device- and vendor-specific
code. Android already defined many such interfaces in the form of HAL
interfaces, defined as C headers in hardware/libhardware
. HIDL
replaced these HAL interfaces with stable, versioned interfaces, which can
either be in Java (described below) or be client- and server-side HIDL
interfaces in C++.
HIDL interfaces are intended to be used primarily from native code, and as a result HIDL is focused on the auto-generation of efficient code in C++. However, HIDL interfaces must also be available for use directly from Java, as some Android subsystems (such as Telephony) have Java HIDL interfaces.
The pages in this section describe the Java frontend for HIDL interfaces, detail how to create, register, and use services, and explain how HALs and HAL clients written in Java interact with the HIDL RPC system.
Client example
This is an example of a client for an interface IFoo
in package
android.hardware.foo@1.0
that is registered as service name
default
and an additional service with the custom service name
second_impl
.
Add libraries
You need to add dependencies on the corresponding HIDL stub library if you want to use it. Usually, this is a static library:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
If you know that you're already pulling in dependencies on these libraries, you can also use shared linkage:
// in Android.bp libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
Additional considerations for adding libraries in Android 10
If you have a system or vendor app that targets Android 10 or higher,
you can statically include these libraries. You can also use (only) HIDL classes
from custom JARs installed on the device with stable Java APIs made available
using the existing uses-library
mechanism for system apps. The
latter approach saves space on the device. For more details, see Implementing Java SDK Library. For
older apps, the old behavior is preserved.
Starting in Android 10, "shallow" versions of these libraries
are also available. These include the class in question but don't include any
of the dependent classes. For instance,
android.hardware.foo-V1.0-java-shallow
includes classes in the foo
package, but doesn't include classes in
android.hidl.base-V1.0-java
, which contains the base class of all
HIDL interfaces. If you're creating a library that already has the preferred
interface's base classes available as a dependency, you can use the following:
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java-shallow", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow
HIDL base and manager libraries are also no longer available on the boot
classpath for apps (previously, they were sometimes used as hidden API, due to
Android's delegate-first classloader). Instead, they've been moved into a new
namespace with jarjar
, and apps which use these (necessarily priv
apps) must have their own separate copies. Modules on the boot classpath using
HIDL must use the shallow variants of these Java libraries and to add
jarjar_rules: ":framework-jarjar-rules"
to their
Android.bp
to use the version of these libraries that exists
in the boot classpath.
Modify your Java source
There's only one version (@1.0
) of this service, so this code
retrieves only that version. See
interface extensions
for how to handle multiple different versions of the service.
import android.hardware.foo.V1_0.IFoo; ... // retry to wait until the service starts up if it is in the manifest IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IFoo anotherServer = IFoo.getService("second_impl", true /* retry */); server.doSomething(…);
Provide a service
Framework code in Java might need to serve interfaces to receive asynchronous callbacks from HALs.
For the IFooCallback
interface in version 1.0 of the
android.hardware.foo
package, you can implement your interface in
Java using the following steps:
- Define your interface in HIDL.
- Open
/tmp/android/hardware/foo/IFooCallback.java
as a reference. - Create a new module for your Java implementation.
- Examine the abstract class
android.hardware.foo.V1_0.IFooCallback.Stub
, then write a new class to extend it and implement the abstract methods.
View auto-generated files
To view the automatically generated files, run:
hidl-gen -o /tmp -Ljava \ -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
These commands generate the directory
/tmp/android/hardware/foo/1.0
. For the file
hardware/interfaces/foo/1.0/IFooCallback.hal
, this generates the
file /tmp/android/hardware/foo/1.0/IFooCallback.java
, which
encapsulates the Java interface, the proxy code, and the stubs (both proxy and
stubs conform to the interface).
-Lmakefile
generates the rules that run this command at build
time and allow you to include
android.hardware.foo-V1.0-java
and link against the
appropriate files. A script that automatically does this for a project full of
interfaces can be found at hardware/interfaces/update-makefiles.sh
.
The paths in this example are relative; hardware/interfaces can be a temporary
directory under your code tree to enable you to develop a HAL prior to
publishing it.
Run a service
The HAL provides the IFoo
interface, which must make asynchronous
callbacks to the framework over the IFooCallback
interface. The
IFooCallback
interface isn't registered by name as a discoverable
service; instead, IFoo
must contain a method such as
setFooCallback(IFooCallback x)
.
To set up IFooCallback
from version 1.0 of the
android.hardware.foo
package, add
android.hardware.foo-V1.0-java
to Android.mk
. The code
to run the service is:
import android.hardware.foo.V1_0.IFoo; import android.hardware.foo.V1_0.IFooCallback.Stub; .... class FooCallback extends IFooCallback.Stub { // implement methods } .... // Get the service from which you will be receiving callbacks. // This also starts the threadpool for your callback service. IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available .... // This must be a persistent instance variable, not local, // to avoid premature garbage collection. FooCallback mFooCallback = new FooCallback(); .... // Do this once to create the callback service and tell the "foo-bar" service server.setFooCallback(mFooCallback);
Interface extensions
Assuming a given service implements the IFoo
interface across all
devices, it's possible that on a particular device the service might provide
additional capabilities implemented in the interface extension
IBetterFoo
, as follows:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
Calling code aware of the extended interface can use the
castFrom()
Java method to safely cast the base interface to the
extended interface:
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IBetterFoo extendedService = IBetterFoo.castFrom(baseService); if (extendedService != null) { // The service implements the extended interface. } else { // The service implements only the base interface. }