Многие современные конструкции транспортных средств содержат несколько электронных блоков управления (ЭБУ) вне информационно-развлекательной системы, которые управляют эргономикой, например настройками сидений и регулировкой зеркал. В соответствии с текущими архитектурами аппаратного обеспечения и питания многие ЭБУ включаются до включения информационно-развлекательной системы на базе Android. Эти ЭБУ могут взаимодействовать с информационно-развлекательной системой на базе Android через уровень абстракции аппаратного обеспечения автомобиля (VHAL) .
Начиная с Android 11, Android Automotive OS (AAOS) представила новый набор свойств VHAL для создания, переключения, удаления и связывания внешних аксессуаров для идентификации пользователей. Например, эти новые свойства позволяют водителю привязать внешний аксессуар, например брелок, к своему пользователю Android. Затем, когда водитель приближается к автомобилю, ЭБУ просыпается и обнаруживает брелок. Этот 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 shell getprop android.car.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 не отвечает, по умолчанию выполняется по истечении периода ожидания (по умолчанию пять секунд), что задерживает загрузку. Если HAL отвечает, но системе Android не удается выполнить действие (например, если достигнуто максимальное количество пользователей), используется поведение по умолчанию. Пример. По умолчанию система Android запускается при загрузке от имени последнего активного пользователя. Если обнаруживается брелок для другого пользователя, ECU отменяет свойство HAL, и во время запуска система Android переключается на запуск от этого указанного пользователя. |
SWITCH_USER (читать/писать) | Это свойство вызывается при переключении активного пользователя Android на переднем плане. Свойство может быть вызвано либо системой Android, либо HAL для запроса переключения пользователя. Три рабочих процесса:
Современный рабочий процесс использует двухфазный подход для обеспечения синхронизации системы Android и внешнего ЭБУ. Когда Android инициирует переключение:
HAL должен дождаться ответа Пример. Во время движения водитель пытается переключить пользователей Android в пользовательском интерфейсе информационно-развлекательной системы. Однако, поскольку настройки автокресла привязаны к пользователю Android, сиденье перемещается при переключении пользователя. Таким образом, ЭБУ управления сиденьями не подтверждает переключение, HAL отвечает отказом, а пользователь Android не переключается. Рабочий процесс Legacy — это односторонний вызов, отправляемый после переключения пользователя (поэтому HAL не может заблокировать переключение). Он вызывается только при загрузке (после первоначального переключения пользователя) или для приложений, вызывающих Пример. Если приложение использует Рабочий процесс транспортного средства берет свое начало из HAL, а не из системы Android:
Пример: Боб использовал брелок Алисы, чтобы открыть машину, и HAL ответил на запрос |
CREATE_USER (читать/писать) | Это свойство вызывается системой Android при создании нового пользователя Android (с использованием API CarUserManager.createUser() ). HAL отвечает Пример. Водитель касается значка информационно-развлекательного интерфейса, чтобы создать нового пользователя Android. При этом запрос отправляется в HAL и остальные подсистемы автомобиля. ЭБУ информируются о вновь созданном пользователе. Затем другие подсистемы и ЭБУ связывают свой внутренний идентификатор пользователя с идентификатором пользователя Android. |
REMOVE_USER (только ПИШИТЕ) | Система Android вызывает это свойство после удаления пользователя Android (с помощью метода CarUserManager.removeUser() ).Это односторонний вызов, ответа от HAL не ожидается. Пример. Водитель нажимает кнопку удаления существующего пользователя Android в пользовательском интерфейсе информационно-развлекательной системы. HAL информируется, а другие подсистемы автомобиля и ЭБУ информируются об удалении пользователя, чтобы они могли удалить свой внутренний идентификатор пользователя. |
Дополнительные свойства
Ниже приведены дополнительные свойства, не связанные с состояниями жизненного цикла пользователя. Каждый из них может быть реализован без поддержки пользовательского HAL.
собственность HAL | Описание |
---|---|
USER_IDENTIFICATION_ASSOCIATION (читать/писать) | Используйте это свойство, чтобы связать любого пользователя Android с механизмом идентификации, например брелоком или телефоном. Используйте это же свойство для get или set ассоциаций. Пример. Водитель касается значка информационно-развлекательного интерфейса, чтобы связать брелок, используемый для открытия автомобиля ( |
Вспомогательные библиотеки
Все объекты, используемые в сообщениях запроса и ответа (такие как UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
и т. д.), имеют представление высокого уровня с использованием struct
C++, но удаление должно быть сведено к стандартным объектам VehiclePropValue
(см. примеры ниже). Для простоты разработки в AOSP предусмотрена вспомогательная библиотека C++ для автоматического преобразования structs
User HAL в VehiclePropValue
(и наоборот).
Примеры
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 }
SWITCH_USER
Фактическое имя классов и свойств немного отличается, но общий рабочий процесс тот же, что показано на рисунке:
Рис. 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) }
CREATE_USER
Пример запроса
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) }
USER_IDENTIFICATION_ASSOCIATION
Пример установки (брелок, связанный с пользователем 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 }