許多當前的車輛架構在信息娛樂系統之外包含多個電子控制單元 (ECU),用於控制人體工程學,例如座椅設置和後視鏡調整。基於當前的硬件和電源架構,許多 ECU 在基於 Android 的信息娛樂系統啟動之前啟動。這些 ECU 可以通過車輛硬件抽象層 (VHAL)與基於 Android 的信息娛樂系統接口。
從 Android 11 開始,Android Automotive OS (AAOS) 在 VHAL 上引入了一組新屬性,用於創建、切換、刪除和關聯外部附件以識別用戶。例如,這些新屬性使驅動程序能夠將外部配件(例如密鑰卡)與其 Android 用戶配對。然後,當駕駛員接近車輛時,ECU 會喚醒並檢測到遙控鑰匙。此 ECU 向 HAL 指示信息娛樂系統應啟動哪個 Android 用戶,從而減少驅動程序等待其 Android 用戶加載的時間。
啟用用戶 HAL
必須通過確保將系統屬性android.car.user_hal_enabled
設置為true
來顯式啟用 User HAL 屬性。 (這也可以在car.mk
文件中完成,因此不需要手動設置。)通過轉儲UserHalService
檢查是否啟用了user_hal_enabled=true
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
您還可以使用檢查user_hal_enabled
adb logcat CarServiceHelper *:s
。如果該屬性被禁用, 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 通過發出屬性更改事件來響應。
注意:當支持 User HAL 時,必須實現以下所有屬性。
HAL 屬性 | 描述 |
---|---|
INITIAL_USER_INFO (讀/寫) | Android 系統調用此屬性來確定當設備從 Suspend-to-RAM (STR) 啟動或恢復時系統將啟動哪個 Android 用戶。調用時,HAL 必須使用以下選項之一進行響應:
注意:如果 HAL 沒有響應,默認行為是在超時時間(默認為五 (5) 秒)後執行,這會延遲啟動。如果 HAL 確實回復了,但 Android 系統未能執行該操作(例如,如果已達到最大用戶數),則使用默認行為。 例如,默認情況下,Android 系統在啟動時以最後一個活動用戶啟動。如果檢測到不同用戶的密鑰卡,ECU 會覆蓋 HAL 屬性,並且在啟動期間,Android 系統會切換到在該指定用戶中啟動。 |
SWITCH_USER (讀/寫) | 該屬性在切換活躍的前台 Android 用戶時被調用。 Android 系統或 HAL 都可以調用該屬性來請求用戶切換。這三個工作流程是:
Modern 工作流程使用兩階段提交方法來確保 Android 系統和外部 ECU 同步。當 Android 發起切換時:
HAL 應等到 例如,在行駛過程中,駕駛員嘗試在信息娛樂 UI 中切換 Android 用戶。但是,由於汽車座椅設置與 Android 用戶相關聯,因此座椅會在用戶切換期間移動。因此,控制座椅的 ECU 不確認切換,HAL 以失敗響應,Android 用戶未切換。 Legacy 工作流是用戶切換後發送的單向調用(因此 HAL 無法阻止切換)。它僅在啟動時調用(在初始用戶切換之後)或調用 例如,如果一個應用使用 Vehicle 工作流程源自 HAL,而非 Android 系統:
例如,Bob 使用 Alice 的密鑰卡打開汽車,HAL 使用 Alice 的用戶 ID 回复 |
CREATE_USER (讀/寫) | 此屬性由 Android 系統在創建新的 Android 用戶時調用(使用CarUserManager.createUser() API)。 HAL 以 例如,駕駛員點擊信息娛樂 UI 圖標來創建新的 Android 用戶。這會向 HAL 和其他車輛子系統發送請求。 ECU 被告知新創建的用戶。然後,其他子系統和 ECU 將其內部用戶 ID 與 Android 用戶 ID 相關聯。 |
REMOVE_USER (只寫) | Android 系統會在移除 Android 用戶後調用此屬性(使用CarUserManager.removeUser() API)。這是一個單向調用 - 預計 HAL 不會響應。 例如,駕駛員在信息娛樂 UI 中點擊以刪除現有的 Android 用戶。通知 HAL 並通知其他車輛子系統和 ECU 用戶刪除,以便他們可以刪除其內部用戶 ID。 |
附加屬性
以下是與用戶生命週期狀態無關的附加屬性。每個都可以在不支持用戶 HAL 的情況下實現。
HAL 屬性 | 描述 |
---|---|
USER_IDENTIFICATION_ASSOCIATION (讀/寫) | 使用此屬性可將任何 Android 用戶與識別機制相關聯,例如密鑰卡或電話。使用相同的屬性來get 或set 關聯。例如,駕駛員點擊信息娛樂 UI 圖標以將用於打開車輛的密鑰卡 (KEY_123) 與當前活動的 Android 用戶 (USER_11) 相關聯。 |
助手庫
請求和響應消息中使用的所有對象(例如UserInfo
、 InitialUserInfoRequest
、 InitialUSerInfoResponse
等)都使用 C++ struct
進行高級表示,但必須將刪除平面化為標準VehiclePropValue
對象(參見下面的示例)。為了便於開發,AOSP 中提供了一個C++ 幫助程序庫,用於自動將 User HAL structs
轉換為VehiclePropValue
(反之亦然)。
例子
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 }
切換用戶
類和屬性的實際名稱略有不同,但整體工作流程相同,如下圖所示:
圖 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
設置示例(與用戶 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 }