Propriétés HAL de l'utilisateur

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 les réglages des rétroviseurs. Sur la base des architectures matérielles et d'alimentation actuelles, de nombreux calculateurs s'allument avant que le système d'infodivertissement basé sur Android ne soit mis sous tension. Ces ECU 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 pour 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 le porte-clés. Cet ECU indique au HAL quel utilisateur Android l'infodivertissement doit démarrer un démarrage, ce qui réduit le temps qu'un conducteur attend que son utilisateur Android se charge.

Activer l'utilisateur HAL

Les propriétés User HAL doivent être explicitement activées en s'assurant 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 , de sorte qu'il n'est pas nécessaire de le définir manuellement.) Vérifiez que user_hal_enabled=true est activé en 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 semblable au suivant 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 de l'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 ECU externe. Ces propriétés utilisent un protocole de demande et de réponse, dans lequel le système Android fait une demande en définissant une valeur de propriété et la HAL répond en émettant un événement de changement de propriété.

Remarque : Lorsque User HAL est pris en charge, toutes les propriétés suivantes doivent être implémentées.

Propriété HAL La 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émarrera lorsque l'appareil démarrera ou reprendra à partir de Suspend-to-RAM (STR). Lorsqu'il est appelé, le HAL doit répondre avec l'une de ces options :
  • Le comportement par défaut défini par Android (passage au dernier utilisateur utilisé ou création d'un nouvel utilisateur s'il s'agit du premier démarrage).
  • Passez à un utilisateur existant.
  • Créez un nouvel utilisateur (avec les propriétés facultatives de nom, indicateurs, paramètres régionaux du système, etc.) et passez à ce nouvel utilisateur.

Remarque : si HAL ne répond pas, le comportement par défaut est de s'exécuter après un délai d'attente (cinq (5) 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é.

Par exemple, par défaut, le système Android démarre dans 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 bascule 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 par le système Android ou par HAL pour demander un changement d'utilisateur. Les trois flux de travail sont :
  • Moderne. Commutateur démarré à partir de CarUserManager .
  • Héritage. Commutateur démarré à partir d ActivityManager .
  • Véhicule. Appelé par HAL pour demander un changement d'utilisateur.

Le flux de travail moderne utilise une approche de validation en deux phases pour s'assurer que le système Android et l'ECU externe sont synchronisés. Lorsqu'Android initie le basculement :

  1. Vérifiez le HAL pour déterminer si l'utilisateur peut être changé.

    Le HAL répond par SUCCESS ou FAILURE , afin qu'Android sache s'il faut continuer ou non.

  2. Terminez le changement d'utilisateur Android.

    Android envoie une réponse ANDROID_POST_SWITCH à HAL pour indiquer le succès ou l'échec du changement.

Le HAL doit attendre après la réponse ANDROID_POST_SWITCH pour mettre à jour son état pour synchroniser les ECU ou mettre à jour d'autres propriétés HAL.

Par exemple, alors qu'il est en mouvement, un conducteur tente de changer d'utilisateur Android dans l'interface utilisateur d'infodivertissement. Cependant, étant donné que les paramètres du siège auto sont liés à l'utilisateur Android, le siège se déplacera 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 flux de travail hérité est un appel unidirectionnel envoyé après le changement d'utilisateur (la 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 ActivityManager.switchUser() au lieu de CarUserManager.switchUser() . Les applications Settings et SystemUI de référence utilisent déjà cette dernière, mais si un OEM fournit ses propres applications Paramètres pour changer d'utilisateur, les OEM doivent modifier l'utilisation.

Par exemple, si une application utilise ActivityManager.switchUser() pour changer d'utilisateur, un appel unidirectionnel est envoyé à HAL pour informer qu'un changement d'utilisateur a eu lieu.

Le flux de travail Véhicule provient de HAL, pas du système Android :

  1. Le HAL demande un changement d'utilisateur.
  2. Le système termine le changement d'utilisateur Android.
  3. Android envoie une réponse ANDROID_POST_SWITCH à HAL pour indiquer le succès ou l'échec du changement.

Par exemple , Bob a utilisé le porte-clés d'Alice pour ouvrir la voiture et HAL a répondu à la demande INITIAL_USER_INFO avec l'ID utilisateur d'Alice. Ensuite, un ECU de capteur biométrique a identifié le conducteur comme étant Bob, de sorte que l'utilisateur HAL a envoyé une demande SWITCH_USER pour changer d'utilisateur.

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() ).

La HAL répond par SUCCESS ou FAILURE . Si HAL répond par un échec, le système Android supprime l'utilisateur.

Par exemple, un conducteur appuie sur une icône d'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 du nouvel utilisateur créé. D'autres sous-systèmes et ECU associent ensuite leur ID utilisateur interne à l'ID utilisateur Android.

REMOVE_USER
(ECRITURE uniquement)
Le système Android appelle cette propriété après la suppression d'un utilisateur Android (avec l'API CarUserManager.removeUser() ).

Il s'agit d'un appel à sens unique — aucune réponse n'est attendue de la HAL.

Par 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 ID utilisateur interne.

Propriétés supplémentaires

Les propriétés supplémentaires suivantes ne sont pas liées aux états du cycle de vie de l'utilisateur. Chacun peut être implémenté sans prendre en charge l'utilisateur HAL.

Propriété HAL La description
USER_IDENTIFICATION_ASSOCIATION
(LIRE ÉCRIRE)
Utilisez cette propriété pour associer tout 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.

Par exemple, un conducteur appuie sur une icône d'interface utilisateur d'infodivertissement pour associer le porte-clés utilisé pour ouvrir le véhicule (KEY_123) à l'utilisateur Android actif actuel (USER_11).

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 de C++ struct , mais la suppression doit être aplatie en 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 les structs HAL utilisateur 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 :

Flux de travail

Figure 1. Flux de travail des propriétés HAL de l'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 workflow 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-commutation 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-switch 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 flux de travail 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-commutation du flux de travail hérité

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 d'ensemble (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
}