インタラクション シーケンスの例

次の自動車用オーディオの例では、車載ヘッドユニットに Android 9 が搭載され、ラジオ アプリケーションとナビゲーション アプリケーションが追加されています。さらに、車載チューナーが外部にルーティングされ、スピーカー経由で再生されます。実際のユースケースによっては、チューナーを Android への入力として処理し、ラジオアプリにチューナーからの読み取りと AudioTrack オブジェクトへの書き込みを指示することをおすすめします。

ユーザーがラジオを起動

このインタラクション シーケンスでは、ユーザーがラジオアプリのプリセット周波数で [再生] を押しても、車両でメディアは再生されません。ラジオアプリは、チューナーがスピーカー経由でサウンドを再生するためにフォーカスを取得する必要があります。

図 1. ラジオがフォーカスを取得し、チューナーがスピーカー経由で再生
  1. ラジオ: 「FM 96.5 にチューニング。」
  2. ラジオ: フォーカス GAIN をリクエストします。
  3. AudioManager: GAIN が付与されます。
  4. ラジオ: createAudioPatch()
  5. ラジオ: 「チューナーの出力を再生。」
  6. 外部にルーティングされるチューナー: ミキサーにより、チューナーからアンプへのオーディオのルーティングが可能になります。

ラジオがナビゲーション プロンプトをダッキング

このインタラクション シーケンスでは、ナビゲーション アプリが次の方向転換をアナウンスするナビゲーション プロンプトを生成したときにラジオが再生されます。このナビゲーション プロンプトを再生するには、ナビゲーション アプリが AudioManager から一時的なフォーカスを取得している必要があります。

図 2. ラジオの再生により、ナビゲーション プロンプトをダッキング
  1. ラジオ: 「チューナーの出力を再生。」
  2. 外部にルーティングされるチューナー: ミキサーにより、チューナーからアンプへのオーディオのルーティングが可能になります。
  3. ナビゲーション: AudioManager からフォーカス GAIN TRANSIENT をリクエストします。
  4. AudioManager: ナビゲーションへの GAIN TRANSIENT。
  5. ナビゲーション: ストリームを開き、パケットを送信します。
    1. ナビゲーション: コンテキスト GUIDANCE が bus1 にルーティングされます。
    2. ミキサー: チューナーにより、スピーカーで bus1 GUIDANCE を再生します。
  6. ナビゲーション: アナウンスが終了し、ストリームを閉じます。
  7. ナビゲーション: フォーカスを破棄します。

AudioManager は、ラジオの再生でダッキングが可能であることを認識し、通常はラジオアプリに通知せずにダッキング要素を音楽ストリームに適用します。ただし、フレームワークのダッキングは、framework/base/core/res/res/values/config.xml をオーバーレイして、config_applyInternalDuckingfalse に設定することでバイパスされるため、引き続き外部チューナーはサウンドを提供し、ラジオアプリは変更を認識しません。ミキサー(HAL の下)は、2 つの入力を結合するとともに、ラジオの再生をダッキングするか、ラジオの再生をリアスピーカーに移動するかを選択できます。

ナビゲーション プロンプトが終了すると、ナビゲーション アプリはフォーカスを解放し、ラジオの再生が再開します。

ユーザーがオーディオ ブック アプリを起動

このインタラクション シーケンスでは、ユーザーがオーディオ ブック アプリを起動すると、ラジオの再生が停止します(音楽ストリーミング アプリで [再生] を押すことも同様のトリガーになります)。

図 3. オーディオ ブックがラジオの再生からフォーカスを取得
  1. オーディオ ブック: AudioManager から GAIN コンテキスト MEDIA をリクエストします。
  2. ラジオがフォーカスを喪失します。
    1. AudioManager: LOSS。
    2. ラジオ: releaseAudioPatch()
  3. オーディオ ブックは次のフォーカスを取得します。
    1. GAIN が付与され、コンテキスト MEDIA が bus0 にルーティングされます。
    2. ストリームを開き、MEDIA パケットを送信します。

オーディオ ブック アプリによるフォーカスのリクエストは一時的なものではないため、以前のフォーカス ホルダー(ラジオアプリ)は永続的なフォーカス喪失を受け取り、ラジオアプリはそれに応答してチューナーへのパッチを破棄します。ミキサーはチューナーのリッスンを停止し、Audio HAL を介して配信される音声の処理を開始します(ラジオからオーディオブックへの移行の一環としてクロスフェードを実行することもできます)。

このインタラクション シーケンスでは、ナビゲーション アプリがナビゲーション プロンプトを生成したときにオーディオ ブックが再生されます。

図 4. ナビゲーション プロンプトがオーディオ ブックの再生からフォーカスを取得
  1. オーディオ ブック: MEDIA パケットをストリーミングし、同時実行にフォーカスしません。
  2. ナビゲーション: GAIN TRANSIENT をリクエストします。
  3. AudioManager: LOSS TRANSIENT。
  4. オーディオ ブック: 停止します。
  5. オーディオ マネージャー: GAIN TRANSIENT が付与されます。
  6. ナビゲーション: ストリームを開き、パケットを送信します。
    1. ナビゲーション: コンテキスト GUIDANCE が bus1 にルーティングされます。
    2. ミキサー: bus1(GUIDANCE)を再生します。
  7. ナビゲーション: アナウンスが終了し、ストリームを閉じます。
  8. ナビゲーション: フォーカスを破棄します。
  9. オーディオ ブック: GAIN。
  10. オーディオ ブック: 再起動します。

元のオーディオ ブック アプリ AudioFocusRequestAudioTrack の開始時に送信)には AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS フラグが含まれているため、AudioManager は、オーディオ ブック アプリのダッキングを処理できないと判断します。代わりに、AudioManagerAUDIOFOCUS_LOSS_TRANSIENT メッセージをオーディオ ブック アプリに送信しますが、その応答として再生が一時停止することが予想されます。

これで、ナビゲーション アプリは、ナビゲーション プロンプトを中断なく再生できるようになりました。ナビゲーション プロンプトが終了すると、オーディオ ブックはフォーカスを再取得し、再生を再開します。