Nhiều kiến trúc xe hiện nay 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í điều khiển công thái học, chẳng hạn như cài đặt ghế và điều chỉnh gương. Dựa trên kiến trúc phần cứng và nguồn hiện tại, nhiều ECU sẽ hoạt động trước khi hệ thống thông tin giải trí dựa trên Android được khởi động. 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, Hệ điều hành Android Ô tô (AAOS) đã giới thiệu một tập hợp các thuộc tính mới trên VHAL để tạo, chuyển đổi, loại bỏ và liên kết các phụ kiện bên ngoài để xác định Người dùng. Ví dụ: các thuộc tính mới này cho phép người lái xe kết nối một phụ kiện bên ngoài, chẳng hạn như một chìa khóa, với Người dùng Android của họ. Sau đó, khi người lái xe đến gần xe, một ECU sẽ đánh thức và phát hiện chìa khóa. ECU này cho HAL biết Người dùng Android nào mà thông tin giải trí sẽ bắt đầu khởi động, điều này làm giảm thời gian người lái xe chờ Người dùng Android của họ tải.
Bật HAL người dùng
Thuộc tính User HAL 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
, vì vậy nó không cần phải được đặt theo cách thủ công.) Kiểm tra xem user_hal_enabled=true
đã được kích hoạt chưa bằng cách kế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 logcat CarServiceHelper *:s
. Nếu thuộc tính bị vô hiệu hóa, mộ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 user_hal_enabled
theo cách thủ công, 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 cung cấp thông tin HAL cho các 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 sự kiện thay đổi thuộc tính.
Lưu ý: Khi User HAL được hỗ trợ, tất cả các thuộc tính sau đây phải được triển khai.
Thuộc tính HAL | Sự mô tả |
---|---|
INITIAL_USER_INFO (ĐỌC VIẾT) | Thuộc tính này được gọi bởi hệ thống Android để xác định Người dùng Android nào mà hệ thống sẽ khởi động khi thiết bị khởi động hoặc tiếp tục từ Suspend-to-RAM (STR). Khi được gọi, HAL phải trả lời bằng một trong các tùy chọn sau:
Lưu ý: Nếu HAL không phản hồi, hành vi mặc định là thực thi sau một khoảng thời gian chờ (năm (5) giây theo mặc định), điều này sẽ làm chậm quá trình khởi động. Nếu HAL trả lời, nhưng hệ thống Android không thực hiện 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 khóa cho một Người dùng khác, ECU sẽ ghi đè thuộc tính HAL và trong quá trình 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 Người dùng Android nền trước đang hoạt động. Thuộc tính có thể được gọi bởi hệ thống Android hoặc bởi HAL để yêu cầu chuyển đổi Người dùng. Ba quy trình làm 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 Người dùng Android trong giao diện người dùng thông tin giải trí. Tuy nhiên, vì cài đặt ghế trên ô tô được gắn với Người dùng Android, 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 với lỗi và Người dùng Android không được chuyển. Dòng công việc Kế thừa là một 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 ban đầu) 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 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 gọi bởi hệ thống Android khi Người dùng Android mới được tạo (sử dụng API CarUserManager.createUser() ). HAL trả lời Ví dụ: người lái xe nhấn 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. Điều này sẽ gửi một yêu cầu đến HAL và phần còn lại của hệ thống phụ 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 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 (với API CarUserManager.removeUser() ).Đây là cuộc gọi một chiều - không có phản hồi từ HAL. Ví dụ: trình điều khiển nhấn để 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 phụ và ECU của xe khác được thông báo về việc Người dùng bị loại bỏ để 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 thứ có thể được triển khai mà không cần hỗ trợ User HAL.
Thuộc tính HAL | Sự mô 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ư khóa hoặc điện thoại. Sử dụng cùng một thuộc tính này để get hoặc set các liên kết.Ví dụ: người lái xe nhấn 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 được sử dụng để mở xe (KEY_123) với Người dùng Android đang hoạt động hiện tại (USER_11). |
Thư viện người 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.) 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 các ví dụ bên dưới). Để dễ phát triển, một 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).
Các ví dụ
INITIAL_USER_INFO
Yêu cầu ví dụ (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 }
SWITCH_USER
Tên thực tế của các lớp và thuộc tính khác nhau một chút nhưng quy trình làm việc tổng thể 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 quy trình làm việc hiện đại sau khi chuyển đổi
Phản hồi này thường xảy ra khi công tắc 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 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 công việc cho 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 khi chuyển đổi quy trình công 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ụ 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 }
REMOVE_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ụ (key fob 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 }