カーオーディオのプラグイン サービス

Android 14 の新しいカー OEM プラグイン サービスでは、いくつかのカー コンポーネントが設定できます。特にオーディオについては、3 つの新しいプラグイン サービスが導入され、OEM が AAOS デバイスのオーディオ管理を柔軟に設定できるようになりました。

  • 音声フォーカス制御
  • 音量とミュートの制御
  • オーディオ ダッキング制御

カープラグイン サービスのアーキテクチャ

下の図は、カーサービスの概要と OEM カーサービスとの関係を示しています。アプリプロセスやカーサービス プロセスと同様に、OEM カーサービス プロセスも独自のプロセス空間を占めています。

画像

カーサービスは、config_oemCarService で定義されたコンポーネントを見つけることで OEM カーサービスを開始します。config が空の場合、OEM サービスは存在せずサービスは開始されません。コンポーネントは OemCarService を拡張する必要があります。カーオーディオ サービスは、カーオーディオ OEM サービスを取得する API を上書きする必要があります。

public final class OemCarServiceImp extends OemCarService {
    @Override
    public OemCarAudioFocusService getOemAudioFocusService();

    @Override
    public OemCarAudioDuckingService getOemAudioDuckingService();

    @Override
    public OemCarAudioVolumeService getOemAudioVolumeService();
}

については、packages/services/Car/tests/OemCarServiceTestApp で定義されるリファレンス テストアプリをご覧ください。

このサービスはカーサービスによって起動されますが、カーオーディオ サービスで利用可能な権限は自動的には継承されません。そのため、OEM サービスで必要な権限は、適切なメカニズムで取得する必要があります。例については、packages/services/Car/data/etc/com.android.car.oemcarservice.testapp.xml をご覧ください。

OEM サービス アーキテクチャによるカーオーディオ サービス

AAOS では、カーオーディオ サービスは次のアクションを管理します。

  • オーディオ ルーティング
  • 音声フォーカス
  • オーディオ ダッキング
  • 音量とミュート

Android 14 より前では、この動作はほぼ静的で、ケースが非常に限られたものの、設定を通してのみ変更できました。Android 14 では、カーオーディオ サービスが、管理対象の OEM 定義コンポーネントと通信するためのメカニズムが導入されました。

  • 音声フォーカス
  • オーディオ ダッキング
  • 音量とミュート

下の図は、カーオーディオ サービスとカー OEM サービスの簡略化したアーキテクチャを示しています。カーオーディオ サービスは、カー OEM オーディオ サービスを呼び出してオーディオの動作を管理できるさまざまなフックを定義します。カー OEM オーディオ サービスによる管理は、対応する OEM カーオーディオ サービス コンポーネントが定義されている場合にのみ行われます。それ以外の場合、カーオーディオ サービスはデフォルトの動作を使用します。

画像

カーオーディオ サービスとカー OEM オーディオ サービスが常に同期するように、カーオーディオ サービスは呼び出しごとに、オーディオ スタックの現在の状態の必要な部分をカー OEM オーディオ サービスに渡します。たとえば、カーオーディオ サービスは音声フォーカスを評価するリクエストをインターセプトすると、スタックの現在の状態をカー OEM オーディオ サービスに渡します。現在の状態には、現在のフォーカス ホルダーと現在のフォーカス ルーザーが含まれます。フォーカス ルーザーは、まだスタックの一部ではあるものの、一時的にフォーカスを失ったフォーカス リクエストです。

カーオーディオ サービスは、車内のすべてのオーディオ アクティビティを管理する必要があります。カーオーディオ サービスがオーディオ動作の一部を管理していない場合、カー OEM オーディオ サービスに公開される情報は不完全な情報になります。たとえば、OEM が独自の音声フォーカス ポリシーを登録することで、カーサービスの音声フォーカス処理を上書きした場合、カーオーディオ サービスはカー OEM オーディオ サービスに完全な情報を提供できません。カーオーディオ サービスではアクセスできない情報が欠けている可能性があるため、カー OEM オーディオ サービスの判断能力に影響を与える可能性があります。

アクションを実行するために、カーオーディオ サービスは OEM カーサービスを呼び出します。これらの呼び出しはプロセス間で行われるため、プロセス間通信(IPC)が必要となります。IPC は各呼び出しにレイテンシを追加します。OEM サービスのレイテンシを最小限に抑えることが重要です。

カーオーディオ サービスから OEM サービスへの呼び出しはレイテンシを発生させるため、OEM サービスは直接 API 評価でカーオーディオ サービスを呼び出すべきではありません。その代わり、カーオーディオ サービスは必要な情報を提供し、2 つのプロセス間の呼び出しが一方向のみで行えるようにします。

