Interfaccia VHAL

L'AIDL VHAL è definito in android.hardware.automotive.vehicle namespace. L'interfaccia VHAL è definita in IVehicle.aidl. Se non diversamente specificato, tutti i metodi devono essere implementati per una versione VHAL specifica.

Versioni

Versione di Android Ultima versione di VHAL Ultima versione della proprietà VHAL Versione VHAL minima compatibile
Android 16 V4 V4 V1
Android 15 V3 V3 V1
Android 14 V2 V2 V1
Android 13 V1 (Interfaccia proprietà VHAL non suddivisa) V1

È CONSIGLIATO implementare l'ultima versione di VHAL per una versione specifica di Android.

Funzioni e callback

Le funzioni VHAL sono definite in IVehicle.aidl.

Metodo
VehiclePropConfigs getAllPropConfigs()
Restituisce un elenco di tutte le configurazioni delle proprietà supportate da questo HAL del veicolo.
VehiclePropConfigs getPropConfigs(in int[] props)
Restituisce un elenco di configurazioni delle proprietà per gli ID proprietà specificati.
void getValues(IVehicleCallback callback, in GetValueRequests requests)
Recupera in modo asincrono i valori delle proprietà del veicolo. Gestisce un batch di GetValueRequest in modo asincrono. Il risultato viene fornito tramite il metodo di callback onGetValues.
void setValues(IVehicleCallback callback, in SetValueRequests requests)
Imposta i valori delle proprietà del veicolo in modo asincrono. Gestisce un batch di SetValueRequest in modo asincrono. Il risultato viene fornito tramite il metodo di callback onSetValues.
void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options, int maxSharedMemoryFileCount)
Si abbona agli eventi della proprietà con le opzioni specificate. Le opzioni di abbonamento includono l'ID proprietà, l'ID area proprietà e la frequenza di campionamento in Hz (per una proprietà continua). maxSharedMemoryFileCount non viene utilizzato.
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
Annulla l'iscrizione agli eventi delle proprietà a cui era stata effettuata l'iscrizione in precedenza per le proprietà specificate.
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
Non utilizzato e può essere implementato come no-op.
(Novità di Android 16)
SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds)
Recupera gli elenchi di valori supportati per le coppie di ID proprietà e ID area specificati.
Introdotto in VHAL V4.
(Novità di Android 16)
MinMaxSupportedValueResults getMinMaxSupportedValue(in List propIdAreaIds)
Recupera i valori minimi e massimi supportati per le coppie di ID proprietà e ID area specificati.
Introdotto in VHAL V4.
void registerSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
Registra un callback da chiamare quando i valori supportati cambiano.
Introdotto in VHAL V4.
void unregisterSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
Annulla la registrazione del callback di modifica del valore supportato.
Introdotto in VHAL V4.

I callback sono definiti in IVehicleCallback.aidl e contengono questi metodi.

Metodo
oneway void onGetValues(in GetValueResults responses)
Callback per la funzione getValues per fornire i risultati di recupero del valore. Chiamato quando alcuni dei valori da recuperare sono pronti.
oneway void onSetValues(in SetValueResults responses)
Callback per la funzione setValues per fornire i risultati del valore impostato. Chiamato quando VHAL ha terminato la gestione di alcune richieste di impostazione delle proprietà.
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount)
Callback per la segnalazione di eventi di aggiornamento della proprietà.
CONTINUOUS, un evento della proprietà si verifica in base alla frequenza di campionamento della sottoscrizione in Hz o alla frequenza dei messaggi del bus del veicolo. Un evento della proprietà potrebbe verificarsi anche se lo stato di una proprietà cambia. Ad esempio, da non disponibile a disponibile.
Per la proprietà ON_CHANGE, un evento della proprietà si verifica quando il valore di una proprietà o lo stato di una proprietà cambia.
Questo deve essere utilizzato anche per fornire eventi di modifica dello stato della proprietà, ad esempio quando la proprietà non è più disponibile o si verifica un errore di lettura, deve essere fornito un VehiclePropValue con uno stato non disponibile o di errore e un valore vuoto.
SharedMemoryFileCount è sempre 0.
oneway void onPropertySetError(in VehiclePropErrors errors)
Callback per la segnalazione di errori di impostazione asincrona delle proprietà che non hanno una richiesta di impostazione corrispondente. Se sappiamo per quale richiesta di set si è verificato l'errore, è necessario utilizzare onSetValues con un risultato di errore.
oneway void onSupportedValueChange(in List propIdAreaIds)
Callback per la segnalazione di modifiche all'elenco dei valori supportati o al valore minimo e massimo supportato. Il chiamante deve chiamare il numero getMinMaxSupportedValue o getSupportedValuesLists per ottenere i valori aggiornati.

