オーディオ ルーティング

Android 10 では、car_volumes_groups.xmlIAudioControl.getBusForContextcar_audio_configuration.xml に置き換えられています。新しい構成ファイルでは、ゾーンのリストが定義されています。各ゾーンには 1 つ以上の音量グループが存在し、それぞれのグループにデバイスが関連付けられています。各デバイスには、そのゾーン内にルーティングする必要があるコンテキストがあります。すべてのコンテキストが各ゾーン内で表現される必要があります。

オーディオ ルーティングの構成

オーディオ ポリシー ファイル(通常はベンダー パーティションに存在します)は、ボードのオーディオ ハードウェア構成を表します。car_audio_configuration.xml で参照されるデバイスはすべて、audio_policy_configuration.xml 内で定義する必要があります。

AAOS ルーティングを有効にする

AAOS ベースのルーティングを使用するには、audioUseDynamicRouting フラグを true に設定する必要があります。

<resources>
    <bool name="audioUseDynamicRouting">true</bool>
</resources>

false に設定すると、ルーティングと CarAudioService の大部分が無効になり、OS は AudioService のデフォルトの動作にフォールバックします。

プライマリ ゾーン

デフォルトでは、すべての音声がプライマリ ゾーンにルーティングされます。属性 isPrimary="true" により構成で指定できるプライマリ ゾーンは 1 つのみです。

構成の例

たとえば、車両に 2 つのゾーン(プライマリ ゾーンとバックシート エンターテイメント システム)があるとします。この場合、car_audio_configuration.xml は次のように定義されることが考えられます。

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true">
           <volumeGroups>
               <group>
                   <device address="bus0_media_out">
                       <context context="music"/>
                       <context context="announcement"/>
                   </device>
                   <device address="bus3_call_ring_out">
                       <context context="call_ring"/>
                   </device>
                   <device address="bus6_notification_out">
                       <context context="notification"/>
                   </device>
                   <device address="bus7_system_sound_out">
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                   </device>
               </group>
               <group>
                   <device address="bus1_navigation_out">
                       <context context="navigation"/>
                   </device>
                   <device address="bus2_voice_command_out">
                       <context context="voice_command"/>
                   </device>
               </group>
               <group>
                   <device address="bus4_call_out">
                       <context context="call"/>
                   </device>
               </group>
               <group>
                   <device address="bus5_alarm_out">
                       <context context="alarm"/>
                   </device>
               </group>
           </volumeGroups>
       </zone>
        <zone name="rear seat zone" audioZoneId="1">
           <volumeGroups>
               <group>
                   <device address="bus100_rear_seat">
                       <context context="music"/>
                       <context context="navigation"/>
                       <context context="voice_command"/>
                       <context context="call_ring"/>
                       <context context="call"/>
                       <context context="alarm"/>
                       <context context="notification"/>
                       <context context="system_sound"/>
                       <context context="emergency"/>
                       <context context="safety"/>
                       <context context="vehicle_status"/>
                       <context context="announcement"/>
                   </device>
               </group>
           </volumeGroups>
    </zones>
</audioZoneConfiguration>

このプライマリ ゾーンには、各種のデバイスと、それぞれが持つコンテキストがあります。これにより、HAL は車両のハードウェアを使用して、さまざまな後処理効果を適用し、各デバイス出力にミキシングできます。デバイスは、メディア、ナビゲーション、通話、アラームの 4 つの音量グループに分類されています。システムが useFixedVolume に構成されている場合は、各グループの音量レベルが HAL に渡され、これらのデバイスの出力に適用されます。

セカンダリ ゾーンについては、1 つの出力デバイスによる出力が想定されます。この例では、わかりやすくするために、すべての使用が 1 つのデバイスと音量グループにルーティングされます。

乗員ゾーンのオーディオ構成

Android 11 では car_audio_configuration.xml がさらに拡張され、audioZoneIdoccupantZoneId という 2 つの新しいフィールドが導入されました。1 つ目の audioZoneId を使用すると、ゾーン管理をより適切に制御できます。一方、occupantZoneId を使用すると、ユーザー ID ベースのルーティングを構成できます。

これらの新しいフィールドを使用するには、car_audio_configuration.xml の V2 が必要です。上のオーディオ構成を見直し、新しいフィールドを乗員ゾーン ID とオーディオ ゾーン ID のマッピングに使用すると、音量グループ定義のない新しい構成を次のように設定できます。

<audioZoneConfiguration version="2.0">
       <zone name="primary zone" isPrimary="true" occupantZoneId="0">
         ...
       </zone>
       <zone name="rear seat zone" audioZoneId="1" occupantZoneId="1">
         ...
       </zone>
    </zones>
</audioZoneConfiguration>

