Пользовательские свойства HAL

Многие современные конструкции транспортных средств содержат несколько электронных блоков управления (ЭБУ) вне информационно-развлекательной системы, которые управляют эргономикой, например настройками сидений и регулировкой зеркал. В соответствии с текущими архитектурами аппаратного обеспечения и питания многие ЭБУ включаются до включения информационно-развлекательной системы на базе 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 должен ответить одним из следующих вариантов:
  • Поведение по умолчанию, установленное Android (переключение на последнего использованного пользователя или создание нового пользователя, если это первая загрузка).
  • Переключиться на существующего пользователя.
  • Создайте нового пользователя (с дополнительными свойствами имени, флагов, языкового стандарта системы и т. д.) и переключитесь на этого нового пользователя.

Примечание. Если HAL не отвечает, по умолчанию выполняется по истечении периода ожидания (по умолчанию пять секунд), что задерживает загрузку. Если HAL отвечает, но системе Android не удается выполнить действие (например, если достигнуто максимальное количество пользователей), используется поведение по умолчанию.

Пример. По умолчанию система Android запускается при загрузке от имени последнего активного пользователя. Если обнаруживается брелок для другого пользователя, ECU отменяет свойство HAL, и во время запуска система Android переключается на запуск от этого указанного пользователя.

SWITCH_USER
(читать/писать)
Это свойство вызывается при переключении активного пользователя Android на переднем плане. Свойство может быть вызвано либо системой Android, либо HAL для запроса переключения пользователя. Три рабочих процесса:
  • Современный. Переключение началось из CarUserManager .
  • Наследие. Переключение началось из ActivityManager .
  • Транспортное средство. Вызывается HAL для запроса переключения пользователя.

Современный рабочий процесс использует двухфазный подход для обеспечения синхронизации системы Android и внешнего ЭБУ. Когда Android инициирует переключение:

  1. Проверьте HAL, чтобы определить, можно ли переключить пользователя.

    HAL отвечает SUCCESS или FAILURE , чтобы Android знал, продолжать или нет.

  2. Завершите смену пользователя Android.

    Android отправляет ответ ANDROID_POST_SWITCH в HAL, чтобы указать успешное или неудачное переключение.

HAL должен дождаться ответа ANDROID_POST_SWITCH , чтобы обновить свое состояние для синхронизации ECU или обновления других свойств HAL.

Пример. Во время движения водитель пытается переключить пользователей Android в пользовательском интерфейсе информационно-развлекательной системы. Однако, поскольку настройки автокресла привязаны к пользователю Android, сиденье перемещается при переключении пользователя. Таким образом, ЭБУ управления сиденьями не подтверждает переключение, HAL отвечает отказом, а пользователь Android не переключается.

Рабочий процесс Legacy — это односторонний вызов, отправляемый после переключения пользователя (поэтому HAL не может заблокировать переключение). Он вызывается только при загрузке (после первоначального переключения пользователя) или для приложений, вызывающих ActivityManager.switchUser() вместо CarUserManager.switchUser() . Эталонные приложения Settings и SystemUI уже используют последнее, но если OEM-производитель предоставляет свои собственные приложения «Настройки» для переключения пользователей, OEM-производители должны изменить использование.

Пример. Если приложение использует ActivityManager.switchUser() для переключения пользователей, то в HAL отправляется односторонний вызов, чтобы сообщить, что переключение пользователя произошло.

Рабочий процесс транспортного средства берет свое начало из HAL, а не из системы Android:

  1. HAL запрашивает смену пользователя.
  2. Система завершает переключение пользователя Android.
  3. Android отправляет ответ ANDROID_POST_SWITCH в HAL, чтобы указать успешное или неудачное переключение.

Пример: Боб использовал брелок Алисы, чтобы открыть машину, и HAL ответил на запрос INITIAL_USER_INFO идентификатором пользователя Алисы. Затем ЭБУ биометрического датчика идентифицировал водителя как Боба, поэтому пользователь HAL отправил запрос SWITCH_USER для переключения пользователей.

CREATE_USER
(читать/писать)
Это свойство вызывается системой Android при создании нового пользователя Android (с использованием API CarUserManager.createUser() ).

HAL отвечает SUCCESS или FAILURE . Если HAL отвечает с ошибкой, система Android удаляет пользователя.

Пример. Водитель касается значка информационно-развлекательного интерфейса, чтобы создать нового пользователя Android. При этом запрос отправляется в HAL и остальные подсистемы автомобиля. ЭБУ информируются о вновь созданном пользователе. Затем другие подсистемы и ЭБУ связывают свой внутренний идентификатор пользователя с идентификатором пользователя Android.

REMOVE_USER
(только ПИШИТЕ)
Система Android вызывает это свойство после удаления пользователя Android (с помощью метода 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++ для автоматического преобразования 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
}