Automotive Audio

This section details the audio architecture for automotive-related Android implementations. OEMs and other Android developers implementing an automotive audio system should review all content in this section thoroughly in addition to content in the main Audio section.

Key concepts

Android is responsible for infotainment sounds (i.e. media, navigation, and communications) but is not directly responsible for chimes and warnings that have strict availability and timing requirements. External sources are represented by applications, which are responsible for audio focus. However, you cannot rely on focus for sound selection and mixing.

Android 9 includes the following changes to automotive-related audio support:

  • The Audio HAL Context maps to AudioAttributes.usage to identify sounds; the Audio HAL implementation is responsible for Context-specific mixing/routing.
  • Vehicles define a generic output device (AUDIO_DEVICE_OUT_BUS) for use in vehicle audio systems; Android supports one AUDIO_DEVICE_OUT_BUS per Context.
  • IAudioControl HAL provides vehicle-specific extensions to the Audio HAL; for an example implementation, refer to device/generic/car/emulator/audio. Android 9 does not include AUDIO_* VHAL properties.

Android sounds and streams

Automotive audio systems handle the following sounds and streams:

Figure 1. Stream-centric architecture diagram

Android is responsible for sounds coming from Android applications, controlling those applications and routing their sounds to individual streams at the HAL based on the type of sound:

  • Logical streams, known as sources in core audio nomenclature, are tagged with Audio Attributes.
  • Physical streams, known as devices in core audio nomenclature, have no context information after mixing.

For reliability, external sounds (coming from independent sources such as seat belt warning chimes) are managed outside Android, below the HAL or even in separate hardware. System implementers must provide a mixer that accepts one or more streams of sound input from Android and then combines those streams in a suitable way with the external sound sources required by the vehicle. External streams can be always on, or controlled via createAudioPatch entry points in the HAL.

The HAL implementation and external mixer are responsible for ensuring the safety-critical external sounds are heard and for mixing in the Android-provided streams and routing them to suitable speakers.

Android sounds

Applications may have one or more players that interact through the standard Android APIs (e.g. AudioManager for focus control or MediaPlayer for streaming) to emit one or more logical streams of audio data. This data could be single channel mono or 7.1 surround, but is routed and treated as a single source. The application stream is associated with AudioAttributes that give the system hints about how the audio should be expressed.

The logical streams are sent through the AudioService and routed to one (and only one) of the available physical output streams, each of which is the output of a mixer within AudioFlinger. After AudioAttributes have been mixed down to a physical stream, they are no longer available.

Each physical stream is then delivered to the Audio HAL for rendering on the hardware. In automotive applications, rendering hardware can be local codecs (similar to mobile devices) or a remote processor across the vehicle's physical network. Either way, it is the job of the Audio HAL implementation to deliver the actual sample data and cause it to become audible.

External streams

Sound streams that should not be routed through Android (for certification or timing reasons) may be sent directly to the external mixer. In many cases, Android doesn't need to know these sounds exist as the external mixer can mix them over Android sounds. If a sound needs to be ducked or routed to different speakers, the external mixer can do that invisibly to Android.

If external streams are media sources that should interact with the sound environment Android is generating (e.g. stop MP3 playback when an external tuner is turned on), those external streams should be represented by an Android app. Such an app would request audio focus and respond to focus notifications by starting/stopping the external source as necessary to fit into the Android focus policy. One suggested mechanism to control such external devices is AudioManager.createAudioPatch().

Audio focus

Before starting a logical stream, an application should request audio focus using the same AudioAttributes as it will use for its logical stream. While sending such a focus request is recommended, it is not enforced by the system. Some applications may explicitly skip sending the request to achieve specific behaviors (e.g. to intentionally play sound during a phone call).

For this reason, you should consider focus as a way to indirectly control and deconflict media playback and not as a primary audio control mechanism—the vehicle should not depend on the focus system for operation of the audio subsystem. Focus awareness is not part of the HAL and should not be used to influence audio routing.

Output BUS