上の構成では、プライマリ ゾーンから乗員ゾーン 0 へのマッピングと、audioZoneId 1 から乗員ゾーン occupantZoneId 1 へのマッピングを定義しています。一般に、乗員ゾーンとオーディオ ゾーンの間のマッピングは構成できますが、1 対 1 のマッピングである必要があります。2 つの新しいフィールドを定義したルールを以下に示します。

  • プライマリ ゾーンの audioZoneId は常にゼロです。
  • audioZoneIdoccupantZoneId の番号を繰り返すことはできません。
  • audioZoneIdoccupantZoneId は 1 対 1 のマッピングのみ可能です。

アプリ UID 経由のルーティング

Android 10 では、一連の非表示 API が CarAudioManager に導入され、アプリでオーディオ ゾーンとフォーカスを照会して設定できるようになりました。

int[] getAudioZoneIds();
int getZoneIdForUid(int uid);
boolean setZoneIdForUid(int zoneId, int uid);
boolean clearZoneIdForUid(int uid);

この API により、ファースト パーティ アプリはアプリの UID に基づいてオーディオ ルーティングを管理できます。そのため、オーディオ ゾーン ID とアプリの UID も必要です。この情報があれば、CarAudioManager#setZoneIdForUid API を使用してオーディオ ルーティングを設定できます。

アプリのゾーンの変更

デフォルトでは、すべてのオーディオがプライマリ ゾーンにルーティングされます。別のゾーンにルーティングされるようにアプリを更新するには、CarAudioManager#setZoneIdForUid を使用します。

// Find zone to play
int zoneId = ...

// Find application's uid
Int uid = mContext.getPackageManager()
        .getApplicationInfo(mContext.getPackageName(), 0)
        .uid;

if (mCarAudioManager.setZoneIdForUid(zoneId, info.uid)) {
    Log.d(TAG, "Zone successfully updated");
} else {
    Log.d(TAG, "Failed to change zone");
}

注: ストリームとフォーカスでは、ゾーンを動的に切り替えることができません。したがって、ゾーンを変更するには、再生を停止してフォーカスする必要があります。

ユーザー ID によるルーティング

アプリケーションの UID ベースのルーティングでは、各アプリのオーディオ ルーティングを細かく制御できますが、アプリが実際に音声フォーカスをリクエストしオーディオを再生する前に、各アプリのオーディオ ルーティングを定義する必要もあります。この問題を軽減し、サードパーティ アプリが変更なしでオーディオを再生できるようにするために、CarAudioService は車両の乗員ゾーンとオーディオ ゾーンのマッピングを使用して、ユーザー ID ベースのルーティングを定義します。こうすることで、ユーザーが乗員ゾーンのカーオーディオ サービスにログインすると通知されます。このシグナルにより、音声フォーカスの管理とルーティングがすべてのオーディオ ゾーンに対して自動的に構成されます。

アプリの UID ベースのルーティングは引き続き使用できますが、ユーザー ID ルーティングとは別に行う必要があります。つまり、乗員ゾーンからカーオーディオ ゾーンへのマッピングが定義されている場合、UID ベースのルーティングは無効となり、CarAudioManager#setZoneidForUid を呼び出そうとするとエラーがスローされます。

オーディオ ルーティングとフォーカス管理は乗員ゾーン管理によって簡素化されていますが、ユーザーは依然として乗員ゾーンに割り当てられる必要があります。これを行うには、CarOccupantZoneManager#assignProfileUserToOccupantZone を使用します。この API にはユーザーを管理する権限が必要です。現時点では、OEM がなんらかのシステム UI を使用してユーザーから乗員ゾーンへの割り当てを管理することが想定されています。これが完了すると、アプリの起動、オーディオ ルーティング、フォーカス管理すべてが、ユーザーに対して自動的に構成されます。

setPreferredDevice によるルーティング

前述の変更に加えて、Android 11 には、各ゾーンに関連付けられた出力デバイスを照会する新しい API である CarAudioManager#getOutputDeviceForUsage(int zoneId, int usage) もあります。

この API を使用すると、特定のゾーンとオーディオ属性の使用状況について、出力デバイスに照会できます。このように、ファースト パーティ アプリはプレーヤーの setPreferredDevice API を活用して、オーディオを別のゾーンにルーティングできます。getOutputDeviceForUsage API はシステム API であり、PERMISSION_CAR_CONTROL_AUDIO_SETTINGS が必要です。特定のゾーンのメディア デバイスを検索し、setPreferredDevice API を使用してそのデバイスにルーティングする例を次に示します。

audioZoneId = ... ;
mediaDeviceInfo = mCarAudioManager
            .getOutputDeviceForUsage(audioZoneId, AudioAttributes.USAGE_MEDIA);
…
mPlayer.setPreferredDevice(mediaDeviceInfo);