OEM カーオーディオ サービスの定義

OEM カー音声フォーカス サービス

カーオーディオ サービスは、オーディオ ポリシー フォーカス リスナーを登録することで、アプリからの音声フォーカス リクエストを管理します。カーオーディオ サービスには、静的なインタラクション マトリックスに基づいてフォーカスの動作を管理するメカニズムがあります。このマトリックスでは 3 種類のインタラクションが定義されています。

  • 同時インタラクション。フォーカス ホルダーは同時にフォーカスを維持できます。

  • 排他的インタラクション。受信フォーカス リクエストは、現在のフォーカス ホルダーからフォーカスを取得します。

  • 拒否インタラクション。受信フォーカス リクエストは現在のフォーカス ホルダーに基づき拒否されます。

自動車のユースケースではこれで十分な場合もありますが、OEM の要件によって異なる可能性のあるインタラクションのニーズをすべて満たすものではありません。そのために、OemCarAudioFocusService を導入します。

public interface OEmCarAudioFocusService {
    OemCarAuddioFocusResults evaluateAudioFocusRequest(
        OemCarAudioFocusEvaluationRequest request);
    
    void notifyAudioFocusChange(
        List<AudioFocusEntry> holder,
        List<AudioFocusEntry> losers, int zoneId);
}

API evaluateAudioFocusRequest は、評価する必要がある音声フォーカスのリクエストがあるときはいつでも、カーオーディオ サービスから呼び出されます。この API は結果を返すためにブロックする双方向 API です。リクエストには、オーディオ スタックの現在の状態に関する情報が含まれます。

この情報を使用し、focusHolders の現在のフォーカス ホルダーおよび focusLosers の現在のフォーカス ルーザーと比較して newFocusRequest を評価できます。API は次の形式で結果を返します。

class OemCarAudioFocusResult {
    int audioZoneId;
    int audioFocusEvaluationResults;
    AudioFocusEntry focusResult;
    List<AudioFocusEntry> newLosers;
    List<AudioFocusEntry> newlyBlocked;
}

これには、現在のリクエストが許可されたか、遅延されたか、または失敗したかを示す、audioFocusEvaluationResults の実際の評価結果に関する情報が含まれます。現在のフォーカス スタックにおける変更は、スタック変更の性質に応じて、newLosers エントリと newlyBlocked エントリで設定する必要があります。

newLosers は、以前フォーカスを保持していたものの、現在は永続的あるいは一時的にフォーカスを喪失するべきエントリを含みます。永続的にフォーカスを喪失すると、音声フォーカス スタックからも削除されます。一時的にフォーカスを喪失すると、フォーカスを取り戻すか、元のフォーカス リクエスト者から放棄されるまで、現在のフォーカス ルーザー スタックに移動されます。いずれにしても、リクエストのフォーカス リスナーが、対応するフォーカス喪失を受信します。

newlyBlocked リストには、以前フォーカス ルーザーのリストにあり現在は新しいエントリによってブロックされているエントリが含まれます。ブロックは永続的な場合と一時的な場合があります。永続的なフォーカス ブロックの場合、エントリはスタックから削除され、フォーカス リスナーにフォーカス喪失が送信されます。一時的なフォーカス喪失の場合、エントリはフォーカス ルーザーのスタックに残りますが、新しいフォーカス ブロッカーがそのブロッカー リストに追加されます。フォーカス喪失は、最初にブロックされた際にすでに送信されているので送信されません。リクエストが最終的にブロック解除されるのは、現在のブロッカーがすべて削除されたときか、フォーカスが放棄された場合にスタックから削除されたときです。

2 つ目の API である notifyAudioFocusChange は、すべての音声フォーカス リクエストまたは放棄時に呼び出される一方向の API です。この API は主に、OEM カーオーディオ サービスの動作に影響を与える可能性のあるフォーカスの変更について OEM サービスに通知するために使用されます。

フォーカス評価のガイドライン

AAOS では、音声フォーカスを使用して、オーディオ再生を管理し、ユーザーに最適なエクスペリエンスを提供するためにどのアプリに準拠すべきかを決定します。そのため、OEM プラグイン サービスでは、音声フォーカス リクエストを管理する際に以下の事項を考慮する必要があります。

  • 優先順位の高い音声フォーカス(電話、緊急速報、安全性など)がない場合、アプリが一時的または永続的に音声フォーカスを得られるようにする必要があります。

  • メディア フォーカスがアクティブになっている間:

    • 通話フォーカスをリクエストしたアプリは、同時または排他的にフォーカスを受け取れる必要があります。

    • ナビゲーション フォーカスをリクエストしたアプリは、同時または排他的にフォーカスを受け取れる必要があります。

    • アシスタント フォーカスをリクエストしたアプリは、同時または排他的にフォーカスを受け取れる必要があります。

  • 優先順位の高い音声フォーカス(電話、緊急速報メール、安全性アラートなど)がアクティブの場合、受信した遅延音声フォーカス リクエストを必要に応じて許可または遅延する必要があります。

