Interfacce e pacchetti

L'architettura HIDL si basa sulle interfacce, un tipo astratto utilizzato nelle soluzioni orientate agli oggetti linguaggi di markup per definire i comportamenti. Ogni interfaccia fa parte di un pacchetto.

Pacchetti

I nomi dei pacchetti possono avere livelli secondari, ad esempio package.subpackage. La La directory root dei pacchetti HIDL pubblicati è hardware/interfaces o vendor/vendorName (ad esempio, vendor/google per Pixel dispositivi). Il nome del pacchetto forma una o più sottodirectory sotto la directory principale directory; tutti i file che definiscono un pacchetto si trovano nella stessa directory. Ad esempio: package android.hardware.example.extension.light@2.0 trovato sotto hardware/interfaces/example/extension/light/2.0.

Nella tabella seguente sono elencati i prefissi e le posizioni dei pacchetti:

Prefisso pacchetto Posizione Tipi di interfaccia
android.hardware.* hardware/interfaces/* HAL
android.frameworks.* frameworks/hardware/interfaces/* framework/ correlati
android.system.* system/hardware/interfaces/* correlato al sistema
android.hidl.* system/libhidl/transport/* nucleo

La directory del pacchetto contiene file con estensione .hal. Ogni evento il file deve contenere un'istruzione package che assegna il nome al pacchetto la versione di cui fa parte il file. Il file types.hal, se presente, non definiscono un'interfaccia, ma definiscono tipi di dati accessibili a ogni all'interno del pacchetto.

Definizione dell'interfaccia

A parte types.hal, ogni altro file .hal definisce un'interfaccia. In genere, un'interfaccia è definita come segue:

interface IBar extends IFoo { // IFoo is another interface
    // embedded types
    struct MyStruct {/*...*/};

    // interface methods
    create(int32_t id) generates (MyStruct s);
    close();
};

Un'interfaccia senza una dichiarazione extends esplicita implicitamente si estende da android.hidl.base@1.0::IBase (simile a java.lang.Object in Java. L'interfaccia IBase, in modo implicito importati, dichiara diversi metodi riservati che non devono e non possono essere ridichiarati nelle interfacce definite dall'utente o utilizzati in altro modo. Questi metodi include:

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

Procedura di importazione

L'istruzione import è un meccanismo HIDL per accedere al pacchetto e i tipi in un altro pacchetto. Un'istruzione import riguarda due entità:

  • L'entità di importazionein corso, che può essere un pacchetto o una interfaccia
  • L'entità importataed, che può essere un pacchetto o una interfaccia

L'entità di importazione è determinata dalla posizione import. Se la dichiarazione si trova all'interno del types.hal, ciò che viene importato è visibile all'intero pacchetto; si tratta di un'importazione a livello di pacchetto. Se l'istruzione è all'interno di un di interfaccia, l'entità di importazione è l'interfaccia stessa; questo è un l'importazione a livello di interfaccia.

L'entità importata è determinata dal valore dopo import parola chiave. Il valore non deve essere un nome completo. se un componente è omesso, viene inserito automaticamente con informazioni del pacchetto corrente. Per i valori completi, sono supportati i seguenti casi di importazione:

  • Importazioni di pacchetti interi. Se il valore è il nome di un pacchetto e un (sintassi descritta di seguito), l'intero pacchetto viene importato nella di importazione dell'entità.
  • Importazioni parziali. Se il valore è:
    • Un'interfaccia, types.hal del pacchetto e tale interfaccia sono importati nell'entità di importazione.
    • Una funzione definita dall'utente (UDT) definita in types.hal, solo allora verrà importata solo questa funzione l'entità di importazione (gli altri tipi in types.hal non vengono importati).
  • Importazioni solo tipi. Se il valore utilizza la sintassi di un importazione parziale descritta sopra, ma con la parola chiave types di un nome di interfaccia, solo gli UDT in types.hal della di pacchetti importati.

