使用者 HAL 屬性

許多現有車輛架構都包含多個電子控制單元 (ECU) 是控管人體工學的資訊娛樂系統以外,例如:座位 調整設定和鏡像取決於目前的硬體和電源 開發了 Android 式資訊娛樂系統 已開機。這些 ECU 具有 Android 資訊娛樂系統 將透過 YAML 檔案 車輛硬體抽象層 (VHAL)

從 Android 11 開始,Android Automotive OS (AAOS) 導入了一組全新的 VHAL 上的屬性建立、切換、移除和關聯 用來識別使用者的外部配件舉例來說 驅動程式,可將外部配件 (例如鍵盤遙控) 與 Android 使用者配對。 之後駕駛人靠近車輛時,ECU 便會喚醒並偵測遙控鑰匙。 這個 ECU 會向 Android 使用者指示 HAL 應提供資訊娛樂 藉此縮短驅動程式等待 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

您也可以使用 adb shell getprop android.car.user_hal_enabledadb 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
(讀取/寫入)
Android 系統會呼叫這個屬性,判斷哪個 Android 裝置 使用者啟動或重新啟用裝置時,系統會啟動 暫停對 RAM (STR)。呼叫時,HAL 必須以下列任一值回應: 這些選項:
  • Android 設定的預設行為 (切換至上次使用的時間 如果是第一次啟動,請先建立使用者或建立新使用者)。
  • 切換至現有使用者。
  • 建立新的 User (使用名稱、旗標、系統的選用屬性) 等等) 並切換至新使用者。

注意:如果 HAL 沒有回應,預設行為是 在逾時期限 (預設為五秒) 後執行,這會延遲啟動。 如果 HAL 確實回覆,但 Android 系統無法執行動作 (例如 如果已達到使用者數量上限,系統就會採用預設行為。

範例:根據預設,Android 系統的起始時間為 啟動期間的活躍使用者。如果偵測到其他使用者的遙控車鑰,ECU 會覆寫 HAL 屬性,並且在啟動期間,Android 系統會切換為 指定的授權中。

SWITCH_USER
(讀取/寫入)
切換有效的前景 Android 使用者時,系統會呼叫這個屬性。 這個屬性可由 Android 系統或 HAL 呼叫, 要求切換使用者。這三項工作流程如下:
  • 現代轉移程序已從「CarUserManager」開始。
  • 舊版。轉移程序已從「ActivityManager」開始。
  • 交通工具HAL 呼叫了使用者切換要求。

現代工作流程採用兩階段修訂方法, Android 系統和外部 ECU 會保持同步。Android 啟動轉移作業時:

  1. 檢查 HAL 以決定是否可以切換使用者。

    HAL 會以 SUCCESSFAILURE 回應, Android 會知道是否要繼續。

  2. 完成 Android 使用者切換作業。

    Android 會將 ANDROID_POST_SWITCH 回應傳送至 HAL 表示切換成功或失敗。

HAL 應等到 ANDROID_POST_SWITCH 後 回應更新其狀態以同步處理 ECU 或更新其他 HAL 資源。

例如:駕駛人在移動時 在資訊娛樂使用者介面中切換 Android 使用者。但由於兒童安全座椅 設定會與 Android 使用者相連結,那你在 使用者切換。因此,負責控管座位的 ECU 無法確認切換開關。 HAL 會回應「失敗」,且 Android 使用者未切換。

舊版工作流程是指使用者切換後傳送的單向呼叫 (因此 HAL 無法阻擋切換)。只會在 初始使用者切換) 或呼叫 ActivityManager.switchUser() 取代 CarUserManager.switchUser()。參考資料 SettingsSystemUI 個應用程式已經使用 雖然原始設備製造商 (OEM) 自行提供「設定」應用程式來切換使用者 原始設備製造商 (OEM) 應變更使用方式。

範例:如果應用程式使用 ActivityManager.switchUser() 到 之後,系統會傳送單向通話給 HAL,通知使用者 開關。

車輛工作流程源自 HAL,而非 Android 系統:

  1. HAL 要求切換使用者。
  2. 系統完成 Android 使用者切換作業。
  3. Android 會向 HAL 傳送 ANDROID_POST_SWITCH 回應,以表示 切換成功或失敗

範例:白先生使用 Alice 的遙控車打開汽車 HAL 透過以下方式回覆「INITIAL_USER_INFO」要求: Alice 的使用者 ID。接下來,生物特徵辨識感應器 ECU 識別驅動程式為 Bob, 使用者 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() 方法)。

此為單向呼叫,但 HAL 不會有任何回應。

範例:駕駛人輕觸以移除現有項目 資訊娛樂 UI 中的 Android 使用者。HAL 掌握了充分資訊 使用者將收到車輛子系統和 ECU 相關通知, 才能移除其內部使用者 ID

其他屬性

以下是與使用者生命週期狀態無關的額外屬性。 每個項目都可以實作,但不支援使用者 HAL。

HAL 屬性 說明
USER_IDENTIFICATION_ASSOCIATION
(讀取/寫入)
請使用這個屬性,將任何 Android 使用者與身分識別資訊建立關聯 例如鑰匙或手機使用相同資源 getset 關聯。

範例:一位駕駛人輕觸資訊娛樂 UI 圖示,以便建立關聯 用來打開車輛的鑰匙 (KEY_123),並進入目前的 Android 使用者所在位置 (USER_11).

輔助程式庫

請求和回應訊息中使用的所有物件 (例如 UserInfoInitialUserInfoRequestInitialUSerInfoResponse 等) 具有較高等級的表示法 使用 C++ struct,但移除物件必須分割為 標準 VehiclePropValue 物件 (請參閱以下範例)。便利 C++ Android 開放原始碼計畫提供輔助程式庫,可自動轉換使用者 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
}

SWITCH_使用者

類別和屬性的實際名稱略有不同 整體工作流程保持不變,如下圖所示:

工作流程

圖 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)
}

使用者 ID

設定範例 (與使用者 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
}