上記の提案はすべてを網羅しているわけではありませんが、優先度の高いサウンドがアクティブでないとき、フォーカスをリクエストするアプリがフォーカスをより確実に取得できるようになります。優先順位の高いサウンドがアクティブであっても、遅延フォーカス リクエストは尊重され、優先順位の高いサウンドが停止した時点でフォーカスを得られる必要があります。

OEM カー音量サービス

カーオーディオ サービスは、オーディオ システムからの音量調整をリッスンするか、カー入力サービスからの音量キーイベントを直接リッスンすることで、音量キーイベントを管理します。いずれの場合も、カーオーディオ サービスのデフォルトの動作では、アクティブなオーディオ プレーヤーとオーディオ コンテキストの優先順位リストに基づいて、変更する音量グループを決定します。

音量優先順位リストは 2 つ提供されます。1 つ目のリストではすべてのコンテキストを以下の順序で考慮します。リストは降順です(優先度が高いものが上、低いものが下)。たとえば、ナビゲーション オーディオと音楽オーディオが同時にアクティブな場合、音量キーイベント中はナビゲーションの音量が変更されます。

  1. ナビゲーション
  2. 通話
  3. 音楽
  4. お知らせ
  5. 音声コマンド
  6. 着信音
  7. システム サウンド
  8. 安全性
  9. アラーム
  10. 通知
  11. 車の状態
  12. 緊急速報

音量キーイベントの管理を簡素にするために、カーオーディオ サービスには 2 つ目のオーディオ コンテキストの優先順位リストがあります。

  1. 通話
  2. メディア
  3. お知らせ
  4. 音声コマンド

このリストも降順です。2 つ目のリストの目的は、より頻度の高いサウンドをキーイベントを通して変更できるようにすることです。頻度の低い(おそらく持続時間の短い)サウンドは、オーディオ設定 UI でのみ管理できます。

音量の実際のバージョンは、audioVolumeAdjustmentContextsVersion 構成で設定できます。この構成には 1 または 2 を設定できます(2 がデフォルト)。

音量をより柔軟に管理できるように、Android 14 では OemCarAudioVolumeService が導入されています。

public interface OemCarAudioVolumeService {
    OemCarvolumeChangeInfo getSuggestedGroupForVolumeChange(
OemCarAudioVolumeRequest request, int volumeAdjustment);
}

OEM カー音量サービスには、volumeAdjustmentOemCarAudioVolumeRequest を受け取る単一のメソッドがあります。

class OemCarAudioVolumeRequest {
    int audioZoneId;
    int callState;
    List<AudioAttributes> activePlaybackAttributes;
    List<AudioAttributes> duckedAttributes;
    List<CarVolumeGroupInfo> volumeGroupState;
}

リクエストの activePlaybackAttributes はアクティブなオーディオ属性を持ちます。duckedAttributes は現在ダッキングされているすべてのオーディオ属性です。volumeGroupState は、音量グループの現在の状態を持ちます。このリクエストは、オーディオ スタックの現在の状態を表し、どの音量グループを変更すべきかを決定するために使用できます。結果は OemCarVolumeChangeInfo で返されます。

class OemCarVolumeChangeInfo {
    boolean change;
    CarVolumeGroupInfo volumeGroupChanged;
}

change ブール値は、音量が変更されたかどうかを示します。true の場合、変更があり、音量グループを更新する必要があります。volumeGroupChanged は変更すべき実際の音量グループです。このグループは、API に渡された元の volumeAdjustment パラメータに沿って変更する必要があります。たとえば、結果がナビゲーションの音量グループをミュートすべきだと示している場合、ブール値は true になり、返される音量グループはナビゲーションのものとなる必要があります。

OEM カーダッキング サービス

カーオーディオ サービスは、音声フォーカスの変更をモニタリングし、どのオーディオ デバイスをダッキングするかについて AudioControl HAL にシグナルを送信することで、オーディオのダッキングを管理します。フォーカスが変わると、すべてのアクティブなフォーカス ホルダーが評価され、この静的なダッキング ルールのセットに基づいてどれをダッキングすべきかを決定します。

  • 緊急速報音声は通話音声以外をすべてダッキングします
  • 安全性音声は緊急速報音声以外をすべてダッキングします
  • ナビゲーション音声は安全性音声と緊急速報音声以外をすべてダッキングします
  • 通話音声は安全性音声、緊急速報音声、ナビゲーション音声以外をすべてダッキングします
  • Voice は着信音をダッキングします
  • 音楽とお知らせは何に対してもダッキングされる必要があります

