Многие современные архитектуры транспортных средств содержат несколько электронных блоков управления (ЭБУ) вне информационно-развлекательной системы, которые управляют эргономикой, например, настройками сидений и регулировкой зеркал. Основываясь на текущем аппаратном обеспечении и архитектуре питания, многие ЭБУ включаются до включения информационно-развлекательной системы на базе Android. Эти ECU могут взаимодействовать с информационно-развлекательной системой на базе Android через уровень абстракции аппаратного обеспечения автомобиля (VHAL) .
Начиная с Android 11, Android Automotive OS (AAOS) представила новый набор свойств в VHAL для создания, переключения, удаления и связывания внешних аксессуаров для идентификации пользователей. Например, эти новые свойства позволяют водителю связать внешний аксессуар, например брелок, со своим пользователем Android. Затем, когда водитель приближается к автомобилю, ECU просыпается и обнаруживает брелок. Этот ECU указывает HAL, у какого пользователя Android информационно-развлекательная система должна начать загрузку, что сокращает время ожидания драйвером загрузки своего пользователя Android.
Включить пользовательский HAL
Свойства User 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
Вы также можете проверить user_hal_enabled
, используя adb logcat CarServiceHelper *:s
. Если свойство отключено, при 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 система запустит при загрузке устройства или выходе из режима ожидания в ОЗУ (STR). При вызове HAL должен ответить одним из следующих вариантов:
Примечание. Если HAL не отвечает, поведение по умолчанию заключается в выполнении после периода ожидания (пять (5) секунд по умолчанию), что задерживает загрузку. Если HAL отвечает, но системе Android не удается выполнить действие (например, если достигнуто максимальное количество пользователей), используется поведение по умолчанию. Например, по умолчанию система Android запускается последним активным пользователем при загрузке. Если обнаруживается брелок для другого пользователя, ECU переопределяет свойство HAL, и во время запуска система Android переключается на запуск в этом указанном пользователе. |
SWITCH_USER (ЧИТАЙ ПИШИ) | Это свойство вызывается при переключении активного пользователя Android переднего плана. Свойство может быть вызвано либо системой Android, либо HAL для запроса переключения пользователя. Три рабочих процесса:
Современный рабочий процесс использует двухэтапный подход фиксации для обеспечения синхронизации системы Android и внешнего ECU. Когда Android инициирует переключение:
HAL должен дождаться ответа Например, во время движения водитель пытается переключить пользователей Android в информационно-развлекательном интерфейсе. Однако, поскольку настройки автокресла привязаны к пользователю Android, сиденье будет перемещаться во время переключения пользователя. Таким образом, ЭБУ, управляющий сиденьями, не подтверждает переключение, HAL отвечает отказом, а пользователь Android не переключается. Устаревший рабочий процесс — это односторонний вызов, отправляемый после переключения пользователя (поэтому HAL не может заблокировать переключение). Он вызывается только при загрузке (после первоначального переключения пользователя) или для приложений, которые вызывают Например, если приложение использует Рабочий процесс Vehicle происходит из HAL, а не из системы Android:
Например , Боб использовал брелок Алисы, чтобы открыть машину, и HAL ответил на запрос |
CREATE_USER (ЧИТАЙ ПИШИ) | Это свойство вызывается системой Android при создании нового пользователя Android (с использованием API CarUserManager.createUser() ). HAL отвечает Например, водитель нажимает на значок информационно-развлекательного интерфейса, чтобы создать нового пользователя Android. Это отправляет запрос в HAL и остальные подсистемы автомобиля. ЭБУ информируются о вновь созданном Пользователе. Затем другие подсистемы и ЭБУ связывают свой внутренний идентификатор пользователя с идентификатором пользователя Android. |
REMOVE_USER (Только ЗАПИСАТЬ) | Система Android вызывает это свойство после удаления пользователя Android (с помощью API CarUserManager.removeUser() ).Это односторонний вызов — ответа от HAL не ожидается. Например, водитель нажимает, чтобы удалить существующего пользователя Android в информационно-развлекательном интерфейсе. HAL информируется, а другие подсистемы автомобиля и ЭБУ информируются об удалении пользователя, чтобы они могли удалить свой внутренний идентификатор пользователя. |
Дополнительные свойства
Ниже приведены дополнительные свойства, не связанные с состояниями жизненного цикла пользователя. Каждый из них может быть реализован без поддержки пользовательского HAL.
HAL-свойство | Описание |
---|---|
USER_IDENTIFICATION_ASSOCIATION (ЧИТАЙ ПИШИ) | Используйте это свойство, чтобы связать любого пользователя Android с механизмом идентификации, таким как брелок или телефон. Используйте это же свойство для get или set ассоциаций.Например, водитель касается значка информационно-развлекательного интерфейса, чтобы связать брелок, использованный для открытия автомобиля (KEY_123), с текущим активным пользователем Android (USER_11). |
Вспомогательные библиотеки
Все объекты, используемые в сообщениях запроса и ответа (например, UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
и т. д.), имеют высокоуровневое представление с использованием struct
C++, но удаление должно быть VehiclePropValue
( см. примеры ниже). Для простоты разработки в AOSP предоставляется вспомогательная библиотека C++ для автоматического преобразования пользовательских структур VehiclePropValue
structs
и наоборот).
Примеры
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 }
ПОМЕНЯТЬ ПОЛЬЗОВАТЕЛЯ
Фактические имена классов и свойств немного отличаются, но общий рабочий процесс такой же, как показано ниже:
Рис. 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) }
ПОЛЬЗОВАТЕЛЬ_ИДЕНТИФИКАЦИЯ_АССОЦИАЦИЯ
Подайте пример (брелок, связанный с Пользователем 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 }