音声フォーカス

通常、音声フォーカスをグローバルに保持するアプリは、最大で 1 つです。別のアプリがフォーカスをリクエストすると、前のアプリはフォーカス喪失イベントを受け取り、新しいアプリにフォーカスが付与されます。この動作にはいくつかの例外があります。たとえば通話がフォーカスを保持している場合、新しいフォーカス リクエストは拒否されます。

新しいコンテキスト インタラクションの定義

Android 9 以降、車の音声フォーカスは別の方法で管理されています。CarAudioFocus にインタラクション マトリックスが導入されました。これはフォーカス リクエストが来たときに、新しいソースと現在フォーカスを保持しているソースの両方の使用タイプに基づいて、望ましい動作をキャプチャする機能です。インタラクションには次の 3 種類があります。

排他的なインタラクション

排他的なアプリ コンテキスト インタラクションでは、一度に 1 つのアプリのみがフォーカスを保持できます。たとえば 2 つのメディア プレーヤー アプリであれば、どちらもメディアを再生しているため、1 つのアプリのみがフォーカスを保持できます。これはフォーカス ホルダーとフォーカス リクエスターの両方が AudioManager.AUDIOFOCUS_GAIN をリクエストした場合によく起こる、デフォルトのインタラクションです。この場合、新着のフォーカス リクエストが承認されると、AudioManager.AUDIOFOCUS_LOSS が現在のフォーカス ホルダーにディスパッチされます。排他的な使用インタラクションは、AudioManager.AUDIOFOCUS_GAIN 以外の他の音声フォーカスをリクエストすることもあります。この場合もインタラクションは排他的となり、適切なタイプのフォーカス喪失がディスパッチされます。

拒否のインタラクション

拒否のコンテキスト インタラクションでは、新着のフォーカス リクエスターによるリクエストは常に拒否されます。通知からアラームへの移行の試みは、拒否の使用インタラクションの一例です。この場合、着信通知音を再生しているアプリが音声フォーカスを保持している状態で、2 つ目のアプリがアラームを再生するためにフォーカスをリクエストすると、アラームアプリはフォーカス リクエストの拒否を受け取ります。フォーカス リクエストが拒否されるため、現在のフォーカス ホルダーにはいかなるタイプのフォーカス喪失もディスパッチされません。

同時インタラクション

カーオーディオ ユーザーにとって最も興味深いのは、同時コンテキスト インタラクションです。これにより、車内で音声フォーカスをリクエストするアプリは、他のアプリと同時に音声を再生できるようになります。OEM は、このインタラクションをカーオーディオ ルーティングとともに使用することで、車のさまざまな部分に音声を同時にルーティングできます。同時インタラクションを行うには、フォーカス リクエスターが AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK をリクエストする必要があります。setPauseWhenDucked(true) は、AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK と組み合わせて使用することにより、引き続き期待どおりに機能します。Dk イベントは、アプリが再生を一時停止できるように、同時フォーカス リクエストに対して配信されます。後者は通常、オーディオブック アプリで使用され、ユーザーがオーディオ内のイベントを見逃さないようにします。

同時インタラクションには多くの便利なアプリがありますが、OEM は、出力デバイス全体のハードウェア レベルでミキシングとダッキングを処理する必要があります。たとえば、ナビゲーションとメディアが同時に配信される場合、OEM は、運転席側のスピーカーで再生されているメディアを一時的にミュート(ダッキング)し、代わりにナビゲーションを再生したい場合があります。メディアとナビゲーションが異なるデバイスに配信されるように車が設定されている場合、データがナビゲーション デバイスに配信されるときにメディアをダッキングすることによってこれを実現できます。このようにして、OEM は、運転席側でナビゲーションの指示を再生しながら、キャビンの残りの部分でメディアの再生を継続できます。ただし、2 つのソースが同じ出力デバイスにミキシングされる場合は、ダッキングは適用されません。そのため、同時再生が可能なコンテキストは、ダッキングを適切に処理できるように、別々のデバイスにルーティングすることをおすすめします。

