Interface VHAL

L'AIDL VHAL est défini dans android.hardware.automotive.vehicle namespace. L'interface VHAL est définie sur IVehicle.aidl. Sauf indication contraire, toutes les méthodes doivent être implémentées pour une version VHAL spécifique.

Versions

Version d'Android Dernière version de VHAL Dernière version de la propriété VHAL Version VHAL minimale compatible
Android 16 V4 V4 V1
Android 15 V3 V3 V1
Android 14 V2 V2 V1
Android 13 V1 (Interface de propriété VHAL non fractionnée) V1

Il est RECOMMANDÉ d'implémenter la dernière version de VHAL pour une version Android spécifique.

Fonctions et rappels

Les fonctions VHAL sont définies sur IVehicle.aidl.

Méthode
VehiclePropConfigs getAllPropConfigs()
Renvoie la liste de toutes les configurations de propriétés acceptées par ce HAL du véhicule.
VehiclePropConfigs getPropConfigs(in int[] props)
Renvoie une liste de configurations de propriétés pour les ID de propriétés donnés.
void getValues(IVehicleCallback callback, in GetValueRequests requests)
Obtenez les valeurs des propriétés du véhicule de manière asynchrone. Gère un lot de GetValueRequest de manière asynchrone. Le résultat est fourni via la méthode de rappel onGetValues.
void setValues(IVehicleCallback callback, in SetValueRequests requests)
Définissez les valeurs des propriétés du véhicule de manière asynchrone. Gère un lot de SetValueRequest de manière asynchrone. Le résultat est fourni via la méthode de rappel onSetValues.
void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options, int maxSharedMemoryFileCount)
S'abonne aux événements de propriété avec les options spécifiées. Les options d'abonnement incluent l'ID de propriété, l'ID de zone de propriété et la fréquence d'échantillonnage en Hz (pour une propriété continue). maxSharedMemoryFileCount n'est pas utilisé.
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
Désabonne les événements de propriété auxquels l'utilisateur s'était abonné précédemment pour les propriétés spécifiées.
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
Non utilisé et peut être implémenté comme no-op.
(Nouveau dans Android 16)
SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds)
Récupère les listes de valeurs acceptées pour les paires d'ID de propriété et d'ID de zone spécifiées.
Introduit dans VHAL V4.
(Nouveauté d'Android 16)
MinMaxSupportedValueResults getMinMaxSupportedValue(in List propIdAreaIds)
Obtient les valeurs minimale et maximale acceptées pour les paires d'ID de propriété et d'ID de zone spécifiées.
Introduit dans VHAL V4.
void registerSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
Enregistre un rappel à appeler lorsque les valeurs acceptées changent.
Introduit dans VHAL V4.
void unregisterSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
Désinscrit le rappel de modification de la valeur acceptée.
Introduit dans VHAL V4.

Les rappels sont définis sur IVehicleCallback.aidl et contiennent ces méthodes.

Méthode
oneway void onGetValues(in GetValueResults responses)
Callback pour la fonction getValues afin de fournir les résultats de la valeur get. Appelée lorsque certaines des valeurs à récupérer sont prêtes.
oneway void onSetValues(in SetValueResults responses)
Rappel pour la fonction setValues afin de fournir les résultats de la valeur définie. Appelé lorsque VHAL a terminé de traiter certaines des demandes de définition de propriété.
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount)
Rappel pour signaler les événements de mise à jour de la propriété.
CONTINUOUS, un événement de propriété se produit en fonction du taux d'échantillonnage de l'abonnement en Hz ou de la fréquence des messages du bus du véhicule. Un événement de propriété peut également se produire si l'état d'une propriété change. Par exemple, de "non disponible" à "disponible".
Pour la propriété ON_CHANGE, un événement de propriété se produit lorsque la valeur ou l'état d'une propriété changent.
Cette méthode doit également être utilisée pour transmettre les événements de changement d'état des propriétés. Par exemple, lorsqu'une propriété devient indisponible ou génère une erreur de lecture, un VehiclePropValue avec un état "indisponible" ou "erreur" et une valeur vide doit être transmis.
SharedMemoryFileCount est toujours 0.
oneway void onPropertySetError(in VehiclePropErrors errors)
Rappel pour signaler les erreurs de définition de propriété asynchrones qui n'ont pas de requête de définition correspondante. Si nous savons pour quelle requête Set l'erreur s'est produite, onSetValues avec un résultat d'erreur doit être utilisé à la place.
oneway void onSupportedValueChange(in List propIdAreaIds)
Rappel pour signaler les modifications apportées à la valeur minimale et maximale acceptées ou à la liste des valeurs acceptées. L'appelant est censé appeler getMinMaxSupportedValue ou getSupportedValuesLists pour obtenir les valeurs mises à jour.

L'implémentation VHAL est validée par le VTS VHAL à l'adresse VtsHalAutomotiveVehicle_TargetTest.cpp.

