Combined Audio Device Routing

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 using several USB sound cards simultaneously.

This page covers how to implement support for streaming audio to multiple audio devices, and how to validate your implementation of this feature.

Supporting 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.

Handling 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:

  1. If all of the preferred devices for media are available, they are all chosen as active devices.
  2. Otherwise, the last connected removable device is chosen.
  3. 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 or setPreferredDevicesForStrategy.

  • getPreferredDeviceForStrategy

    Returns the preferred device for an audio strategy previously set with setPreferredDeviceForStrategy or setPreferredDevicesForStrategy.

  • setPreferredDevicesForStrategy

    Sets the preferred devices for a given strategy.

  • getPreferredDevicesForStrategy

    Returns the preferred devices for an audio strategy previously set with setPreferredDeviceForStrategy or setPreferredDevicesForStrategy.

  • 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.

Reporting 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 new AudioProfile format.

  • AudioManagerTest#testPreferredDevicesForStrategy and AudioManagerTest#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.