De nombreuses architectures de véhicules actuelles contiennent plusieurs unités de commande électroniques (ECU) en dehors du système d'infodivertissement qui contrôlent l'ergonomie, comme les réglages des sièges et des rétroviseurs. Sur la base des architectures matérielles et électriques actuelles, de nombreux calculateurs s'allument avant que le système d'infodivertissement basé sur Android ne soit mis sous tension. Ces calculateurs peuvent s'interfacer avec un système d'infodivertissement basé sur Android via la couche d'abstraction matérielle du véhicule (VHAL) .
À partir d'Android 11, Android Automotive OS (AAOS) a introduit un nouvel ensemble de propriétés sur le VHAL pour créer, changer, supprimer et associer des accessoires externes afin d'identifier les utilisateurs. Par exemple, ces nouvelles propriétés permettent à un conducteur d' associer un accessoire externe, tel qu'un porte-clés, à son utilisateur Android. Ensuite, lorsque le conducteur s'approche du véhicule, un ECU se réveille et détecte la télécommande. Cet ECU indique au HAL quel utilisateur Android l'infodivertissement doit démarrer un démarrage, ce qui réduit le temps pendant lequel un pilote attend le chargement de son utilisateur Android.
Activer l'utilisateur HAL
Les propriétés User HAL doivent être explicitement activées en garantissant que la propriété système android.car.user_hal_enabled
est définie sur true
. (Cela peut également être fait dans le fichier car.mk
, afin qu'il ne soit pas nécessaire de le définir manuellement.) Vérifiez que user_hal_enabled=true
est activé en vidant le UserHalService
:
$ adb shell dumpsys car_service --hal UserHalService|grep enabled user_hal_enabled=true
Vous pouvez également vérifier user_hal_enabled
en utilisant adb shell getprop android.car.user_hal_enabled
ou adb logcat CarServiceHelper *:s
. Si la propriété est désactivée, un message comme celui-ci s'affiche au démarrage system_server
:
I CarServiceHelper: Not using User HAL
Pour activer manuellement user_hal_enabled
, définissez la propriété système android.car.user_hal_enabled
et redémarrez system_server
:
$ adb shell setprop android.car.user_hal_enabled true $ adb shell stop && adb shell start
La sortie logcat
apparaît comme suit :
I CarServiceHelper: User HAL enabled with timeout of 5000ms D CarServiceHelper: Got result from HAL: OK I CarServiceHelper: User HAL returned DEFAULT behavior
Propriétés HAL utilisateur
Propriétés du cycle de vie de l'utilisateur
Les propriétés suivantes fournissent les informations HAL pour les états du cycle de vie de l'utilisateur, qui permettent la synchronisation du cycle de vie de l'utilisateur entre le système Android et un calculateur externe. Ces propriétés utilisent un protocole de requête et de réponse, dans lequel le système Android effectue une requête en définissant une valeur de propriété et le HAL répond en émettant un événement de changement de propriété.
Remarque : Lorsque l'utilisateur HAL est pris en charge, toutes les propriétés suivantes doivent être implémentées.
Propriété HAL | Description |
---|---|
INITIAL_USER_INFO (LIRE ÉCRIRE) | Cette propriété est appelée par le système Android pour déterminer quel utilisateur Android le système démarre lorsque l'appareil démarre ou reprend depuis la suspension vers la RAM (STR). Lorsqu'il est appelé, le HAL doit répondre avec l'une de ces options :
Remarque : Si HAL ne répond pas, le comportement par défaut consiste à s'exécuter après un délai d'attente (cinq secondes par défaut), ce qui retarde le démarrage. Si HAL répond, mais que le système Android ne parvient pas à exécuter l'action (par exemple, si le nombre maximum d'utilisateurs a été atteint), le comportement par défaut est utilisé. Exemple : Par défaut, le système Android démarre avec le dernier utilisateur actif au démarrage. Si un porte-clés pour un autre utilisateur est détecté, l'ECU remplace la propriété HAL et, lors du démarrage, le système Android passe pour démarrer dans cet utilisateur spécifié. |
SWITCH_USER (LIRE ÉCRIRE) | Cette propriété est appelée lors du changement d’utilisateur Android actif au premier plan. La propriété peut être appelée soit par le système Android, soit par HAL pour demander un changement d'utilisateur. Les trois flux de travail sont :
Le flux de travail moderne utilise une approche de validation en deux phases pour garantir la synchronisation du système Android et de l'ECU externe. Lorsqu'Android lance le changement :
Le HAL doit attendre la réponse Exemple : en mouvement, un conducteur tente de changer d'utilisateur Android dans l'interface utilisateur d'infodivertissement. Cependant, comme les paramètres du siège auto sont liés à l'utilisateur Android, le siège bouge pendant le changement d'utilisateur. Ainsi, l'ECU contrôlant les sièges ne confirme pas le changement, le HAL répond par un échec et l'utilisateur Android n'est pas commuté. Le workflow hérité est un appel unidirectionnel envoyé après le changement d'utilisateur (le HAL ne peut donc pas bloquer le changement). Il n'est appelé qu'au démarrage (après le changement d'utilisateur initial) ou pour les applications qui appellent Exemple : si une application utilise Le workflow Véhicule provient de HAL, et non du système Android :
Exemple : Bob a utilisé le porte-clés d'Alice pour ouvrir la voiture et le HAL a répondu à la requête |
CREATE_USER (LIRE ÉCRIRE) | Cette propriété est appelée par le système Android lorsqu'un nouvel utilisateur Android est créé (à l'aide de l'API CarUserManager.createUser() ). Le HAL répond par Exemple : un conducteur appuie sur une icône de l'interface utilisateur d'infodivertissement pour créer un nouvel utilisateur Android. Cela envoie une demande au HAL et au reste des sous-systèmes du véhicule. Les calculateurs sont informés de l'utilisateur nouvellement créé. D'autres sous-systèmes et calculateurs associent ensuite leur identifiant d'utilisateur interne à l'identifiant d'utilisateur Android. |
REMOVE_USER (ÉCRITURE seulement) | Le système Android appelle cette propriété après la suppression d'un utilisateur Android (avec la méthode CarUserManager.removeUser() ).Il s'agit d'un appel à sens unique : aucune réponse n'est attendue de la part du HAL. Exemple : un conducteur appuie pour supprimer un utilisateur Android existant dans l'interface utilisateur d'infodivertissement. Le HAL est informé et les autres sous-systèmes et ECU du véhicule sont informés de la suppression de l'utilisateur afin qu'ils puissent supprimer leur identifiant d'utilisateur interne. |
Propriétés supplémentaires
Les propriétés suivantes sont des propriétés supplémentaires, sans rapport avec les états du cycle de vie de l'utilisateur. Chacun peut être implémenté sans prendre en charge le HAL utilisateur.
Propriété HAL | Description |
---|---|
USER_IDENTIFICATION_ASSOCIATION (LIRE ÉCRIRE) | Utilisez cette propriété pour associer n'importe quel utilisateur Android à un mécanisme d'identification, tel qu'un porte-clés ou un téléphone. Utilisez cette même propriété pour get ou set des associations. Exemple : un conducteur appuie sur une icône de l'interface utilisateur d'infodivertissement pour associer le porte-clés utilisé pour ouvrir le véhicule ( |
Bibliothèques d'assistance
Tous les objets utilisés dans les messages de demande et de réponse (tels que UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
, etc.) ont une représentation de haut niveau à l'aide struct
C++, mais la suppression doit être aplatie dans des objets VehiclePropValue
standard (voir les exemples ci-dessous). Pour faciliter le développement, une bibliothèque d'assistance C++ est fournie dans AOSP pour convertir automatiquement structs
User HAL en VehiclePropValue
(et vice versa).
Exemples
INITIAL_USER_INFO
Exemple de requête (au premier démarrage)
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 }
Exemple de réponse (créer un utilisateur administrateur)
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 }
CHANGER D'UTILISATEUR
Le nom réel des classes et des propriétés diffère légèrement, mais le flux de travail global est le même, comme illustré ci-dessous :
Figure 1. Flux de travail des propriétés HAL utilisateur
Exemple de demande de workflow moderne
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) }
Exemple de réponse de flux de travail moderne
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 }
Exemple de réponse post-changement de flux de travail moderne
Cette réponse se produit généralement lorsqu'un changement Android réussit :
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) }
Réponse post-changement de flux de travail moderne
Cette réponse se produit généralement lorsqu'un commutateur Android échoue :
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) }
Exemple de demande de workflow hérité
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) }
Exemple de demande de workflow de véhicule
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 }
Réponse post-changement du flux de travail existant
Cette réponse se produit généralement lorsqu'un changement Android réussit :
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) }
CRÉER UN UTILISATEUR
Exemple de demande
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) }
Exemple de réponse
VehiclePropValue { // flattened from CreateUserResponse prop: 299896585 // CREATE_USER prop.values.int32Values: [0] = 42 // Request ID (must match request) [1] = 3 // CreateUserStatus::SUCCESS }
REMOVE_USER
Exemple de demande
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
Exemple de définition (porte-clés associé à l'utilisateur 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 }