組合音頻設備路由

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

從 Android 12 開始,這些限制被刪除,以便允許新的用例,例如音訊廣播、多播到一組 BLE 音訊耳機或同時選擇多個 USB 音效卡。不支援同時路由到多個 USB 裝置。

從 Android 14 開始,USB 框架支援路由到多個 USB 設備,前提是這些 USB 設備具有不同的音訊設備類型,並且核心和供應商支援同時連接多個 USB 設備。

本頁介紹如何實現對多個音訊設備的串流音訊支持,以及如何驗證此功能的實現。

支援將音訊串流傳輸到多個音訊設備

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

  • 系統 API 處理策略的多個首選設備。
  • HIDL 介面由供應商作為音訊 HAL 的一部分實現,用於報告設備功能。

以下部分更詳細地討論每個 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 的使用範例位於PreferredDeviceRoutingTest方法中,該方法位於 GTS 中。

若要查看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測試。