The combined audio device routing feature adds support for streaming audio to multiple audio devices simultaneously. Using this feature, privileged apps can select multiple preferred devices for a particular strategy by way of system APIs. Apps can discover capabilities of audio devices more precisely by using the public APIs provided by this feature. For Android versions 11 and below, the audio framework implementation has limited support for multiple audio devices of the same type (for example, 2 Bluetooth A2DP headsets) connected simultaneously. The default audio routing rules also do not allow users to select multiple devices of the same type for a given use case.
Starting with Android 12, these limitations are removed in order to allow new use cases like audio broadcasting, multicasting to a group of BLE audio headphones or selecting several USB sound cards simultaneously. Routing to multiple USB devices simultaneously is not supported.
Starting with Android 14, the USB framework supports routing to multiple USB devices provided the USB devices are of different audio device types and, there's kernel and vendor support to connect multiple USB devices simultaneously.
This page covers how to implement support for streaming audio to multiple audio devices, and how to validate your implementation of this feature.
Support streaming audio to multiple audio devices
There are two sets of APIs in Android 12 that support this feature:
- The system APIs handle multiple preferred devices for a strategy.
- The HIDL interface, implemented by the vendor as part of the audio HAL, reports device capabilities.
The following sections discuss each of these APIs in more detail.
Handle multiple preferred devices for a strategy
The Audio Policy Manager offers system APIs to better support streaming audio to multiple audio device simultaneously. These system APIs enable setting, getting and removing multiple preferred devices for a given strategy. Until Android 12, this feature was supported for a single device only.
The Audio Policy Manager introduces the concept of active media devices to describe the devices that are most likely to be picked for media playback. When a detachable device is connected, the audio HAL output streams that can be routed to this device may have to be opened and probed for supported attributes.
An audio device must be specified when opening an output stream. The active media device is the device used when output streams are opened in this context.
The active media device selection can change depending on the actual devices connected or disconnected. The Audio Policy Manager uses the following series of rules to choose active media devices:
- If all of the preferred devices for media are available, they are all chosen as active devices.
- Otherwise, the last connected removable device is chosen.
- If there are no removable devices connected, the default audio policy rules for choosing output devices are applied to choose active devices.
An output stream must satisfy the following criteria to be reopened and routed to the active devices so that the best configuration is picked for the playback:
- The output stream must support the active devices.
- The output stream must support dynamic profiles.
- The output stream must not be currently routed to active devices.
In order to apply a new device selection, the Audio Policy Manager closes and reopens an output stream upon device connection if the output stream is idle, or defers it for when the output stream is placed into standby.
The Audio Policy Manager offers the following list of system APIs(as defined in
AudioManager.java
):
setPreferredDeviceForStrategy
Sets the preferred device for the audio routing for a given strategy. Note that the device may not be available at the time the preferred device is set, but is used once made available.
removePreferredDeviceForStrategy
Removes the preferred audio device(s) previously set with
setPreferredDeviceForStrategy
orsetPreferredDevicesForStrategy
.getPreferredDeviceForStrategy
Returns the preferred device for an audio strategy previously set with
setPreferredDeviceForStrategy
orsetPreferredDevicesForStrategy
.setPreferredDevicesForStrategy
Sets the preferred devices for a given strategy.
getPreferredDevicesForStrategy
Returns the preferred devices for an audio strategy previously set with
setPreferredDeviceForStrategy
orsetPreferredDevicesForStrategy
.OnPreferredDevicesForStrategyChangedListener
Defines an interface for notification of changes in the preferred audio devices which are set for a given audio strategy.
addOnPreferredDevicesForStrategyChangedListener
Adds a listener to get notified of changes to the strategy-preferred audio device.
removeOnPreferredDevicesForStrategyChangedListener
Removes a previously added listener of changes to the strategy-preferred audio device.
Report device capabilities
As part of the Audio HAL implementation, vendors implement the APIs that support reporting device capabilities. This section explains the data types and methods used to report device capabilities and lists some changes made in audio HIDL HAL V7 to support multiple devices.
Data types
In audio HIDL HAL V7, device capabilities are reported using the AudioProfile
and AudioTransport
structures. The AudioTransport
structure describes the
capability of an audio port with AudioProfile
for known audio formats, or with
raw hardware descriptors for formats that are not known by the platform. The
AudioProfile
structure contains the audio format, the sample rates supported
by the profile, and the list of channel masks, as shown in the following code
block from types.hal
:
/**
* Configurations supported for a certain audio format.
*/
struct AudioProfile {
AudioFormat format;
/** List of the sample rates (in Hz) supported by the profile. */
vec<uint32_t> sampleRates;
/** List of channel masks supported by the profile. */
vec<AudioChannelMask> channelMasks;
};
In audio HIDL HAL V7, the AudioPort
data type is defined with the
AudioTransport
andAudioProfile
structures to describe the device's
capabilities.
Audio HAL methods
The Audio Policy Manager uses the following methods to query the device’s capabilities:
getParameters:
A generic method for retrieving vendor-specific parameter values such as supported audio formats and their respective sampling rates.getAudioPort:
Returns the list of supported attributes (like sampling rates, formats, channel masks, gain controllers) for a given audio port.
The following code from IDevice.hal
shows the interface for the getAudioPort
method:
/**
* Returns the list of supported attributes for a given audio port.
*
* As input, 'port' contains the information (type, role, address etc...)
* needed by the HAL to identify the port.
*
* As output, 'resultPort' contains possible attributes (sampling rates,
* formats, channel masks, gain controllers...) for this port.
*
* @param port port identifier.
* @return retval operation completion status.
* @return resultPort port descriptor with all parameters filled up.
*/
getAudioPort(AudioPort port)
generates (Result retval, AudioPort resultPort);
Changes to the legacy API
To support multiple audio profiles, version 3.2 of the legacy API adds a new
structure called audio_port_v7
. See the source code
for more details.
Because of the addition of audio_port_v7
, version 3.2 of the legacy API adds a
new API called get_audio_port_v7
to query devices’ capabilities using the
audio_port_v7
structure.
The following code from audio.h
shows the definition of the get_audio_port_v7
API:
/**
* Fills the list of supported attributes for a given audio port.
* As input, "port" contains the information (type, role, address etc...)
* needed by the HAL to identify the port.
* As output, "port" contains possible attributes (sampling rates,
* formats, channel masks, gain controllers...) for this port. The
* possible attributes are saved as audio profiles, which contains audio
* format and the supported sampling rates and channel masks.
*/
int (*get_audio_port_v7)(struct audio_hw_device *dev,
struct audio_port_v7 *port);
Data from the legacy get_audio_port
API has to be populated into the new
AudioPort
format when the legacy API version is below 3.2 and the HIDL HAL
version is 7 or above. In this case, all the reported sample rates and channel
masks from get_audio_port
are assumed to be supported for all the returned
formats, enabling a straightforward mapping from get_audio_port
values to the
new AudioPort
structure.
Example API implementations
This section describes several test suites containing methods that use the APIs covered in the preceding sections. Refer to these methods for some examples of how these APIs are implemented and used.
An example of the usage of the setPreferredDevicesForStrategy
,
getPreferredDevicesForStrategy
, removePreferredDeviceForStrategy
and
OnPreferredDevicesForStrategyChangedListener
system APIs is in the
PreferredDeviceRoutingTest
method, which is located in GTS.
To see an example of the new structure in AudioDeviceInfo
in use, see the
AudioManagerTest#testGetDevices
method which is located in CTS.
An example of the implementation for get_audio_port_v7
is located in
audio_hal.c
and it shows how capabilities are queried for multiple devices.
Validation
This section gives information on CTS and GTS (Google Mobile Services Test Suite) validation of the Audio Manager.
CTS tests
CTS tests are located in android.media.cts.AudioManagerTest
.
The following is the list of available Audio Manager tests:
AudioManagerTest#testGetDevices
Verifies the precise capabilities of the audio device. It also verifies that the returned audio profiles in the
AudioDeviceInfo
structure preserve the content from the older, flattened array format, but are in the newAudioProfile
format.AudioManagerTest#testPreferredDevicesForStrategy
andAudioManagerTest#testPreferredDeviceForCapturePreset
Verify that the preferred devices for strategy and capture preset related API tests complete successfully.
GTS tests
GTS tests are located in com.google.android.gts.audioservice.AudioServiceHostTest
.
To validate if the APIs for preferred devices for strategy and capture preset
work correctly, run the AudioServiceHostTest#testPreferredDeviceRouting
and AudioServiceHostTest#testPreferredDeviceRoutingForCapturePreset
tests.