インタラクション マトリックス

次の表 1 は、CarAudioFocus で定義されたインタラクション マトリックスを示しています。この表では、行はフォーカスを保持している現在のアプリを、列は新着のフォーカス リクエスターを表しています。

音楽メディアアプリが現在フォーカスを保持していて、ナビゲーション アプリがフォーカスをリクエストしている例を見ると、マトリックスは 2 つのインタラクションが同時に再生できることを示しています。新着のナビゲーション アプリがリクエストしたフォーカスが AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK である場合、フォーカス リクエストは承認され、メディアアプリにフォーカス喪失が送信されることはありません。複数のフォーカス ホルダーが存在することも可能です。この場合、適用する移行の種類を決定する前に、新着のフォーカス リクエスターが現在の各フォーカス ホルダーと比較されます。

表 1. カーオーディオ フォーカスの使用インタラクション マトリックス。

新着のフォーカス リクエスターのコンテキスト:

コンテキスト 無効 音楽 ナビゲーション 音声 着信音 電話 アラーム 通知 システム
無効 REJ REJ REJ REJ REJ REJ REJ REJ REJ
音楽 REJ EXC CON EXC EXC EXC EXC CON CON
ナビゲーション REJ CON CON EXC CON EXC CON CON CON
音声 REJ CON REJ CON EXC EXC REJ REJ REJ
着信音 REJ REJ CON CON CON CON REJ REJ CON
電話 REJ REJ CON REJ CON CON CON CON REJ
アラーム REJ CON CON EXC EXC EXC CON CON CON
通知 REJ CON CON EXC EXC EXC CON CON CON
システム REJ CON CON EXC EXC EXC CON CON CON

凡例:

  • REJ。拒否(Reject)
  • EXC。排他的(Exclusive)
  • CON。同時(Concurrent)

詳細については、packages/services/Car/service/src/com/android/car/audio/CarAudioFocus.java をご覧ください。

マルチゾーン フォーカス管理

Android 10 では、Android 9 のアプリ使用インタラクションのルールは維持されていますが、フォーカスはオーディオ ゾーンごとにさらに分割されています。これにより、メインキャビンのフォーカスを後部座席のエンターテインメント システムとは別に管理できるため、あるゾーンでのフォーカスの変更によって別のゾーンでのオーディオ再生が中断されることを回避できます。

すべてのアプリのフォーカス管理は、CarAudioService によって自動的に行われ、CarAudioManager.setZoneIdForUid API を介して設定されます。UID が特定のゾーンにマッピングされると、そのゾーンからフォーカスが自動的にリクエストされます。フォーカス リクエストの例を次に示します。

//Create focus
ret = mAudioManager
.requestAudioFocus(mFocusListener,
mMusicAudioAttrib,AudioManager.AUDIOFOCUS_GAIN, 0);

if (ret == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { Log.i(TAG, "Got focus for usage " + mMusicAudioAttrib.getUsage()); start(); } else { Log.i(TAG, "MediaPlayer denied focus for usage " + mMusicAudioAttrib.getUsage()); }

これは、サードパーティ アプリがフォーカスをリクエストする方法と同じです。したがって、サードパーティ アプリは、オーディオ ゾーン機能を引き続き使用できますが、ゾーン管理は OEM アプリ ランチャーまたはその他の管理アプリで行う必要があります。

複数のゾーンへの同時ストリーミング

単一のゾーンにストリーミングするアプリの場合、音声フォーカスはアプリの観点から見て同じように動作します。また、ゾーン管理は CarAudioManager.setZoneIdForUid を使用して設定できます。ただし、アプリが複数のゾーンで同時にオーディオを再生する場合は、次のようにバンドルに AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID を含めて、ゾーンごとにフォーカスをリクエストする必要があります。

//Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneIdForDisplayId);

mMusicAudioAttribForDisplay = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .addBundle(bundle) .build();
//Create focus