オーディオ機器のルーティングの組み合わせ

オーディオ機器のルーティング機能を組み合わせると、複数のオーディオ機器に同時に音声をストリーミングできるようになります。この機能を使用すると、特権アプリはシステム API を通じて、特定の戦略に対して複数の優先デバイスを選択できます。アプリはこの機能によって提供されている公開 API を使用することで、オーディオ機器の機能をより正確に検出できます。Android 11 以前のバージョンでは、同じタイプの複数のオーディオ機器(2 つの Bluetooth A2DP ヘッドセットなど)が同時に接続されている場合、オーディオ フレームワークの実装ではサポートが制限されていました。また、特定のユースケースにおいて、デフォルトのオーディオ ルーティング ルールでは、同じタイプのデバイスを複数選択することはできませんでした。

Android 12 以降ではこれらの制限がなくなり、オーディオ ブロードキャスト、BLE オーディオ ヘッドフォン グループへのマルチキャスト、複数の USB サウンドカードの同時選択など、新たなユースケースに対応できるようになっています。ただし、複数の USB デバイスへの同時ルーティングはサポートされていません。

Android 14 から、USB フレームワークは USB デバイスが異なるオーディオ デバイスタイプの場合、複数の USB デバイスへのルーティングをサポートします。複数の USB デバイスを同時に接続するカーネルとベンダー サポートがあります。

このページでは、複数のオーディオ機器へのオーディオ ストリーミングのサポートを実装する方法と、この機能の実装を検証する方法について説明します。

複数のオーディオ機器へのオーディオ ストリーミングをサポートする

Android 12 には、この機能をサポートする 2 つの API セットがあります。

  • システム API は、1 つの戦略に対して複数の優先デバイスを処理します。
  • ベンダーがオーディオ HAL の一部として実装した HIDL インターフェースが、デバイスの機能をレポートします。

以降のセクションでは、これらの各 API について詳しく説明します。

1 つの戦略に対して複数の優先デバイスを処理する

オーディオ ポリシー マネージャーは、複数のオーディオ機器への同時オーディオ ストリーミングをサポートするシステム API を提供します。これらのシステム API を使用することで、特定の戦略に合わせて複数の優先デバイスを設定、取得、削除できます。Android 12 より前は、この機能は 1 台のデバイスについてのみサポートされていました。

オーディオ ポリシー マネージャーでは、アクティブなメディア デバイスという概念が導入されています。これは、メディア再生用に選ばれる可能性が最も高いデバイスを意味します。取り外し可能なデバイスが接続されている場合、このデバイスにルーティングできるオーディオ HAL 出力ストリームを開始して、サポートされている属性についてプローブすることが必要となる場合があります。

オーディオ機器は、出力ストリームを開始する際に指定する必要があります。アクティブなメディア デバイスは、このコンテキストで出力ストリームが開始されるときに使用されるデバイスです。

アクティブなメディア デバイスの選択は、実際に接続または接続解除されているデバイスに応じて変わります。オーディオ ポリシー マネージャーは、次の一連のルールに従ってアクティブなメディア デバイスを選択します。

  1. 優先デバイスがメディアに対してすべて使用可能な場合、そのすべてがアクティブなデバイスとして選択されます。
  2. それ以外の場合は、最後に接続された取り外し可能なデバイスが選択されます。
  3. 取り外し可能なデバイスが接続されていない場合、出力デバイスを選択するためのデフォルトのオーディオ ポリシー ルールが適用され、アクティブなデバイスが選択されます。

出力ストリームが再開され、アクティブなデバイスにルーティングされるには、次の条件を満たす必要があります。これによって、再生に最適な構成が選択されるようになります。

  • 出力ストリームはアクティブなデバイスをサポートしている必要があります。
  • 出力ストリームはダイナミック プロファイルをサポートしている必要があります。
  • 出力ストリームは現在アクティブなデバイスにルーティングされていない必要があります。

新しいデバイスの選択を適用するために、オーディオ ポリシー マネージャーは、出力ストリームがアイドル状態の場合はデバイス接続時に出力ストリームを閉じてから再度開き、出力ストリームがスタンバイ状態の場合は遅延させます。

オーディオ ポリシー マネージャーでは、次のリストのシステム API を利用できます(これは AudioManager.java で定義されています)。

  • setPreferredDeviceForStrategy

    特定の戦略に対して音声ルーティングの優先デバイスを設定します。優先デバイスの設定時にその優先デバイスが使用できない場合もありますが、使用可能になればその優先デバイスが使用されます。

  • removePreferredDeviceForStrategy

    以前に setPreferredDeviceForStrategy または setPreferredDevicesForStrategy で設定された優先オーディオ機器を削除します。

  • getPreferredDeviceForStrategy

    以前に setPreferredDeviceForStrategy または setPreferredDevicesForStrategy で設定されたオーディオ戦略の優先デバイスを返します。

  • setPreferredDevicesForStrategy

    特定の戦略に対して優先デバイスを設定します。

  • getPreferredDevicesForStrategy

    以前に setPreferredDeviceForStrategy または setPreferredDevicesForStrategy で設定されたオーディオ戦略の優先デバイスを返します。

  • OnPreferredDevicesForStrategyChangedListener

    特定の戦略に対して設定されている優先オーディオ機器の変更を通知するインターフェースを定義します。

  • addOnPreferredDevicesForStrategyChangedListener

    戦略に対して設定されている優先オーディオ機器の変更の通知を取得するリスナーを追加します。

  • removeOnPreferredDevicesForStrategyChangedListener

    戦略に対して設定されている優先オーディオ機器の変更の通知を取得する、以前に追加されたリスナーを削除します。

デバイスの機能をレポートする

Audio HAL の実装の一環として、ベンダーはデバイスの機能のレポートをサポートする API を実装します。このセクションでは、デバイスの機能を報告するために使用されるデータの種類とメソッドについて説明し、オーディオ HIDL HAL V7 で複数のデバイスをサポートするために行われた変更の一覧を示します。

データの種類

オーディオ HIDL HAL V7 では、AudioProfile 構造と AudioTransport 構造を使用してデバイスの機能をレポートします。AudioTransport 構造は、既知のオーディオ形式の場合は AudioProfile、プラットフォームで認識されない形式の場合は未加工のハードウェア記述子を使用して、オーディオ ポートの機能を記述します。次の types.hal のコードブロックに示すように、AudioProfile 構造には、音声形式、プロファイルでサポートされるサンプルレート、チャンネル マスクのリストが含まれます。

/**
* 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 データ型が AudioTransport および AudioProfile 構造で定義されています。

オーディオ 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 という新しい構造が追加されています。詳しくは、ソースコードをご覧ください。

レガシー API のバージョン 3.2 では、audio_port_v7 が追加されたため、audio_port_v7 構造を使用してデバイスの機能をクエリするための get_audio_port_v7 という新しい API が追加されています。

次の 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#testPreferredDeviceRouting テストと AudioServiceHostTest#testPreferredDeviceRoutingForCapturePreset テストを実施します。