Nhiều kiến trúc xe hiện tại có nhiều bộ điều khiển điện tử (ECU) bên ngoài hệ thống thông tin giải trí điều khiển các thiết bị công thái học, chẳng hạn như ghế ngồi chế độ cài đặt và điều chỉnh đồng bộ hoá hai chiều. Dựa trên phần cứng và nguồn hiện tại nhiều kiến trúc, nhiều ECU được kích hoạt trước hệ thống thông tin giải trí dựa trên Android đã được kích hoạt. Các ECU này có thể giao tiếp với một hệ thống thông tin giải trí dựa trên Android hệ thống thông qua Lớp trừu tượng về phần cứng xe (VHAL).
Kể từ Android 11, Android Automotive OS (AAOS) đã giới thiệu một bộ tính năng mới gồm các thuộc tính trên VHAL để tạo, chuyển đổi, xoá và liên kết phụ kiện bên ngoài để nhận dạng Người dùng. Ví dụ: những thuộc tính mới này cho phép người lái xe để ghép nối một phụ kiện bên ngoài (chẳng hạn như thiết bị điều khiển từ xa cầm tay) với Người dùng Android của mình. Sau đó, khi người lái xe đến gần xe, bộ ECU sẽ đánh thức và phát hiện chìa khoá điện tử. ECU này cho HAL biết thông tin giải trí mà Người dùng Android nên khởi động để giảm thời gian người lái xe đợi thiết bị Android Người dùng cần tải.
Bật HAL (Lớp trừu tượng phần cứng) cho người dùng
Bạn phải bật các thuộc tính HAL của người dùng một cách rõ ràng bằng cách đảm bảo hệ thống
thuộc tính android.car.user_hal_enabled
được đặt thành true
.
(Bạn cũng có thể thực hiện việc này trong tệp car.mk
để không cần
đặt theo cách thủ công). Kiểm tra để đảm bảo rằng bạn đã bật user_hal_enabled=true
bằng
kết xuất UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Bạn cũng có thể kiểm tra user_hal_enabled
bằng cách sử dụng adb shell
getprop android.car.user_hal_enabled
hoặc adb logcat
CarServiceHelper *:s
. Nếu cơ sở lưu trú bị vô hiệu hoá, một thông báo như
sẽ hiển thị thông tin sau đây khi system_server
khởi động:
I CarServiceHelper: Not using User HAL
Để bật user_hal_enabled
theo cách thủ công, hãy đặt
Thuộc tính hệ thống android.car.user_hal_enabled
rồi khởi động lại
system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
Kết quả logcat
sẽ xuất hiện như sau:
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Thuộc tính HAL của người dùng
Thuộc tính vòng đời của người dùng
Các thuộc tính sau cung cấp thông tin HAL cho Vòng đời của người dùng Trạng thái cho phép đồng bộ hoá vòng đời người dùng giữa hệ thống Android và một bộ ECU bên ngoài. Các thuộc tính này sử dụng một giao thức yêu cầu và phản hồi trong hệ thống Android đưa ra yêu cầu bằng cách đặt giá trị thuộc tính và HAL phản hồi bằng cách đưa ra một sự kiện thay đổi thuộc tính.
Lưu ý: Khi HAL người dùng được hỗ trợ, tất cả các điều sau phải được triển khai.
Thuộc tính HAL | Mô tả |
---|---|
INITIAL_USER_INFO (ĐỌC/GHI) |
Thuộc tính này được hệ thống Android gọi để xác định xem Android nào
Người dùng mà hệ thống khởi động khi thiết bị khởi động hoặc tiếp tục từ
Tạm ngưng với RAM (STR). Khi được gọi, HAL phải phản hồi bằng một trong
các tuỳ chọn sau:
Lưu ý: Nếu HAL không phản hồi, thì chế độ mặc định sẽ là thực thi sau một khoảng thời gian chờ (5 giây theo mặc định) để trì hoãn quá trình khởi động. Nếu HAL trả lời nhưng hệ thống Android không thực thi được thao tác đó (ví dụ: nếu đã đạt đến số lượng Người dùng tối đa), thì hành vi mặc định sẽ được sử dụng. Ví dụ: Theo mặc định, hệ thống Android khởi động trong người dùng đang hoạt động khi khởi động. Nếu thiết bị điều khiển từ xa cầm tay của một Người dùng khác được phát hiện, thì ECU ghi đè thuộc tính HAL và trong khi khởi động, hệ thống Android sẽ chuyển sang trong Người dùng được chỉ định đó. |
SWITCH_USER (ĐỌC/GHI) |
Thuộc tính này được gọi khi chuyển đổi Người dùng Android đang hoạt động ở nền trước.
Hệ thống Android hoặc HAL có thể gọi thuộc tính để
yêu cầu chuyển đổi Người dùng. Ba quy trình công việc này là:
Quy trình làm việc hiện đại sử dụng phương pháp cam kết 2 giai đoạn nhằm đảm bảo Hệ thống Android và ECU bên ngoài được đồng bộ hoá. Khi Android bắt đầu nút chuyển:
HAL sẽ đợi cho đến sau Ví dụ: Khi đang chuyển động, người lái xe cố gắng chuyển đổi Người dùng Android trong giao diện người dùng thông tin giải trí. Tuy nhiên, vì ghế ngồi trên ô tô được liên kết với Người dùng Android, ghế sẽ di chuyển trong Chuyển đổi người dùng. Do đó, ECU điều khiển ghế không xác nhận việc chuyển đổi, HAL phản hồi với lỗi và Người dùng Android không được chuyển đổi.
Quy trình làm việc cũ là cuộc gọi một chiều được gửi sau khi Người dùng được chuyển đổi
(để HAL không chặn công tắc). Phương thức này chỉ được gọi khi khởi động (sau khi
chuyển đổi người dùng ban đầu) hoặc cho các ứng dụng gọi
Ví dụ: Nếu một ứng dụng sử dụng
Quy trình làm việc của Xe bắt nguồn từ HAL (Lớp trừu tượng phần cứng), không phải từ hệ thống Android:
Ví dụ: Bob dùng thiết bị điều khiển từ xa cầm tay của Alice để mở ô tô
và HAL đã trả lời yêu cầu |
CREATE_USER (ĐỌC/GHI) |
Thuộc tính này được hệ thống Android gọi khi một Người dùng Android mới
(bằng API CarUserManager.createUser() ).
HAL phản hồi bằng Ví dụ: Một người lái xe nhấn vào một biểu tượng giao diện người dùng thông tin giải trí để tạo Người dùng Android mới. Thao tác này sẽ gửi yêu cầu đến HAL và phần còn lại trong các hệ thống phụ về xe. ECU được thông báo về Người dùng mới tạo. Lý do khác hệ thống con và ECU sau đó liên kết mã nhận dạng người dùng nội bộ với dữ liệu Mã nhận dạng người dùng. |
REMOVE_USER (Chỉ VIẾT) |
Hệ thống Android gọi thuộc tính này sau khi một Người dùng Android
đã xoá (bằng phương thức CarUserManager.removeUser() ).
Đây là cuộc gọi một chiều — dự kiến sẽ không có phản hồi từ HAL. Ví dụ: Người lái xe nhấn để xoá một ô tô hiện có Người dùng Android trong giao diện người dùng thông tin giải trí. HAL được thông báo và các hệ thống phụ và ECU của xe được thông báo về việc Người dùng gỡ bỏ có thể xoá mã nhận dạng người dùng nội bộ của họ. |
Các cơ sở lưu trú khác
Sau đây là các thuộc tính bổ sung, không liên quan đến trạng thái vòng đời của người dùng. Có thể triển khai từng lớp mà không cần hỗ trợ lớp trừu tượng phần cứng (HAL) cho người dùng.
Thuộc tính HAL | Mô tả |
---|---|
USER_IDENTIFICATION_ASSOCIATION (ĐỌC/GHI) |
Sử dụng thuộc tính này để liên kết bất kỳ Người dùng Android nào với thông tin nhận dạng
một cơ chế thiết bị, chẳng hạn như thiết bị điều khiển từ xa cầm tay hoặc điện thoại. Sử dụng cùng thuộc tính này để
Liên kết get hoặc set .
Ví dụ: Một người lái xe nhấn vào một biểu tượng giao diện người dùng thông tin giải trí để liên kết
chìa khoá điện tử dùng để mở xe ( |
Thư viện trợ giúp
Tất cả đối tượng được dùng trong yêu cầu và thông báo phản hồi (chẳng hạn như
UserInfo
, InitialUserInfoRequest
InitialUSerInfoResponse
, v.v.) có giá trị đại diện cao
sử dụng C++ struct
nhưng việc xoá phải được làm phẳng thành
đối tượng VehiclePropValue
chuẩn (xem ví dụ bên dưới). Dành cho dễ dàng
của sự phát triển, một
C++
thư viện trợ giúp được cung cấp trong AOSP để tự động chuyển đổi HAL của người dùng
structs
thành VehiclePropValue
(và ngược lại).
Ví dụ
NGƯỜI DÙNG_THÔNG_ TIN_KHỞI CHẠY
Ví dụ về yêu cầu (trong lần khởi động đầu tiên)
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 }
Ví dụ về phản hồi (tạo người dùng Quản trị)
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 }
NGƯỜI DÙNG CHUYỂN ĐỔI
Tên thực tế của các lớp và thuộc tính có khác một chút, nhưng quy trình làm việc chung là giống nhau, như được minh hoạ dưới đây:
Hình 1. Quy trình thuộc tính HAL (Lớp trừu tượng phần cứng) cho người dùng
Ví dụ về yêu cầu quy trình công việc hiện đại
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) }
Ví dụ về phản hồi của quy trình công việc hiện đại
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 }
Ví dụ về phản hồi sau khi chuyển đổi quy trình công việc hiện đại
Phản hồi này thường xảy ra khi chuyển đổi Android thành công:
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) }
Phản hồi sau khi chuyển đổi quy trình công việc hiện đại
Phản hồi này thường xảy ra khi quá trình chuyển đổi Android không thành công:
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) }
Ví dụ về yêu cầu quy trình công việc cũ
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) }
Ví dụ về yêu cầu quy trình công việc về xe
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 }
Phản hồi sau khi chuyển đổi quy trình công việc cũ
Phản hồi này thường xảy ra khi chuyển đổi Android thành công:
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) }
NGƯỜI DÙNG TẠO
Ví dụ về yêu cầu
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) }
Ví dụ về phản hồi
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
NGƯỜI DÙNG LOẠI BỎ
Ví dụ về yêu cầu
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) }
NGƯỜI DÙNG_IDENTIFICATION_ASSOCIATION
Đặt ví dụ (khoá xác thực được liên kết với Người dùng 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 }