La piattaforma Android contiene molti file XML per l'archiviazione
(ad esempio la configurazione audio). Molti file XML si trovano in vendor
ma verranno letti nella partizione system
. In questo caso, lo schema
del file XML funge da interfaccia tra le due partizioni.
lo schema deve essere specificato esplicitamente e deve evolversi in una
in modo adeguato.
Prima di Android 10, la piattaforma non forniva
meccanismi per richiedere di specificare e utilizzare lo schema XML o di impedire
modifiche incompatibili nello schema. Android 10 offre
questo meccanismo, chiamato API Config File Schema. Questo meccanismo consiste in uno strumento
denominata xsdc
, e una regola di build denominata xsd_config
.
Lo strumento xsdc
è un compilatore XSD (XML Schema Document). Analizza un file XSD
che descrive lo schema di un file XML e genera codice Java e C++. La
il codice generato analizza i file XML conformi allo schema XSD in una struttura ad albero di
ciascuno dei quali modella un tag XML. Gli attributi XML vengono modellati come campi
degli oggetti.
La regola di build xsd_config
integra lo strumento xsdc
nel sistema di compilazione.
Per un determinato file di input XSD, la regola di compilazione genera librerie Java e C++. Tu
possono collegare le librerie ai moduli in cui i file XML sono conformi
Vengono letti e utilizzati i file XSD. Puoi usare la regola di creazione per i tuoi file XML utilizzati
tra le partizioni system
e vendor
.
API Build Config File Schema
Questa sezione descrive come creare l'API Config File Schema.
Configura la regola di build xsd_config in Android.bp
La regola di build xsd_config
genera il codice del parser con lo strumento xsdc
. La
La proprietà package_name
della regola di build xsd_config
determina il nome del pacchetto di
il codice Java generato.
Esempio di regola di build xsd_config
in Android.bp
:
xsd_config {
name: "hal_manifest",
srcs: ["hal_manifest.xsd"],
package_name: "hal.manifest",
}
Esempio di struttura di directory:
├── Android.bp
├── api
│ ├── current.txt
│ ├── last_current.txt
│ ├── last_removed.txt
│ └── removed.txt
└── hal_manifest.xsd
Il sistema di compilazione genera un elenco di API utilizzando il codice Java generato e verifica
l'API. Questo controllo dell'API viene aggiunto a DroidCore ed eseguito alle ore m -j
.
Crea file degli elenchi delle API
I controlli delle API richiedono dei file con elenchi delle API nel codice sorgente.
I file degli elenchi delle API includono:
current.txt
eremoved.txt
controllano se le API vengono modificate da con i file API generati in fase di creazione.last_current.txt
elast_removed.txt
controllano se le API sono compatibili con le versioni precedenti, confrontandoli con i file API.
Per creare i file degli elenchi delle API:
- Crea file di elenchi vuoti.
- Esegui il comando
make update-api
.
Usa il codice del parser generato
Per utilizzare il codice Java generato, aggiungi :
come prefisso al modulo xsd_config
nella proprietà Java srcs
. Il pacchetto del codice Java generato è
uguale alla proprietà package_name
.
java_library {
name: "vintf_test_java",
srcs: [
"srcs/**/*.java"
":hal_manifest"
],
}
Per utilizzare il codice C++ generato, aggiungi il nome del modulo xsd_config
alla
generated_sources
e generated_headers
proprietà. E aggiungi libxml2
a
static_libs
o shared_libs
, poiché è richiesto libxml2
nel parser generato
le API nel tuo codice. Lo spazio dei nomi
il codice C++ generato corrisponde alla proprietà package_name
. Ad esempio, se
il nome del modulo xsd_config
è hal.manifest
, lo spazio dei nomi è
hal::manifest
.
cc_library{
name: "vintf_test_cpp",
srcs: ["main.cpp"],
generated_sources: ["hal_manifest"],
generated_headers: ["hal_manifest"],
shared_libs: ["libxml2"],
}
Utilizzare il parser
Per utilizzare il codice dell'analizzatore sintattico Java, utilizza XmlParser#read
o
Metodo read{class-name}
per restituire la classe del root
. L'analisi viene eseguita in questo momento.
import hal.manifest.*;
…
class HalInfo {
public String name;
public String format;
public String optional;
…
}
void readHalManifestFromXml(File file) {
…
try (InputStream str = new BufferedInputStream(new FileInputStream(file))) {
Manifest manifest = XmlParser.read(str);
for (Hal hal : manifest.getHal()) {
HalInfo halinfo;
HalInfo.name = hal.getName();
HalInfo.format = hal.getFormat();
HalInfo.optional = hal.getOptional();
…
}
}
…
}
Per utilizzare il codice del parser C++, includi innanzitutto il file di intestazione. Il nome del
di intestazione è il nome del pacchetto con punti (.) convertiti in trattini bassi (_).
Quindi utilizza il metodo read
o read{class-name}
per restituire
la classe dell'elemento radice. L'analisi viene eseguita in questo momento. Il valore restituito è
std::optional<>
.
include "hal_manifest.h"
…
using namespace hal::manifest
struct HalInfo {
public std::string name;
public std::string format;
public std::string optional;
…
};
void readHalManifestFromXml(std::string file_name) {
…
Manifest manifest = *read(file_name.c_str());
for (Hal hal : manifest.getHal()) {
struct HalInfo halinfo;
HalInfo.name = hal.getName();
HalInfo.format = hal.getFormat();
HalInfo.optional = hal.getOptional();
…
}
…
}
Tutte le API fornite per utilizzare il parser si trovano in api/current.txt
. Per
uniformità, tutti i nomi di elementi e attributi vengono convertiti in caratteri a cammello (ad
esempio, ElementName
) e utilizzato come variabile, metodo e
nome della classe. La classe dell'elemento radice analizzato può essere ottenuta utilizzando
Funzione read{class-name}
. Se è presente una sola radice
, il nome della funzione sarà read
. Il valore di un elemento secondario analizzato o
puoi ottenere utilizzando l'attributo get{variable-name}
personalizzata.
Genera codice parser
Nella maggior parte dei casi, non è necessario eseguire xsdc
direttamente. Utilizza la build xsd_config
una regola di accesso, come descritto in
Hai configurato la regola di build xsd_config in Android.bp. Questo
spiega l'interfaccia a riga di comando xsdc
, solo per completezza. Questo
per il debug.
Devi assegnare allo strumento xsdc
il percorso del file XSD e un pacchetto. La
pacchetto è un nome pacchetto nel codice Java e uno spazio dei nomi nel codice C++. Opzioni
per determinare se il codice generato è Java o C sono -j
o -c
,
rispettivamente. L'opzione -o
è il percorso della directory di output.
usage: xsdc path/to/xsd_file.xsd [-c] [-j] [-o <arg>] [-p]
-c,--cpp Generate C++ code.
-j,--java Generate Java code.
-o,--outDir <arg> Out Directory
-p,--package Package name of the generated java file. file name of
generated C++ file and header
Comando di esempio:
$ xsdc audio_policy_configuration.xsd -p audio.policy -j