Nhiều cấu trúc xe hiện tại chứa nhiều bộ điều khiển điện tử (ECU) bên ngoài hệ thống thông tin giải trí để kiểm soát công thái học, chẳng hạn như cài đặt ghế ngồi và điều chỉnh gương. Dựa trên kiến trúc phần cứng và nguồn điện hiện tại, nhiều ECU khởi động trước khi hệ thống thông tin giải trí dựa trên Android bật nguồn. Các ECU này có thể giao tiếp với hệ thống thông tin giải trí dựa trên Android thông qua Lớp trừu tượng phần cứng xe (VHAL) .
Bắt đầu từ Android 11, Android Automotive OS (AAOS) đã giới thiệu một bộ thuộc tính mới trên VHAL để tạo, chuyển đổi, xóa và liên kết các phụ kiện bên ngoài nhằm nhận dạng Người dùng. Ví dụ: các 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ư chìa khóa thông minh, với Người dùng Android của họ. Sau đó, khi người lái xe đến gần xe, ECU sẽ thức dậy và phát hiện chìa khóa điện tử. ECU này cho HAL biết thông tin giải trí nào sẽ bắt đầu khởi động cho Người dùng Android, giúp giảm thời gian người lái xe chờ Người dùng Android của họ tải.
Kích hoạt HAL của người dùng
Thuộc tính HAL của người dùng phải được bật rõ ràng bằng cách đảm bảo thuộc tính hệ thống android.car.user_hal_enabled
được đặt thành true
. (Điều này cũng có thể được thực hiện trong tệp car.mk
, do đó không cần phải đặt thủ công.) Kiểm tra xem user_hal_enabled=true
đã được bật hay chưa bằng cách 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 thuộc tính bị tắt, thông báo như sau sẽ hiển thị khi system_server
khởi động:
I CarServiceHelper: Not using User HAL
Để bật thủ công user_hal_enabled
, hãy đặt thuộc tính hệ thống android.car.user_hal_enabled
và khởi động lại system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
Đầu ra logcat
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 đây cung cấp thông tin HAL cho trạng thái vòng đời của Người dùng, cho phép đồng bộ hóa vòng đời của Người dùng giữa hệ thống Android và ECU bên ngoài. Các thuộc tính này sử dụng 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 người dùng HAL được hỗ trợ, tất cả các thuộc tính sau phải được triển khai.
tài sản HAL | Sự miêu tả |
---|---|
INITIAL_USER_INFO (ĐỌC VIẾT) | Thuộc tính này được hệ thống Android gọi để xác định Người dùng Android nào mà hệ thống khởi động khi thiết bị khởi động hoặc tiếp tục từ chế độ Tạm dừng vào RAM (STR). Khi được gọi, HAL phải phản hồi bằng một trong các tùy chọn sau:
Lưu ý: Nếu HAL không phản hồi thì hành vi mặc định là thực thi sau một khoảng thời gian chờ (năm giây theo mặc định), điều này làm 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 hiện được hành động (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 ở Người dùng hoạt động cuối cùng khi khởi động. Nếu phát hiện thấy chìa khóa thông minh dành cho một Người dùng khác, ECU sẽ ghi đè thuộc tính HAL và trong khi khởi động, hệ thống Android sẽ chuyển sang khởi động ở Người dùng được chỉ định đó. |
SWITCH_USER (ĐỌC VIẾT) | Thuộc tính này được gọi khi chuyển đổi Người dùng Android ở nền trước đang hoạt động. Thuộc tính có thể được hệ thống Android hoặc HAL gọi để yêu cầu chuyển đổi Người dùng. Ba quy trình công việc là:
Quy trình làm việc Hiện đại sử dụng phương pháp cam kết hai giai đoạn để đảm bảo hệ thống Android và ECU bên ngoài được đồng bộ hóa. Khi Android bắt đầu chuyển đổi:
HAL phải đợi cho đến sau phản hồi Ví dụ: Khi đang di chuyển, 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, do cài đặt ghế ô tô gắn liền với Người dùng Android nên ghế sẽ di chuyển trong quá trình 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 bằng lỗi và Người dùng Android không được chuyển đổi. Quy trình làm việc kế thừa là cuộc gọi một chiều được gửi sau khi Người dùng được chuyển đổi (vì vậy HAL không thể chặn chuyển đổi). Nó chỉ được gọi khi khởi động (sau lần chuyển đổi người dùng đầu tiên) hoặc đối với 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, không phải từ hệ thống Android:
Ví dụ: Bob đã sử dụng chìa khóa thông minh của Alice để mở xe và HAL đã trả lời yêu cầu |
CREATE_USER (ĐỌC VIẾT) | Thuộc tính này được hệ thống Android gọi khi Người dùng Android mới được tạo (sử dụng API CarUserManager.createUser() ). HAL phản hồi với Ví dụ: Người lái xe chạm vào 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 tới HAL và các hệ thống con còn lại của xe. ECU được thông báo về Người dùng mới được tạo. Sau đó, các hệ thống con và ECU khác sẽ liên kết ID người dùng nội bộ của chúng với ID người dùng Android. |
REMOVE_USER (Chỉ viết) | Hệ thống Android gọi thuộc tính này sau khi Người dùng Android bị xóa (bằng phương thức CarUserManager.removeUser() ).Đây là cuộc gọi một chiều - không mong đợi phản hồi nào từ HAL. Ví dụ: Người lái xe chạm để xóa Người dùng Android hiện có 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 con và ECU khác của xe được thông báo về việc xóa Người dùng để họ có thể xóa ID người dùng nội bộ của mình. |
Thuộc tính bổ sung
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. Mỗi cái có thể được triển khai mà không cần hỗ trợ HAL của người dùng.
Tài sản HAL | Sự miêu tả |
---|---|
USER_IDENTIFICATION_ASSOCIATION (ĐỌC VIẾT) | 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 cơ chế nhận dạng, chẳng hạn như chìa khóa điện tử hoặc điện thoại. Sử dụng cùng thuộc tính này để get hoặc set các liên kết. Ví dụ: Người lái xe chạm vào biểu tượng giao diện người dùng thông tin giải trí để liên kết chìa khóa thông minh dùng để mở xe ( |
Thư viện trợ giúp
Tất cả các đối tượng được sử dụng trong thông báo yêu cầu và phản hồi (chẳng hạn như UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
, v.v.) đều có biểu diễn cấp cao bằng cách sử dụng struct
C++, nhưng việc loại bỏ phải được làm phẳng thành các đối tượng VehiclePropValue
tiêu chuẩn (xem ví dụ bên dưới). Để dễ phát triển, thư viện trợ giúp C++ được cung cấp trong AOSP để tự động chuyển đổi structs
HAL của người dùng thành VehiclePropValue
(và ngược lại).
Ví dụ
INITIAL_USER_INFO
Ví dụ 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ụ phản hồi (tạo người dùng Quản trị viên)
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
Tên thực tế của các lớp và thuộc tính hơi khác một chút nhưng quy trình làm việc tổng thể giống nhau, như được minh họa bên dưới:
Hình 1. Quy trình làm việc thuộc tính HAL của người dùng
Ví dụ về yêu cầu quy trình làm 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 quy trình làm 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 chuyển đổi quy trình làm 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 chuyển đổi quy trình làm việc hiện đại
Phản hồi này thường xảy ra khi quá trình chuyển đổi Android bị lỗi:
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 làm việc kế thừa
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 làm việc của phương tiện
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 chuyển đổi quy trình làm việc kế thừa
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) }
TẠO NGƯỜI DÙNG
Yêu cầu ví dụ
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ụ 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 }
LOẠI BỎ_USER
Yêu cầu ví dụ
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
Đặt ví dụ (khóa fob đượ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 }