Interface VHAL

Le VHAL AIDL est défini dans android.hardware.automotive.vehicle namespace. L'interface VHAL est définie à 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 minimale compatible de VHAL
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

Nous vous RECOMMANDONS d'implémenter la dernière version de VHAL pour une version d'Android spécifique.

Fonctions et rappels

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

Méthode
VehiclePropConfigs getAllPropConfigs()
Renvoie la liste de toutes les configurations de propriétés compatibles avec ce HAL de véhicule.
VehiclePropConfigs getPropConfigs(in int[] props)
Renvoie une liste de configurations de propriétés pour des ID de propriété 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 la propriété avec les options spécifiées. Les options d'abonnement incluent l'ID de la propriété, l'ID de la zone de la 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ésinscrit les événements de propriété précédemment souscrits pour les propriétés spécifiées.
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
Non utilisé et peut être implémenté comme une opération sans effet.
(Nouveauté d'Android 16)
SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds)
Obtient 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 minimales et maximales 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 compatibles changent.
Introduit dans VHAL v4.
void unregisterSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
Désinscrit le rappel de modification de valeur compatible.
Introduit dans VHAL v4.

Les rappels sont définis à l'emplacement IVehicleCallback.aidl et contiennent ces méthodes.

Méthode
oneway void onGetValues(in GetValueResults responses)
Rappel de la fonction getValues pour obtenir les résultats de la valeur. Appelé lorsque certaines des valeurs à extraire sont prêtes.
oneway void onSetValues(in SetValueResults responses)
Rappel de la fonction setValues pour fournir les résultats de la valeur définie. Appelé lorsque VHAL a terminé de traiter certaines des requêtes de jeu de propriétés.
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount)
Rappel pour signaler les événements de mise à jour des établissements.
CONTINUOUS, un événement de propriété se produit en fonction du taux d'échantillonnage d'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é change.
Cette valeur doit également être utilisée pour transmettre des événements de modification de l'état de la propriété. Par exemple, lorsque la propriété devient indisponible ou qu'une erreur de lecture se produit, un VehiclePropValue avec un état indisponible ou d'erreur et une valeur vide doit être envoyé.
SharedMemoryFileCount est toujours 0.
oneway void onPropertySetError(in VehiclePropErrors errors)
Rappel pour signaler les erreurs de jeu de propriétés asynchrones qui n'ont pas de requête de jeu correspondante. Si nous savons à quelle requête d'ensemble l'erreur est destinée, 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 aux valeurs minimales et maximales 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 de 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é compatibles sont correctes. Le test s'exécute sur toutes les instances VHAL de l'appareil. Toutefois, 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 Horodatage 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 compatibles listées dans la configuration de l'ID de zone, ou 0 pour les établissements globaux.
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 la section Configurations de propriété.
status État de la propriété pour la lecture. Pour les propriétés en lecture/écriture, cela peut également s'appliquer à l'écriture, mais ce n'est pas garanti. 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 être renvoyée avant la fin de l'opération d'obtention ou de définition. 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 transmis via les rappels transmis en tant qu'arguments.

L'implémentation ne doit pas bloquer sur le résultat dans le thread de liaison qui gère la requête. Nous vous recommandons plutôt de stocker la requête dans une file d'attente de requêtes et d'utiliser un thread de gestionnaire distinct pour gérer les requêtes de manière asynchrone. Pour en savoir plus, consultez la section 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 données qui peuvent dépasser les limites du liaisonneur (4 ko dans l'implémentation de la bibliothèque LargeParcelable) au-delà des limites du liaisonneur. Chacune d'elles a une définition de structure similaire, qui contient les champs suivants.

Conseils Description
payloads Liste de valeurs lorsque la taille de la valeur correspond à une limite de mémoire du liaisonneur, ou liste vide.
sharedMemoryFd Descripteur de fichier nullable pointant vers un fichier de mémoire partagée qui stocke les charges utiles sérialisées si la liste de 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 est 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 de wrapper utile pour la bibliothèque dans ParcelableUtils.h.

Par exemple, un client natif analysant les requêtes pour getValues reçues d'un liant est le suivant:

// '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 de VHAL qui envoie des résultats pour getValues via le liaisonneur:

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