用戶 HAL 屬性

許多當前的車輛架構在信息娛樂系統之外包含多個電子控制單元 (ECU),用於控制人體工程學,例如座椅設置和後視鏡調節。基於當前的硬件和電源架構,許多 ECU 在基於 Android 的信息娛樂系統上電之前先上電。這些ECU可以與通過一個基於Android信息娛樂系統接口車輛硬件抽象層(VHAL) 。

從 Android 11 開始,Android Automotive OS (AAOS) 在 VHAL 上引入了一組新屬性,用於創建、切換、移除和關聯外部附件以識別用戶。例如,這些新的屬性使得駕駛員能夠成對配合的外部附件,例如密鑰卡,到Android用戶。然後,當駕駛員靠近車輛時,ECU 會喚醒並檢測遙控鑰匙。該 ECU 向 HAL 指示信息娛樂系統應該啟動哪個 Android 用戶,從而減少驅動程序等待其 Android 用戶加載的時間。

啟用用戶 HAL

用戶HAL屬性必須確保系統屬性明確啟用android.car.user_hal_enabled設置為true 。 (這也可以在完成car.mk文件,因此它不需要手動設置。)檢查user_hal_enabled=true被傾倒啟用UserHalService

$ adb shell dumpsys car_service --hal UserHalService|grep enabled
user_hal_enabled=true

您還可以檢查user_hal_enabled使用亞行外殼getprop android.car.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 通過發出屬性更改事件進行響應。

注意:當用戶HAL支持,以下所有屬性必須得到執行。

哈爾地產描述
INITIAL_USER_INFO
(讀/寫)
該屬性由 Android 系統調用,以確定當設備從 Suspend-to-RAM (STR) 啟動或恢復時系統將啟動哪個 Android 用戶。調用時,HAL 必須使用以下選項之一進行響應:
  • Android 設置的默認行為(切換到上次使用的用戶或如果這是第一次啟動則創建新用戶)。
  • 切換到現有用戶。
  • 創建一個新用戶(具有名稱、標誌、系統區域設置等可選屬性)並切換到該新用戶。

注意:如果HAL不響應,默認行為是超時時間(默認為五(5)秒),其延遲開機後執行。如果 HAL 確實回復了,但 Android 系統無法執行該操作(例如,如果已達到最大用戶數),則使用默認行為。

例如,默認情況下,Android系統在啟動時啟動的最後一項活動的用戶。如果檢測到不同用戶的遙控鑰匙,ECU 會覆蓋 HAL 屬性,並且在啟動期間,Android 系統切換到以該指定用戶啟動。

SWITCH_USER
(讀/寫)
在切換活躍的前台 Android 用戶時調用此屬性。該屬性可以由 Android 系統或 HAL 調用以請求用戶切換。這三個工作流程是:
  • 現代的。交換機從開始CarUserManager
  • 遺產。交換機從開始ActivityManager
  • 車輛。由 HAL 調用以請求用戶切換。

Modern 工作流使用兩階段提交方法來確保 Android 系統和外部 ECU 同步。當 Android 啟動切換時:

  1. 檢查 HAL 以確定是否可以切換用戶。

    該HAL與響應SUCCESSFAILURE ,這樣的Android知道是否繼續或取消。

  2. 完成 Android 用戶切換。

    機器人發送ANDROID_POST_SWITCH響應HAL以指示開關成功或失敗。

該HAL應該等到後ANDROID_POST_SWITCH響應更新其狀態同步的ECU或更新其他HAL性能。

例如,在運動的同時,驅動器的嘗試切換Android用戶在信息娛樂UI。但是,由於汽車座椅設置與 Android 用戶相關聯,因此座椅會在用戶切換期間移動。因此,控制座椅的 ECU 不確認切換,HAL 響應失敗,Android 用戶未切換。

Legacy 工作流是在用戶切換後發送的單向調用(因此 HAL 無法阻止切換)。這只是呼籲啟動(後的初始用戶交換機)或應用程序,調用ActivityManager.switchUser()代替CarUserManager.switchUser()基準SettingsSystemUI應用程序已經使用了後者,但如果OEM提供自己設置的應用程序切換用戶,OEM廠商應該改變使用。

例如,如果一個應用程序使用ActivityManager.switchUser()來切換的用戶,然後單向呼叫被發送到HAL以通知用戶交換機已經發生。

Vehicle 工作流源自 HAL,而不是 Android 系統:

  1. HAL 請求用戶切換。
  2. 系統完成Android用戶切換。
  3. 機器人發送ANDROID_POST_SWITCH響應HAL以指示開關成功或失敗。

例如,Bob用Alice的鑰匙開的車和HAL回答了INITIAL_USER_INFO用Alice的用戶ID請求。接著,生物測定傳感器ECU識別出的驅動程序作為鮑勃,所以用戶HAL發送的SWITCH_USER請求開關用戶。

CREATE_USER
(讀/寫)
此屬性是由Android系統,當一個新的Android用戶創建(使用被叫CarUserManager.createUser() API)。

該HAL與響應SUCCESSFAILURE 。如果 HAL 響應失敗,Android 系統將刪除用戶。

例如,駕駛員水龍頭信息娛樂UI圖標來創建一個新的Android用戶。這會向 HAL 和其餘車輛子系統發送請求。 ECU 被告知新創建的用戶。其他子系統和 ECU 然後將其內部用戶 ID 與 Android 用戶 ID 相關聯。

REMOVE_USER
(只寫)
Android系統調用此屬性一個Android用戶被移除之後(與CarUserManager.removeUser() API)。

這是一個單向調用 - 預計 HAL 不會響應。

例如,驅動器抽頭在信息娛樂UI刪除現有的Android用戶。 HAL 會收到通知,其他車輛子系統和 ECU 也會收到有關用戶刪除的通知,以便他們可以刪除其內部用戶 ID。

附加屬性

以下是與用戶生命週期狀態無關的附加屬性。每個都可以在不支持用戶 HAL 的情況下實現。

哈爾地產描述
USER_IDENTIFICATION_ASSOCIATION
(讀/寫)
使用此屬性可將任何 Android 用戶與識別機制(例如遙控鑰匙或電話)相關聯。使用相同的屬性來getset關聯。

例如,驅動器抽頭信息娛樂UI圖標以用於打開車輛(KEY_123)到當前活動的Android用戶(USER_11)智能鑰匙相關聯。

輔助庫

在請求和響應消息中使用的所有對象(諸如UserInfoInitialUserInfoRequestInitialUSerInfoResponse ,等等)具有使用C ++高級表示struct ,但必須去除被平整成標準VehiclePropValue對象(參見下文實施例)。為了便於開發,一個C ++幫助程序庫在AOSP提供自動轉換用戶HAL structsVehiclePropValue (反之亦然)。

例子

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
}