Google is committed to advancing racial equity for Black communities. See how.

AIDL for HALs

Android R introduces the ability to use AIDL for HALs in Android. This makes it possible to implement parts of Android without HIDL. It is strongly recommended to transition HALs to use AIDL exclusively where possible (when upstream HALs use HIDL, HIDL must be used).

HALs using AIDL to communicate between framework components, such as those in system.img, and hardware components, such as those in vendor.img, must use Stable AIDL. However, to communicate within a partition, for instance, from one HAL to another, there is no restriction on the IPC mechanism being used.

Motivation

AIDL has been around longer than HIDL, and is used in many other places, such as between Android framework components or in apps. Now that AIDL has stability support, it's possible to implement an entire stack with a single IPC runtime. AIDL also has a better versioning system than HIDL.

  • Using a single IPC language means having only one thing to learn, debug, optimize, and secure.
  • AIDL supports in-place versioning for the owners of an interface
    • Owners can add methods to the end of interfaces or fields to parcelables. This means it's easier to version code over the years, and also the year over year cost is smaller (types can be amended in-place and there is no need for extra libraries for each interface version).
    • Extension interfaces can be attached at runtime rather than in the type system, so there is no need to rebase downstream extensions onto newer versions of interfaces.
  • Existing AIDL interfaces can be used directly when its owner chooses to stabilize it. Before, an entire copy of the interface would have to be created in HIDL.

Writing an AIDL HAL interface

For an AIDL interface to be used between system and vendor, the interface needs two changes:

  • Every type definition needs to be annotated with @VintfStability
  • The aidl_interface declaration needs to include stability: "vintf",

Only the owner of an interface can make these changes.

Additionally, for maximum code portability and to avoid potential problems such as unnecessary additional libraries, it is recommended to disable the CPP backend.

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

Finding AIDL HAL interfaces

AOSP Stable AIDL interfaces for HALs are in the same base directories as HIDL interfaces, in aidl folders.

  • hardware/interfaces
  • frameworks/hardware/interfaces
  • system/hardware/interfaces

You should put extension interfaces into other hardware/interfaces subdirectories in vendor or hardware. It is strongly recommended to keep interfaces consistent between all devices. Extensions can register in two different ways:

Building against the AIDL runtime

AIDL has three different backends: Java, NDK, CPP. To use Stable AIDL, you must always use the system copy of libbinder at system/lib*/libbinder.so and talk on /dev/binder. For code on the vendor image, this means that libbinder (from the VNDK) cannot be used: this library has an unstable C++ API and unstable internals. Instead, native vendor code must use the NDK backend of AIDL, link against libbinder_ndk (which is backed by system libbinder.so), and link against the -ndk_platform libraries created by aidl_interface entries.

AIDL HAL server instance names

By convention, AIDL HAL services have an instance name of the format $package.$type/$instance. For example, an instance of the vibrator HAL is registered as android.hardware.vibrator.IVibrator/default.

Wrting an AIDL HAL server

AIDL servers must be declared in the VINTF manifest, for example like this:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <fqname>IVibrator/default</fqname>
    </hal>

Otherwise, they should register an AIDL service normally. When running VTS tests, it's expected that all declared AIDL HALs are available.

Writing an AIDL client

AIDL clients must declare themselves in the compatibility matrix, for example like this:

    <name>android.hardware.vibrator</name>
    <interface>
        <name>IVibrator</name>
        <instance>default</instance>
    </interface>

Converting an existing HAL from HIDL to AIDL

Use the hidl2aidl tool to convert a HIDL interface to AIDL. Follow these steps to convert a package of .hal files to .aidl files:

  1. Build the tool located in system/tools/hidl/hidl2aidl.

    m hidl2aidl
    
  2. Execute the tool with an output directory followed by the package to be converted.

    hidl2aidl -o <output directory> <package>
    

    For example:

    hidl2aidl -o . android.hardware.nfc@1.2
    
  3. Read through the generated files and fix up any issues with the conversion.

    • conversion.log contains any unhandled issues that should be fixed first.
    • The generated .aidl files may have warnings and suggestions that may need action. These comments begin with //.
    • Take the opportunity to clean up and make improvements to the package.

Sepolicy for AIDL HALs

An AIDL service type which is visible to vendor code must have the vendor_service attribute. Otherwise, the sepolicy configuration is the same as any other AIDL service.

    type hal_power_service, service_manager_type, vendor_service;

Attached extension interfaces

An extension can be attached to any binder interface, whether it is a top-level interface registered directly with service manager or it is a sub-interface. When getting an extension, you must confirm the type of the extension is as expected. Extensions can only be set from the process serving a binder.

Attached extensions should be used whenever an extension modifies the functionality of an existing HAL. When entirely new functionality is needed, this mechanism doesn't need to be used, and an extension interface can be registered with the service manager directly.

To set an extension on binder, use the following APIs:

  • In the NDK backend: AIBinder_setExtension
  • In the Java backend: android.os.Binder.setExtension
  • In the CPP backend: android::Binder::setExtension

To get an extension on a binder, use the following APIs:

  • In the NDK backend: AIBinder_getExtension
  • In the Java backend: android.os.IBinder.getExtension
  • In the CPP backend: android::IBinder::getExtension

You can find more information for these APIs in the documentation of the getExtension function in the corresponding backend. An example of how to use extensions can be found in hardware/interfaces/tests/extension/vibrator.

Major AIDL/HIDL differences

When using AIDL HALs or using AIDL HAL interfaces, be aware of the differences compared to writing HIDL HALs.

  • The AIDL language's syntax is closer to Java. HIDL syntax is similar to C++.
  • All AIDL interfaces have built-in error statuses. Instead of creating custom status types, create constant status ints in interface files and use EX_SERVICE_SPECIFIC in the CPP/NDK backends and ServiceSpecificException in the Java backend.
  • AIDL does not abort on unchecked transport errors (HIDL Return aborts on unchecked errors).
  • AIDL can only declare one type per file.
  • AIDL arguments can be specified as in/out/inout in addition to the output parameter (there are no "synchronous callbacks").
  • AIDL uses an fd as the primitive type instead of handle.
  • HIDL uses major versions for incompatible changes and minor versions for compatible changes. In AIDL, backwards compatible changes are done in place. AIDL has no explicit concept of major versions, and instead this is incorporated into package names. For instance, AIDL might use the package name bluetooth2.