現在の車両アーキテクチャの多くには、シート設定やミラー調整などの人間工学を制御する、インフォテインメント システムの外側に複数の電子制御ユニット (ECU) が含まれています。現在のハードウェアおよび電源アーキテクチャに基づいて、Android ベースのインフォテインメント システムの電源が投入される前に、多くの ECU が電源投入されます。これらの ECU は、車両ハードウェア抽象化レイヤー (VHAL)を介して Android ベースのインフォテインメント システムと連携できます。
Android 11 以降、Android Automotive OS (AAOS) では、ユーザーを識別するために外部アクセサリを作成、切り替え、削除、関連付けするための新しいプロパティ セットが VHAL に導入されました。たとえば、これらの新しいプロパティを使用すると、ドライバーはキー フォブなどの外部アクセサリを Android ユーザーにペア接続できます。その後、ドライバーが車両に近づくと、ECU が起動してキーフォブを検出します。この ECU は、インフォテインメントが起動を開始する Android ユーザーを HAL に指示します。これにより、ドライバーが Android ユーザーのロードを待つ時間が短縮されます。
ユーザー HAL を有効にする
ユーザー HAL プロパティは、システム プロパティandroid.car.user_hal_enabled
true
に設定されていることを確認して、明示的に有効にする必要があります。 (これはcar.mk
ファイルでも実行できるため、手動で設定する必要はありません。) UserHalService
をダンプして、 user_hal_enabled=true
が有効になっていることを確認します。
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
adb shell getprop android.car.user_hal_enabled
またはadb logcat CarServiceHelper *:s
を使用してuser_hal_enabled
確認することもできます。このプロパティが無効になっている場合、 system_server
の起動時に次のようなメッセージが表示されます。
I CarServiceHelper: Not using User HAL
user_hal_enabled
手動で有効にするには、 android.car.user_hal_enabled
システム プロパティを設定し、 system_server
を再起動します。
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
logcat
出力は次のように表示されます。
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
ユーザー HAL プロパティ
ユーザーのライフサイクルのプロパティ
次のプロパティは、ユーザー ライフサイクル状態の HAL 情報を提供します。これにより、Android システムと外部 ECU 間のユーザー ライフサイクル同期が可能になります。これらのプロパティはリクエストとレスポンスのプロトコルを使用します。このプロトコルでは、Android システムがプロパティ値を設定してリクエストを行い、HAL がプロパティ変更イベントを発行して応答します。
注:ユーザー HAL がサポートされている場合は、次のプロパティをすべて実装する必要があります。
HAL特性 | 説明 |
---|---|
INITIAL_USER_INFO (読み書き) | このプロパティは、デバイスが起動するとき、または Suspend-to-RAM (STR) から再開するときに、システムが開始する Android ユーザーを決定するために Android システムによって呼び出されます。呼び出されると、HAL は次のいずれかのオプションで応答する必要があります。
注: HAL が応答しない場合、デフォルトの動作ではタイムアウト期間 (デフォルトでは 5 秒) の経過後に実行され、起動が遅れます。 HAL が応答しても、Android システムがアクションの実行に失敗した場合 (たとえば、最大ユーザー数に達した場合)、デフォルトの動作が使用されます。 例:デフォルトでは、Android システムは起動時に最後にアクティブなユーザーで起動します。別のユーザーのキー フォブが検出された場合、ECU は HAL プロパティをオーバーライドし、起動時に Android システムがその指定されたユーザーで起動するように切り替えます。 |
SWITCH_USER (読み書き) | このプロパティは、アクティブなフォアグラウンド Android ユーザーを切り替えるときに呼び出されます。このプロパティは、Android システムまたは HAL によって呼び出され、ユーザーの切り替えを要求できます。 3 つのワークフローは次のとおりです。
最新のワークフローでは、2 フェーズ コミット アプローチを使用して、Android システムと外部 ECU が確実に同期されます。 Android が切り替えを開始すると、次のようになります。
HAL は、ECU を同期したり、他の HAL プロパティを更新したりするために、 例:走行中、ドライバーはインフォテインメント UI で Android ユーザーを切り替えようとします。ただし、カーシートの設定は Android ユーザーに関連付けられているため、ユーザーの切り替え中にシートが移動します。したがって、座席を制御する ECU は切り替えを確認せず、HAL は失敗で応答し、Android ユーザーは切り替えられません。 レガシー ワークフローは、ユーザーが切り替えられた後に送信される一方向の呼び出しです (そのため、HAL は切り替えをブロックできません)。これは、起動時 (最初のユーザー切り替え後) または 例:アプリが Vehicle ワークフローは、Android システムではなく HAL から発生します。
例:ボブはアリスのキーホルダーを使用して車を開け、HAL はアリスのユーザー ID を使用して |
CREATE_USER (読み書き) | このプロパティは、新しい Android ユーザーが作成されるときに ( CarUserManager.createUser() API を使用して) Android システムによって呼び出されます。 HAL は 例:ドライバーがインフォテインメント UI アイコンをタップして、新しい Android ユーザーを作成します。これにより、HAL と残りの車両サブシステムにリクエストが送信されます。 ECU には、新しく作成されたユーザーが通知されます。他のサブシステムと ECU は、内部ユーザー ID を Android ユーザー ID に関連付けます。 |
REMOVE_USER (書き込みのみ) | Android ユーザーが ( CarUserManager.removeUser() メソッドで) 削除された後、Android システムはこのプロパティを呼び出します。これは一方向の呼び出しであり、HAL からの応答は期待されません。 例:ドライバーがインフォテインメント UI で既存の Android ユーザーをタップして削除します。 HAL にはユーザーの削除が通知され、他の車両サブシステムと ECU にもユーザーの削除が通知され、内部ユーザー ID を削除できるようになります。 |
追加のプロパティ
以下は、ユーザーのライフサイクル状態とは関係のない追加のプロパティです。それぞれは、ユーザー HAL をサポートせずに実装できます。
HAL プロパティ | 説明 |
---|---|
USER_IDENTIFICATION_ASSOCIATION (読み書き) | このプロパティを使用して、Android ユーザーをキー フォブや電話などの識別メカニズムに関連付けます。これと同じプロパティを使用して、関連付けをget またはset 。例:ドライバーはインフォテインメント UI アイコンをタップして、車両を開けるために使用されるキー フォブ ( |
ヘルパー ライブラリ
リクエストおよびレスポンス メッセージで使用されるすべてのオブジェクト ( UserInfo
、 InitialUserInfoRequest
、 InitialUSerInfoResponse
など) は C++ struct
を使用した高レベル表現ですが、削除は標準のVehiclePropValue
オブジェクトにフラット化する必要があります (以下の例を参照)。開発を容易にするために、ユーザー HAL structs
VehiclePropValue
(またはその逆) に自動的に変換するC++ ヘルパー ライブラリが AOSP で提供されています。
例
INITIAL_USER_INFO
リクエストの例 (初回起動時)
VehiclePropValue { // flattened from InitialUserInfoRequest prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID [1] = 1 // InitialUserInfoRequestType.FIRST_BOOT [2] = 0 // user id of current user [3] = 1 // flags of current user (SYSTEM) [4] = 1 // number of existing users [5] = 0 // existingUser[0].id [6] = 1 // existingUser[0].flags }
応答例(管理者ユーザーの作成)
VehiclePropValue { // flattened from InitialUserInfoResponse prop: 299896583 // INITIAL_USER_INFO prop.values.int32Values: [0] = 1 // Request ID (must match request) [1] = 2 // InitialUserInfoResponseAction.CREATE [2] = -10000 // user id (not used on CREATE) [3] = 8 // user flags (ADMIN) prop.values.stringValue: "en-US||Car Owner" // User locale and User name }
SWITCH_USER
クラスとプロパティの実際の名前は若干異なりますが、以下に示すように、全体的なワークフローは同じです。
図 1.ユーザー HAL プロパティのワークフロー
最新のワークフロー リクエストの例
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896585 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID [1] = 2 // SwitchUserMessageType::ANDROID_SWITCH ("modern") [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
最新のワークフローの応答例
VehiclePropValue { // flattened from SwitchUserResponse prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // SwitchUserMessageType::VEHICLE_RESPONSE [2] = 1 // SwitchUserStatus::SUCCESS }
最新のワークフローの切り替え後の応答例
この応答は通常、Android の切り替えが成功したときに発生します。
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
最新のワークフローの切り替え後の対応
この応答は通常、Android スイッチに障害が発生したときに発生します。
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 42 // Request ID (must match "pre"-SWITCH_USER request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 10,8 // current user id (10) and flags (ADMIN) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
従来のワークフロー リクエストの例
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = 2 // Request ID [1] = 1 // SwitchUserMessageType::LEGACY_ANDROID_SWITCH [2,3] = 10,8 // target user id (10) and flags (ADMIN) [4,5] = 0,1 // current user id (0) and flags (SYSTEM) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
車両ワークフローリクエストの例
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must be negative) [1] = 4 // SwitchUserMessageType::VEHICLE_REQUEST [2] = 11 // target user id }
従来のワークフローの切り替え後の対応
この応答は通常、Android の切り替えが成功したときに発生します。
VehiclePropValue { // flattened from SwitchUserRequest prop: 299896584 // SWITCH_USER prop.values.int32Values: [0] = -108 // Request ID (must match from vehicle request ) [1] = 5 // SwitchUserMessageType::ANDROID_POST_SWITCH [2,3] = 11,0 // target user id (11) and flags (none in this case) [4,5] = 11,0 // current user id (11) and flags (none in this case) [6] = 3 // number of existing users (0, 10, 11) [7,8] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [9,10] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [11,12] = 11,0 // existingUser[2] (id=11, flags=NONE) }
ユーザーを作成
リクエスト例
VehiclePropValue { // flattened from CreateUserRequest prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,6 // Android id of the created user and flags (id=11, flags=GUEST, EPHEMERAL) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 3 // number of existing users (0, 10, 11) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) [10,11] = 11,6 // newUser[2] (id=11, flags=GUEST,EPHEMERAL) }
応答例
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
REMOVE_USER
リクエスト例
VehiclePropValue { // flattened from RemoveUserRequest prop: 299896586 // REMOVE_USER prop.values.int32Values: [0] = 42 // Request ID [1,2] = 11,0 // Android id of the removed user and flags (none in this case) [3,4] = 10,0 // current user id (10) and flags (none in this case) [5] = 2 // number of existing users (0, 10) [6,7] = 0,1 // existingUser[0] (id=0, flags=SYSTEM) [8,9] = 10,8 // existingUser[1] (id=10, flags=ADMIN) }
USER_IDENTIFICATION_ASSOCIATION
セット例 (User 10 に関連付けられたキーフォブ)
VehiclePropValue { // flattened from UserIdentificationSetRequest prop: 299896587 // USER_IDENTIFICATION_ASSOCIATION prop.values.int32Values: [0] = 43 // Request ID [1,2] = 10,0 // Android id (10) and flags (none in this case) [3] = 1 // number of associations being set [4] = 1 // 1st type: UserIdentificationAssociationType::KEY_FOB [5] = 1 // 1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER }