HIDL Java

Android 8.0 re-architected the Android OS 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 be in Java (described below) or as 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 able to be used directly from Java as some Android subsystems (such as Telephony) will most likely 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.

Being a client

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.

Adding 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 you are 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/vendor app targeting Android 10 and higher, you must statically include these libraries. For older apps, the old behavior is preserved. Alternatively, it is possible to 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. In order to save space on a device, this is the recommended approach. For more details, see Implementing Java SDK Library.

Starting in 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. Instead, they have been moved into a new namespace with jarjar. Modules on the boot classpath using HIDL need to use the shallow variants of those libraries as well as add jarjar_rules: ":framework-jarjar-rules" to their Android.bp in order to avoid duplicated code and having system/vendor apps use hidden APIs.

Modifying 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(…);

Providing a service

Framework code in Java may 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:

  1. Define your interface in HIDL.
  2. Open /tmp/android/hardware/foo/IFooCallback.java as a reference.
  3. Create a new module for your Java implementation.
  4. Examine the abstract class android.hardware.foo.V1_0.IFooCallback.Stub, then write a new class to extend it and implement the abstract methods.

Viewing 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.

Running 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 you will be receiving callbacks from.
// 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 may 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.
}