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()
|
|
VehiclePropConfigs getPropConfigs(in int[] props)
|
|
void getValues(IVehicleCallback callback, in GetValueRequests requests)
GetValueRequest de manière asynchrone. Le résultat est fourni via la méthode de rappel onGetValues . |
|
void setValues(IVehicleCallback callback, in SetValueRequests requests)
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)
maxSharedMemoryFileCount n'est pas utilisé. |
|
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
|
|
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
|
|
(Nouveau dans Android 16)SupportedValuesListResults getSupportedValuesLists(in List
|
|
(Nouveauté d'Android 16)MinMaxSupportedValueResults getMinMaxSupportedValue(in List
|
|
void registerSupportedValueChangeCallback(in IVehicleCallback callback, in List
|
|
void unregisterSupportedValueChangeCallback(in IVehicleCallback callback, in List
|
Les rappels sont définis sur IVehicleCallback.aidl
et contiennent ces méthodes.
Méthode | |
---|---|
oneway void onGetValues(in GetValueResults responses)
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)
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)
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".ON_CHANGE , un événement de propriété se produit lorsque la valeur ou l'état d'une propriété changent.VehiclePropValue avec un état "indisponible" ou "erreur" et une valeur vide doit être transmis.SharedMemoryFileCount est toujours 0 . |
|
oneway void onPropertySetError(in VehiclePropErrors errors)
onSetValues avec un résultat d'erreur doit être utilisé à la place. |
|
oneway void onSupportedValueChange(in List
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 deVehiclePropConfigs
. La structure utilise la fonctionwriteToParcel
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::vectorresults = getResults(); GetValueResults parcelableResults; ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults); if (status.isOk()) { // Send parcelableResults through callback. } else { // Handle error. }