Le test vérifie que les méthodes de base sont implémentées correctement et que les configurations de propriétés compatibles sont correctes. Le test s'exécute sur toutes les instances VHAL de l'appareil, mais AAOS n'utilise que l'instance par défaut (android.hardware.automotive.vehicle.IVehicle/default).

Valeur de la propriété du véhicule

Utilisez la structure VehiclePropValue pour décrire la valeur de chaque propriété, qui comporte les champs suivants :

Champ Description
timestamp Code temporel représentant l'heure à laquelle l'événement s'est produit et synchronisé avec l'horloge SystemClock.elapsedRealtimeNano().
prop ID de la propriété pour cette valeur.
areaid ID de la zone pour cette valeur. La zone doit être l'une des zones acceptées listées dans la configuration de l'ID de zone, ou 0 pour les propriétés globales.
value Structure de données contenant la valeur réelle de la propriété. En fonction du type de propriété, un ou plusieurs champs de ce champ sont utilisés pour stocker la valeur réelle. Par exemple, le premier élément de value.int32Values est utilisé pour les propriétés de type Int32. Pour en savoir plus, consultez Configurations des propriétés.
status État de la propriété pour la lecture. Pour une propriété en lecture/écriture, cela peut également s'appliquer à l'écriture, mais sans garantie. Par exemple, la propriété peut être disponible en lecture, mais pas en écriture. Dans ce cas, l'état est AVAILABLE et le champ de valeur contient des informations valides. Pour connaître les états possibles, consultez VehiclePropertyStatus.

getValues et setValues asynchrones

Les opérations getValues et setValues sont effectuées de manière asynchrone, ce qui signifie que la fonction peut renvoyer des données avant la fin de l'opération get ou set. Les résultats de l'opération (par exemple, la valeur de la propriété pour getValues et l'état de réussite ou d'erreur pour setValues) sont fournis par le biais des rappels transmis en tant qu'arguments.

L'implémentation ne doit pas bloquer le résultat dans le thread Binder qui gère la requête. Nous vous recommandons plutôt de stocker la requête dans une file d'attente et d'utiliser un thread de gestionnaire distinct pour traiter les requêtes de manière asynchrone. Pour en savoir plus, consultez l'implémentation de référence.

Figure 1 : Processus asynchrone.

Parcelables volumineux

Toutes les structures nommées XXXs, telles que VehiclePropConfigs, SetValueRequests et VehiclePropValues, sont appelées LargeParcelable (ou StableLargeParcelable). Chacune représente une liste de valeurs utilisées pour transmettre de grandes quantités de données qui peuvent dépasser les limites du binder (4 ko dans l'implémentation de la bibliothèque LargeParcelable) au-delà des limites du binder. Chacun d'eux a une définition de structure similaire qui contient les champs suivants.

Conseils Description
payloads Liste de valeurs lorsque la taille de la valeur est compatible avec la limite de mémoire du binder, ou liste vide.
sharedMemoryFd Descripteur de fichier pouvant être nul, pointant vers un fichier de mémoire partagée qui stocke les charges utiles sérialisées si la liste des valeurs est trop longue.

Par exemple, VehiclePropConfigs est défini comme suit :

parcelable VehiclePropConfigs {
    // The list of vehicle property configs if they fit the binder memory
    // limitation.
    VehiclePropConfig[] payloads;
    // Shared memory file to store configs if they exceed binder memory
    // limitation. Created by VHAL, readable only at client. Client could keep
    // the fd opened or keep the FD mapped to access configs.
    @nullable ParcelFileDescriptor sharedMemoryFd;
}

VehiclePropConfigs contient des charges utiles non vides ou un sharedMemoryFd non nul.

  • Si payloads n'est pas vide, il stocke une liste des données réelles, qui correspond à la configuration de la propriété.
  • Si sharedMemoryFd n'est pas nul, il contient un fichier de mémoire partagée qui stocke la structure sérialisée de VehiclePropConfigs. La structure utilise la fonction writeToParcel pour sérialiser un Parcel.

En tant que client Java pour VHAL, Car Service gère la sérialisation et la désérialisation pour LargeParcelable. Pour les implémentations VHAL et les clients natifs, un LargeParcelable doit être sérialisé et désérialisé avec la bibliothèque LargeParcelable ou une classe wrapper utile pour la bibliothèque dans ParcelableUtils.h.

Par exemple, un client natif qui analyse les requêtes pour getValues reçues d'un binder se présente comme suit :

// 'requests' are from the binder.
GetValueRequests requests;
expected<LargeParcelableBase::BorrowedOwnedObject, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests);
if (deserializedResults.ok()) {
    const std::vector& getValueRequests = deserializedResults.value().getObject()->payloads;
    // Use the getValueRequests.
  } else {
    // handle error.
}

Vous trouverez ci-dessous un exemple d'implémentation VHAL qui envoie les résultats pour getValues via le binder :

std::vector results = getResults();
GetValueResults parcelableResults;
ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
if (status.isOk()) {
    // Send parcelableResults through callback.
} else {
    // Handle error.
}