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 つ目のリストではすべてのコンテキストを以下の順序で考慮します。リストは降順です(優先度が高いものが上、低いものが下)。たとえば、ナビゲーション オーディオと音楽オーディオが同時にアクティブな場合、音量ボタンイベント中はナビゲーションの音量が変更されます。
- ナビゲーション
- 通話
- 音楽
- お知らせ
- 音声コマンド
- 着信音
- システム サウンド
- 安全性
- アラーム
- 通知
- 車の状態
- 緊急速報
音量ボタンイベントの管理を簡素にするために、カーオーディオ サービスには 2 つ目のオーディオ コンテキストの優先順位リストがあります。
- 通話
- メディア
- お知らせ
- 音声コマンド
このリストも降順です。2 つ目のリストの目的は、より頻度の高いサウンドをキーイベントを通して変更できるようにすることです。頻度の低い(おそらく持続時間の短い)サウンドは、オーディオ設定 UI でのみ管理できます。
音量の実際のバージョンは、audioVolumeAdjustmentContextsVersion
構成で設定できます。この構成には 1
または 2
を設定できます(2
がデフォルト)。
音量をより柔軟に管理できるように、Android 14 では OemCarAudioVolumeService
が導入されています。
public interface OemCarAudioVolumeService {
OemCarvolumeChangeInfo getSuggestedGroupForVolumeChange(
OemCarAudioVolumeRequest request, int volumeAdjustment);
}
OEM カー音量サービスには、volumeAdjustment
と OemCarAudioVolumeRequest
を受け取る単一のメソッドがあります。
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 カーサービスのリファレンス実装を提供します。これにより、OemCarService
が OemCarAudioFocusService
、OemCarAudioDuckingService
、OemCarAudioVolumeService
とともに実装されます。後者については、各サービスは 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
の場合は準備が整っていません。