これらのルールはすべてを網羅したものではなく、OEM はこれらのガイドラインに基づき、どのようにサウンドをダッキングすべきかを決定する責任があります。OEM は、利用可能な要件に基づいて、これらの推奨事項をより積極的に制御できます。OemCarDuckingService は Android 14 で導入されました。

class OemCarAudioDuckingService {
List<AudioAttributes>   evaluateAttributesToDuck(
        OemCarAudioVolumeRequest request);
}

この API は、音声フォーカスの変更時にカーオーディオ サービスから呼び出されます。OEM カー音量サービスで導入された OemCarAudioVolumeRequest を再利用し、どの属性をダッキングするかを決定するための関連情報を含んでいます。API からダッキングするオーディオ属性のリストは、現在のオーディオ状態と比較されます。

  • 現在ダッキングされているオーディオ属性:

    • リストにある場合、引き続きダッキングされます
    • リストにない場合、ダッキングはオフになります
  • 現在ダッキングされていないオーディオ属性:

    • リストにある場合、ダッキングされます
    • リストにない場合、ダッキングはオフになります

次にカーオーディオ サービスは、オーディオ属性がどのオーディオ出力デバイスに属するかを判断し、それぞれダッキングされたオーディオ出力デバイスリストまたはダッキングされていないオーディオ デバイス リストに追加します。これは最終的に AudioControl HAL に送信され、ハードウェア レベルで必要なダッキングが実行されます。

下の図は、OEM ダッキング サービスが使用されている場合の、フォーカス リクエストのオーディオ ダッキング制御のシーケンス図を簡略化したものです。

画像

アプリがパブリック オーディオ マネージャー API を通じて音声フォーカスの管理をリクエストすると、シーケンスが始まります。リクエストはカーオーディオ サービスに転送され、結果が決定されます。音声フォーカスが決定されると、カーオーディオ サービスはオーディオ ダッキングを評価し、OemCarAudioDuckingService を呼び出してどのオーディオ属性をダッキングすべきかを評価します。evaluateAttributesToDuck API から結果が返されると、ダッキングするオーディオ デバイスが計算され、最後に情報が AudioControl に送信されてオーディオ ハードウェアにダッキングが適用されます。

OEM カーオーディオ サービスのリファレンス実装

AAOS は、packages/services/Car/tests/OemCarServiceTestApp に OEM カーサービスのリファレンス実装を提供します。これにより、OemCarServiceOemCarAudioFocusServiceOemCarAudioDuckingServiceOemCarAudioVolumeService とともに実装されます。後者については、各サービスは XML ファイルを使用して静的動作を読み込みます。たとえば、OemCarAudioFocusServiceImp は、インタラクション マトリックスを含む oem_focus_config.xml を読み込みます。このマトリックスは、evaluateAudioFocusRequest が呼び出されたときに、フォーカス リクエストを評価するために使用されます。

リファレンス テストアプリのデバッグ

OEM カーサービス テストアプリは AOSP ソースコードの一部です。OEM はニーズに応じて変更できます。デバッグを行うには、config_oemCarService 構成を使用してテストアプリを有効にします。

<!-- This is the component name for the OEM customization service. OEM can choose to implement
this service to customize car service behavior for different policies. If OEMs choose to
implement it, they have to implement a service extending OemCarService exposed by car-lib,
and implement the required component services.
If the component name is invalid, CarService would not connect to any OEM service.
Component name can not be a third party package. It should be pre-installed -->
<string name="config_oemCarService" translatable="false">
com.android.car.oemcarservice.testapp/.OemCarServiceImpl
</string>

OEM カーサービスを検証するには、OEM サービスのカーサービス dump コマンドを使用します。

adb shell dumpsys car_service --oem-service

結果は下記の出力のようになる場合があります。

***CarOemProxyService dump***
  mIsFeatureEnabled: true
  mIsOemServiceBound: true
  mIsOemServiceReady: true
  mIsOemServiceConnected: true
  mInitComplete: true
  OEM_CAR_SERVICE_CONNECTED_TIMEOUT_MS: 5000
  OEM_CAR_SERVICE_READY_TIMEOUT_MS: 5000
  mComponentName: com.android.car.oemcarservice.testapp/.OemCarServiceImpl

dump 情報の各バッチの各ブール値は機能とサービスの状態を決定します。たとえば dump 情報 mIsOemServiceReady はサービスが使用できる状態かどうかを指定します。true の場合は使用の準備ができており、false の場合は準備が整っていません。