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

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

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

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

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

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

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

  2. Завершите переключение пользователя Android.

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

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

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

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

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

Рабочий процесс Vehicle происходит из 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 (с помощью 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
}