At the Audio HAL level, the device type AUDIO_DEVICE_OUT_BUS provides a generic output device for use in vehicle audio systems. The BUS device supports addressable ports (where each port is the end point for a physical stream) and is expected to be the only supported output device type in a vehicle.

A system implementation can use one BUS port for all Android sounds, in which case Android mixes everything together and delivers it as one stream. Alternatively, the HAL can provide one BUS port for each Context to allow concurrent delivery of any sound type. This makes it possible for the HAL implementation to mix or duck the different sounds as desired.

The assignment of Contexts to BUS ports is done through the Audio Control HAL and creates a many:one relationship between Contexts and BUS ports.

Microphone input

When capturing audio, the Audio HAL receives an openInputStream call that includes an AudioSource argument indicating how the microphone input should be processed.

VOICE_RECOGNITION (specifically the Google Assistant) expects a stereo microphone stream that has an echo cancellation effect (if available) but no other processing applied to it. Beamforming is expected to be done by the Assistant itself.

Multi-channel microphone input

To capture audio from a device with more than two channels (stereo), use a channel index mask instead of positional index mask (such as CHANNEL_IN_LEFT). Example:

final AudioFormat audioFormat = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(44100)
    .setChannelIndexMask(0xf /* 4 channels, 0..3 */)
    .build();
final AudioRecord audioRecord = new AudioRecord.Builder()
    .setAudioFormat(audioFormat)
    .build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);

When both setChannelMask and setChannelIndexMask are set, AudioRecord uses only the value set by setChannelMask (maximum of two channels).

Concurrent capture

The Android framework does not allow concurrent capture for most input audio device types but makes exceptions for AUDIO_DEVICE_IN_BUS and AUDIO_DEVICE_IN_FM_TUNER by handling them as virtual devices. Doing so means the framework assumes no competition for resources exists between/among these devices and thus any/all of them are allowed to be captured concurrently along with one regular input device (such as the microphone). If hardware constraints on concurrent capture do exist between/among these devices, such constraints must be handled by custom application logic in the first party applications designed to use these input devices.

Applications designed to work with AUDIO_DEVICE_IN_BUS devices or with secondary AUDIO_DEVICE_IN_FM_TUNER devices must rely on explicitly identifying those devices and using AudioRecord.setPreferredDevice() to bypass the Android default source selection logic.

Volume and volume groups

Android 8.x and lower supports three volume groups (ring, media, and alarm) along with a hidden group for phone in-call. Each group can be set to a different volume level based on the output device, such as higher volumes for speakers and lower volumes for headsets).

Android 9 adds a speech volume group and the automotive-related contexts as shown below:

Volume group Audio contexts Description
Ring CALL_RING_CONTEXT Voice call ringing
NOTIFICATION_CONTEXT Notifications
ALARM_CONTEXT Alarm sound from Android
SYSTEM_SOUND_CONTEXT System sound from Android
Media MUSIC_CONTEXT Music playback
Phone CALL_CONTEXT Voice call
Speech NAVIGATION_CONTEXT Navigation directions
VOICE_COMMAND_CONTEXT Voice command session

When the value for a volume group is updated, the framework's CarAudioService handles setting the affected physical stream gains. Physical stream volume in a vehicle is based on volume group (rather than stream_type) and each volume group consists of one or more Audio Contexts. Each AudioAttributes.USAGE maps to an Audio Context in a CarAudioService and can be configured to be routed to an output bus (see Configuring volume and Configuring volume groups).

Android 9 simplifies controlling the hardware volume in the amplifier:

  • Each volume group is routed to one or more output buses. The volume for a specific group can be changed using the Car Settings UI or via an externally-generated KEYCODE_VOLUME_DOWN or KEYCODE_VOLUME_UP key event.
  • In response, CarAudioService calls AudioManager.setAudioPortGain() with the audio device port(s) bound to targeted volume group. At the HAL, this appears as a series of one or more calls to IDevice.setAudioPortConfig() with the volume gain value for each physical output stream associated with the targeted volume group.

You can configure the maximum, minimum, and step gain value for each audio device port in audio_policy_configuration.xml. For a sample configuration and details on overriding the default set of volume groups, see Configuring audio devices.

Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.