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:
- 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.
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. }