L'entità di importazione ottiene l'accesso a una combinazione di:

  • le UDT comuni del pacchetto importato definite in types.hal.
  • Le interfacce del pacchetto importato (per l'importazione dell'intero pacchetto) o (per un'importazione parziale) ai fini di richiamarle, trasmettere e/o ereditarli.

L'istruzione import utilizza la sintassi completo-type-name per fornire il parametro nome e versione del pacchetto o dell'interfaccia da importare:

import android.hardware.nfc@1.0;            // import a whole package
import android.hardware.example@1.0::IQuux; // import an interface and types.hal
import android.hardware.example@1.0::types; // import just types.hal

Eredità dell'interfaccia

Un'interfaccia può essere un'estensione di un'interfaccia definita in precedenza. Le estensioni possono essere di uno dei tre tipi seguenti:

  • L'interfaccia può aggiungere funzionalità a un'altra, incorporando la sua API senza modifiche.
  • Il pacchetto può aggiungere funzionalità a un altro, incorporando la sua API senza modifiche.
  • L'interfaccia può importare tipi da un pacchetto o da un'interfaccia specifica.

Un'interfaccia può estendere solo un'altra interfaccia (non ereditarietà multipla). Ogni interfaccia in un pacchetto con un numero di versione secondario diverso da zero deve estendere un nella versione precedente del pacchetto. Ad esempio, se un'interfaccia IBar nella versione 4.0 del pacchetto derivative è basato su (estende) un'interfaccia IFoo nella versione 1.2 del pacchetto original, mentre la versione 1.3 del pacchetto original è creato, la versione 4.1 di IBar non può estendere la versione 1.3 di IFoo. La versione 4.1 di IBar deve invece estendere IBar versione 4.0, collegata alla versione 1.2 di IFoo. La versione 5.0 di IBar potrebbe estendere la versione 1.3 di IFoo, se desiderato.

Le estensioni di interfaccia non implicano una dipendenza dalla libreria o inclusione inter-HAL nel codice generato, importano semplicemente la struttura e il metodo dei dati a livello HIDL. Ogni metodo in un HAL deve essere implementato HAL

Estensioni del fornitore

In alcuni casi, le estensioni del fornitore vengono implementate come sottoclasse del che rappresenta l'interfaccia principale che estendono. Lo stesso oggetto registrati con il nome e la versione di base dell'HAL e nel nome (fornitore) Nome e versione dell'HAL.

Controllo delle versioni

Viene eseguito il controllo delle versioni dei pacchetti e le interfacce hanno la versione del pacchetto. Le versioni sono espresse in due numeri interi, maggiore.minore.

  • Le versioni Principali non sono compatibili con le versioni precedenti. Incremento il numero della versione principale reimposta il numero di versione secondaria su 0.
  • Le versioni Minor sono compatibili con le versioni precedenti. L'aumento del un numero minore indica che la versione più recente è completamente compatibile con le versioni precedenti precedente. È possibile aggiungere nuove strutture dati e nuovi metodi, ma non ne esistono le strutture dati o le firme dei metodi potrebbero essere modificate.

Su un dispositivo possono essere presenti più versioni principali o secondarie di un HAL contemporaneamente. Tuttavia, una versione secondaria dovrebbe essere preferita rispetto a una maggiore. perché il codice client funziona con un'interfaccia di una versione secondaria precedente funziona anche con le versioni secondarie successive della stessa interfaccia. Per ulteriori informazioni sul controllo delle versioni e sulle estensioni dei fornitori, consulta Controllo delle versioni HIDL.

Riepilogo del layout dell'interfaccia

Questa sezione riassume come gestire un pacchetto di interfaccia HIDL (come hardware/interfaces) e consolida le informazioni presentate in tutta la sezione HIDL. Prima di leggere, assicurati di acquisire familiarità con Controllo delle versioni HIDL con l'hashing con hidl-gen, i dettagli dell'utilizzo HIDL in generale e le seguenti definizioni:

Termine Definizione
Binary Interface (ABI) dell'applicazione Un'interfaccia di programmazione di un'applicazione ed eventuali collegamenti binari richiesti.
nome completo (fqName) Nome per distinguere un tipo Hidl. Esempio: android.hardware.foo@1.0::IFoo.
Pacco Pacchetto contenente un'interfaccia e dei tipi HIDL. Esempio: android.hardware.foo@1.0.
radice pacchetto Pacchetto radice che contiene le interfacce HIDL. Esempio: interfaccia HIDL android.hardware si trova nella directory principale del pacchetto android.hardware.foo@1.0.
percorso principale del pacchetto Posizione nella struttura di origine Android in cui viene mappato un pacchetto root.

Per altre definizioni, consulta HIDL Terminologia.

Ogni file può essere trovato dalla mappatura principale del pacchetto il nome completo

Le radici dei pacchetti sono specificate come hidl-gen come argomento -r android.hardware:hardware/interfaces. Ad esempio, se pacchetto è vendor.awesome.foo@1.0::IFoo e hidl-gen viene inviato -r vendor.awesome:some/device/independent/path/interfaces, il file dell'interfaccia dovrebbe trovarsi $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal.

In pratica, è consigliato per un fornitore o OEM denominato awesome per inserire le proprie interfacce standard in vendor.awesome. Dopo un pacco il percorso è stato selezionato, non deve essere modificato perché è integrato nell'ABI di l'interfaccia.

La mappatura dei percorsi dei pacchetti deve essere univoca

Ad esempio, se hai -rsome.package:$PATH_A e -rsome.package:$PATH_B, $PATH_A deve essere uguale a $PATH_B per una directory dell'interfaccia coerente (questo rende anche interfacce per il controllo delle versioni più facile).

La radice del pacchetto deve avere un file di controllo delle versioni

Se crei un percorso pacchetto, come -r vendor.awesome:vendor/awesome/interfaces, dovresti anche crea il file $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt, che deve contenere hash di interfacce create utilizzando l'opzione -Lhash in hidl-gen (questo argomento è discusso in modo approfondito nella Hashing con hidl-gen).

Le interfacce sono indipendenti dal dispositivo sedi

In pratica, consigliamo di condividere le interfacce tra i rami. Questo consente il massimo riutilizzo del codice e il massimo test del codice in diverse dispositivi e casi d'uso.