Thuộc tính HAL của người dùng

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:
  • Hành vi mặc định do Android đặt (chuyển sang Người dùng được sử dụng gần đây nhất hoặc tạo Người dùng mới nếu đây là lần khởi động đầu tiên).
  • Chuyển sang Người dùng hiện có.
  • Tạo Người dùng mới (với các thuộc tính tùy chọn như tên, cờ, ngôn ngữ hệ thống, v.v.) và chuyển sang Người dùng mới đó.

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à:
  • Hiện đại. Chuyển đổi bắt đầu từ CarUserManager .
  • Di sản. Chuyển đổi bắt đầu từ ActivityManager .
  • Phương tiện giao thông. Được HAL gọi để yêu cầu chuyển đổi Người dùng.

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:

  1. Kiểm tra HAL để xác định xem Người dùng có thể được chuyển đổi hay không.

    HAL phản hồi bằng SUCCESS hoặc FAILURE để Android biết có nên tiếp tục hay không.

  2. Hoàn tất quá trình chuyển đổi Người dùng Android.

    Android gửi phản hồi ANDROID_POST_SWITCH tới HAL để cho biết quá trình chuyển đổi thành công hay thất bại.

HAL phải đợi cho đến sau phản hồi ANDROID_POST_SWITCH để cập nhật trạng thái nhằm đồng bộ hóa ECU hoặc cập nhật các thuộc tính HAL khác.

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 ActivityManager.switchUser() thay vì CarUserManager.switchUser() . Các ứng dụng SettingsSystemUI tham chiếu đã sử dụng ứng dụng sau, nhưng nếu OEM cung cấp ứng dụng Cài đặt của riêng họ để chuyển đổi Người dùng thì OEM nên thay đổi cách sử dụng.

Ví dụ: Nếu một ứng dụng sử dụng ActivityManager.switchUser() để chuyển đổi Người dùng thì lệnh gọi một chiều sẽ được gửi tới HAL để thông báo rằng quá trình chuyển đổi Người dùng đã diễn ra.

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:

  1. HAL yêu cầu chuyển đổi Người dùng.
  2. Hệ thống hoàn tất quá trình chuyển đổi Người dùng Android.
  3. Android gửi phản hồi ANDROID_POST_SWITCH tới HAL để cho biết quá trình chuyển đổi thành công hay thất bại.

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 INITIAL_USER_INFO bằng ID người dùng của Alice. Tiếp theo, ECU cảm biến sinh trắc học đã xác định người lái xe là Bob, do đó Người dùng HAL đã gửi yêu cầu SWITCH_USER để chuyển đổi người dùng.

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 SUCCESS hoặc FAILURE . Nếu HAL phản hồi không thành công, hệ thống Android sẽ xóa Người dùng.

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 ( KEY_123 ) với Người dùng Android đang hoạt động hiện tại ( USER_11 ).

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:

Quy trình làm việc

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
}