Implementing USB HAL

The Android 8.0 release moves handling of USB commands out of init scripts and into a native USB daemon for better configuration and code reliability. For the Gadget function configuration, init scripts (property triggers) are used to perform device-specific gadget operations.

In previous releases, these device-specific configurations were achieved through device-specific init scripts (using property triggers). Moving to a Hardware Abstraction Layer (HAL) design results in a much cleaner implementation that solves these problems:

  1. Operations such as writes to the kernel sysfs nodes could fail but not be propagated back to the frameworks code that sets the property trigger. As a result, frameworks incorrectly assumes the operations have succeeded even though they have silently failed.
  2. init scripts have a limited number of operations that could be executed.

The Android 12 release adds USB Gadget HAL support for Network Control Models (NCM) and API calls that return both the HAL version number and USB speed. For more information on the API calls available through the USB HAL, see the android.hardware.usb package summary.

HAL and Treble

The device-specific init scripts were used as a substitution for HAL layers to perform device-specific USB operations. USB (through ADB) is a primary interface for debugging system issues. Having a native daemon to perform USB configuration eliminates the dependency on the framework code so even if the framework crashes USB should be running.

Under the Treble model also introduced in Android 8.0, all of the HALs are isolated from System services and are required to run in their own native daemons. This eliminates the requirement to have an exclusive USB daemon as the HAL layer nicely doubles as a USB daemon.

The default HAL implementation takes care of all pre-Android 8.0 devices. Therefore, there wouldn't be any device-specific work for the pre-Android 8.0 devices. Android 8.0 uses the HAL interface to query the status of USB ports and to perform data role and power role swaps.

Implementation

New USB HAL interface needs to be implemented on every device launching on Android 8.0. The default implementation should take care of pre-Android 8.0 devices. The default implementation is sufficient if the device uses the dual_role_usb class to report type-c port status. Trivial changes might be required in device-specific USB scripts to transfer ownership of the typc-c nodes to system.