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 intypes.hal
non vengono importati).
- Un'interfaccia,
- 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 intypes.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.