L'implementazione di VHAL viene convalidata da VHAL VTS all'indirizzo VtsHalAutomotiveVehicle_TargetTest.cpp.

Il test verifica che i metodi di base siano implementati correttamente e che le configurazioni delle proprietà supportate siano corrette. Il test viene eseguito su tutte le istanze VHAL sul dispositivo, tuttavia AAOS utilizza solo l'istanza predefinita (android.hardware.automotive.vehicle.IVehicle/default)

Valore della proprietà del veicolo

Utilizza la struttura VehiclePropValue per descrivere il valore di ogni proprietà, che ha i seguenti campi:

Campo Descrizione
timestamp Il timestamp che rappresenta l'ora in cui si è verificato l'evento e sincronizzato con l'orologio di SystemClock.elapsedRealtimeNano().
prop L'ID proprietà per questo valore.
areaid L'ID area per questo valore. L'area deve essere una delle aree supportate elencate nella configurazione dell'ID area o 0 per le proprietà globali.
value Una struttura di dati contenente il valore effettivo della proprietà. A seconda del tipo di proprietà, uno o più campi all'interno di questo campo vengono utilizzati per memorizzare il valore effettivo. Ad esempio, il primo elemento di value.int32Values viene utilizzato per le proprietà di tipo Int32. Per maggiori dettagli, vedi Configurazioni della proprietà.
status Lo stato della proprietà per la lettura. Per la proprietà di lettura/scrittura, questo potrebbe valere anche per la scrittura, ma non è garantito. Ad esempio, la proprietà potrebbe essere disponibile per la lettura, ma non per la scrittura. In questo caso, lo stato è AVAILABLE e il campo del valore contiene informazioni valide. Per gli stati possibili, vedi VehiclePropertyStatus.

getValues e setValues asincroni

Le operazioni getValues e setValues vengono eseguite in modo asincrono, il che significa che la funzione potrebbe restituire un valore prima del completamento dell'operazione di recupero o impostazione effettiva. I risultati dell'operazione (ad esempio, il valore della proprietà per getValues e lo stato di riuscita o di errore per setValues) vengono forniti tramite i callback passati come argomenti.

L'implementazione non deve bloccare il risultato nel thread del binder che gestisce la richiesta. Ti consigliamo invece di memorizzare la richiesta in una coda di richieste e di utilizzare un thread di gestione separato per gestire le richieste in modo asincrono. Per i dettagli, consulta l'implementazione di riferimento.

Figura 1. Processo asincrono.

Valori "parcelable" di grandi dimensioni

Tutte le strutture denominate XXXs, ad esempio VehiclePropConfigs, SetValueRequests e VehiclePropValues, sono chiamate LargeParcelable (o StableLargeParcelable). Ognuna rappresenta un elenco di valori utilizzati per trasferire grandi quantità di dati che potrebbero superare i limiti del binder (4 KB nell'implementazione della libreria LargeParcelable) oltre i limiti del binder. Ognuno ha una definizione di struttura simile che contiene i seguenti campi.

Assistenza Descrizione
payloads Elenco di valori quando la dimensione del valore rientra in una limitazione della memoria del binder o un elenco vuoto.
sharedMemoryFd Descrittore di file Nullable che punta a un file di memoria condivisa che archivia i payload serializzati se l'elenco di valori è troppo grande.

Ad esempio, VehiclePropConfigs è definito come:

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 contiene payload non vuoti o un valore sharedMemoryFd non nullo.

  • Se payloads non è vuoto, memorizza un elenco dei dati effettivi, ovvero la configurazione della proprietà.
  • Se sharedMemoryFd non è null, contiene un file di memoria condivisa che memorizza la struttura serializzata di VehiclePropConfigs. La struttura utilizza la funzione writeToParcel per serializzare un Parcel.

In qualità di client Java per VHAL, Car Service gestisce la serializzazione e la deserializzazione per LargeParcelable. Per le implementazioni VHAL e i client nativi, un LargeParcelable deve essere serializzato e deserializzato con la libreria LargeParcelable o una classe wrapper utile per la libreria in ParcelableUtils.h.

Ad esempio, un client nativo che analizza le richieste per getValues ricevute da un binder è il seguente:

// '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.
}

Di seguito è riportato un esempio di implementazione VHAL che invia i risultati per getValues tramite il binder:

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