Overview
The Audio Hardware Abstraction Layer (HAL) provides the interface between the Android framework (AudioFlinger and AudioPolicyService) and the device-specific audio hardware drivers. It is the lowest level of user-space code in the audio stack, communicating directly with the kernel ALSA (Advanced Linux Sound Architecture) drivers or proprietary vendor DSP drivers.
Audio HAL Interfaces
In modern Android (Android 8.0+), the Audio HAL is defined using HIDL (and more recently, AIDL). It consists of two primary components:
- Core HAL: Handles playback and capture of audio streams.
- Policy HAL: Describes the device topology (which ports are available, routing paths, and supported formats).
Core HAL Interfaces
The IDevice interface is the entry point. AudioFlinger uses it to open streams.
openOutputStream(): Called byAudioFlingerwhen a playback thread needs to send data to a hardware sink (e.g., speaker, headphone jack, Bluetooth A2DP). It returns anIStreamOutinterface.openInputStream(): Called for audio capture. Returns anIStreamIninterface.
// Example: HIDL IStreamOut write interface
Return<void> write(const hidl_vec<uint8_t>& data, write_cb _hidl_cb) {
// 1. Pass the buffer down to the tinyalsa library
// 2. tinyalsa interacts with /dev/snd/pcmC0D0p
int bytesWritten = pcm_write(mPcmHandle, data.data(), data.size());
// 3. Invoke callback with results
_hidl_cb(Result::OK, bytesWritten);
return Void();
}
Audio Policy HAL and Routing
The AudioPolicyService determines where audio should go, but the Audio HAL determines how to get it there.
The vendor provides an audio_policy_configuration.xml file. This file defines:
- Modules: The hardware interfaces (e.g.,
primary,a2dp,usb). - MixPorts: The logical streams
AudioFlingercan open. - DevicePorts: The physical endpoints (e.g.,
Speaker,Wired Headset). - Routes: The permitted paths between MixPorts and DevicePorts.
When a user plugs in headphones, the kernel detects the jack insertion. The Audio HAL notifies AudioPolicyService. The policy engine evaluates the routing rules and tells AudioFlinger to move the active audio tracks from the speaker's output stream to the headphone's output stream via a patch command sent back down to the HAL.
DSP Offloading for Low Power Playback
One of the most critical functions of the modern Audio HAL is hardware offloading. Decoding MP3 or AAC files on the main application processor (CPU) consumes significant battery.
To save power, Android supports pushing the compressed audio stream directly to a Digital Signal Processor (DSP).
- Capability Query: The framework checks if the HAL supports offloading for a specific format (e.g., MP3 at 44.1kHz).
- OffloadThread Creation:
AudioFlingerspawns anOffloadThread. - Stream Delivery: Compressed bytes are sent via
openOutputStreamwith theAUDIO_OUTPUT_FLAG_COMPRESS_OFFLOADflag. - DSP Processing: The DSP, which runs a highly optimized RTOS, buffers the data, decodes it, and drives the DAC (Digital-to-Analog Converter). The main CPU can enter a deep sleep state.
Gapless Playback and Offloading
Managing offload requires tight control. For gapless playback (playing two songs seamlessly), the framework must send the next track's metadata and data to the DSP before the first track finishes. The HAL uses setParameters() or specific HIDL methods to signal "drain" or "next track" events to ensure smooth transitions without waking the main CPU.
Diagnosing Audio Policy
You can view the active audio routes, connected devices, and the loaded policy configuration using:
adb shell dumpsys media.audio_policy
This output is invaluable for debugging why audio is playing out of the wrong speaker or why offload is failing.