組合音頻設備路由

組合的音頻設備路由功能增加了對同時將音頻流式傳輸到多個音頻設備的支持。使用此功能,特權應用可以通過系統 API 為特定策略選擇多個首選設備。應用程序可以通過使用該功能提供的公共 API 更準確地發現音頻設備的能力。對於 Android 11 及以下版本,音頻框架實現對同時連接的多個相同類型的音頻設備(例如,2 個藍牙 A2DP 耳機)的支持有限。默認音頻路由規則也不允許用戶為給定用例選擇多個相同類型的設備。

從 Android 12 開始,這些限制被移除,以便允許新的用例,例如音頻廣播、多播到一組 BLE 音頻耳機或同時使用多個 USB 聲卡。

本頁介紹如何實現對將音頻流式傳輸到多個音頻設備的支持,以及如何驗證您對該功能的實現。

支持將音頻流式傳輸到多個音頻設備

Android 12 中有兩組 API 支持此功能:

  • 系統 API 為一個策略處理多個首選設備。
  • 由供應商作為音頻 HAL 的一部分實施的 HIDL 接口報告設備功能。

以下部分將更詳細地討論這些 API。

為策略處理多個首選設備

音頻策略管理器提供系統 API 以更好地支持同時將音頻流式傳輸到多個音頻設備。這些系統 API 支持為給定策略設置、獲取和刪除多個首選設備。在 Android 12 之前,此功能僅支持單個設備。

音頻策略管理器引入了活動媒體設備的概念來描述最有可能被挑選用於媒體播放的設備。連接可拆卸設備時,可能必須打開可路由到此設備的音頻 HAL 輸出流並探測支持的屬性。

打開輸出流時必須指定音頻設備。活動媒體設備是在此上下文中打開輸出流時使用的設備。

活動媒體設備選擇可以根據連接或斷開的實際設備而改變。音頻策略管理器使用以下一系列規則來選擇活動媒體設備:

  1. 如果媒體的所有首選設備都可用,則它們都被選為活動設備。
  2. 否則,將選擇最後連接的可移動設備。
  3. 如果沒有連接可移動設備,則會應用用於選擇輸出設備的默認音頻策略規則來選擇活動設備。

輸出流必須滿足以下條件才能重新打開並路由到活動設備,以便為播放選擇最佳配置:

  • 輸出流必須支持活動設備。
  • 輸出流必須支持動態配置文件。
  • 輸出流當前不得路由到活動設備。

為了應用新的設備選擇,如果輸出流空閒,音頻策略管理器會在設備連接時關閉並重新打開輸出流,或者將其推遲到輸出流處於待機狀態時。

音頻策略管理器提供以下系統 API 列表(定義在AudioManager.java中):

  • setPreferredDeviceForStrategy

    為給定策略設置音頻路由的首選設備。請注意,在設置首選設備時該設備可能不可用,但一旦可用,就會使用該設備。

  • removePreferredDeviceForStrategy

    刪除先前使用setPreferredDeviceForStrategysetPreferredDevicesForStrategy設置的首選音頻設備。

  • getPreferredDeviceForStrategy

    返回先前使用setPreferredDeviceForStrategysetPreferredDevicesForStrategy設置的音頻策略的首選設備。

  • setPreferredDevicesForStrategy

    為給定策略設置首選設備。

  • getPreferredDevicesForStrategy

    返回先前使用setPreferredDeviceForStrategysetPreferredDevicesForStrategy設置的音頻策略的首選設備。

  • OnPreferredDevicesForStrategyChangedListener

    定義一個接口,用於通知為給定音頻策略設置的首選音頻設備的更改。

  • addOnPreferredDevicesForStrategyChangedListener

    添加一個偵聽器以獲取有關策略首選音頻設備更改的通知。

  • removeOnPreferredDevicesForStrategyChangedListener

    刪除先前添加的對策略首選音頻設備更改的偵聽器。

報告設備功能

作為音頻 HAL 實施的一部分,供應商實施支持報告設備功能的 API。本部分介紹了用於報告設備功能的數據類型和方法,並列出了音頻 HIDL HAL V7 中為支持多個設備所做的一些更改。

數據類型

在音頻 HIDL HAL V7 中,使用AudioProfileAudioTransport結構報告設備功能。 AudioTransport結構使用AudioProfile描述音頻端口的功能,用於已知音頻格式,或使用原始硬件描述符用於平台未知的格式。 AudioProfile結構包含音頻格式、配置文件支持的採樣率以及通道掩碼列表,如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;
};

在音頻 HIDL HAL V7 中, AudioPort數據類型使用AudioTransportAudioProfile結構定義,以描述設備的功能。

音頻 HAL 方法

音頻策略管理器使用以下方法來查詢設備的功能:

  • getParameters:用於檢索特定於供應商的參數值的通用方法,例如支持的音頻格式及其各自的採樣率。
  • getAudioPort:返回給定音頻端口支持的屬性列表(如採樣率、格式、通道掩碼、增益控制器)。

IDevice.hal中的以下代碼顯示了getAudioPort方法的接口:

   /**
    * 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);

對舊版 API 的更改

為了支持多個音頻配置文件,舊版 API 3.2 版添加了一個名為audio_port_v7的新結構。有關更多詳細信息,請參閱源代碼

由於添加了audio_port_v7 ,舊版 API 的 3.2 版添加了一個名為get_audio_port_v7的新 API,以使用audio_port_v7結構查詢設備的功能。

audio.h中的以下代碼顯示了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);

當舊版 API 版本低於 3.2 且 HIDL HAL 版本為 7 或更高版本時,必須將來自舊版get_audio_port API 的數據填充到新的AudioPort格式中。在這種情況下,假設所有返回的格式都支持來自get_audio_port的所有報告的採樣率和通道掩碼,從而可以直接將get_audio_port值映射到新的AudioPort結構。

示例 API 實現

本節描述了幾個測試套件,其中包含使用前面​​章節中介紹的 API 的方法。有關如何實現和使用這些 API 的一些示例,請參閱這些方法。

使用setPreferredDevicesForStrategygetPreferredDevicesForStrategyremovePreferredDeviceForStrategyOnPreferredDevicesForStrategyChangedListener系統 API 的示例在位於 GTS 中的PreferredDeviceRoutingTest方法中。

要查看正在使用的AudioDeviceInfo中的新結構的示例,請參閱位於 CTS 中的AudioManagerTest#testGetDevices方法。

get_audio_port_v7的實現示例位於audio_hal.c中,它顯示瞭如何查詢多個設備的功能。

驗證

本節提供有關音頻管理器的CTS和 GTS(Google 移動服務測試套件)驗證的信息。

CTS 測試

CTS 測試位於android.media.cts.AudioManagerTest中。

以下是可用音頻管理器測試的列表:

  • AudioManagerTest#testGetDevices

    驗證音頻設備的精確功能。它還驗證AudioDeviceInfo結構中返回的音頻配置文件是否保留了舊的扁平數組格式的內容,但採用新的AudioProfile格式。

  • AudioManagerTest#testPreferredDevicesForStrategyAudioManagerTest#testPreferredDeviceForCapturePreset

    驗證策略和捕獲預設相關 API 測試的首選設備是否成功完成。

GTS 測試

GTS 測試位於com.google.android.gts.audioservice.AudioServiceHostTest

要驗證用於策略和捕獲預設的首選設備的 API 是否正常工作,請運行AudioServiceHostTest#testPreferredDeviceRoutingAudioServiceHostTest#testPreferredDeviceRoutingForCapturePreset測試。