Die Android-Plattform enthält viele XML-Dateien zum Speichern von Konfigurationen.
(z. B. „audio config“). Viele der XML-Dateien befinden sich im vendor
.
werden aber in der Partition system
gelesen. In diesem Fall wird das Schema
der XML-Datei dient als Schnittstelle zwischen den beiden Partitionen.
Das Schema muss explizit angegeben werden und in einer abwärtskompatiblen
auf die Art und Weise.
Vor Android 10 hatte die Plattform
die die Angabe und Verwendung des XML-Schemas erfordern oder
nicht kompatible Änderungen im Schema. Android 10 bietet
diesen Mechanismus, die Config File Schema API. Dieser Mechanismus besteht aus einem Tool,
mit dem Namen xsdc
und der Build-Regel xsd_config
.
Das xsdc
-Tool ist ein XSD-Compiler (XML Schema Document). Sie parst eine XSD-Datei.
beschreibt das Schema einer XML-Datei und generiert Java- und C++-Code. Die
parst der generierte Code XML-Dateien, die dem XSD-Schema entsprechen,
-Objekte, die jeweils ein XML-Tag modellieren. XML-Attribute werden als Felder modelliert
der Objekte.
Durch die Build-Regel xsd_config
wird das xsdc
-Tool in das Build-System integriert.
Für eine bestimmte XSD-Eingabedatei generiert die Build-Regel Java- und C++-Bibliotheken. Ich
die Bibliotheken mit den Modulen verknüpfen, in denen die XML-Dateien, die den
XSD gelesen und verwendet werden. Sie können die Build-Regel für Ihre eigenen verwendeten XML-Dateien verwenden
in den Partitionen system
und vendor
.
Build Config File Schema API
In diesem Abschnitt wird beschrieben, wie Sie die Config File Schema API erstellen.
Build-Regel „xsd_config“ in Android.bp konfigurieren
Die Build-Regel xsd_config
generiert den Parsercode mit dem xsdc
-Tool. Die
Das Attribut package_name
der xsd_config
-Build-Regel bestimmt den Paketnamen der
den generierten Java-Code.
Beispiel für eine xsd_config
-Build-Regel in Android.bp
:
xsd_config {
name: "hal_manifest",
srcs: ["hal_manifest.xsd"],
package_name: "hal.manifest",
}
Beispiel für eine Verzeichnisstruktur:
├── Android.bp
├── api
│ ├── current.txt
│ ├── last_current.txt
│ ├── last_removed.txt
│ └── removed.txt
└── hal_manifest.xsd
Das Build-System generiert eine API-Liste mit dem generierten Java-Code und prüft,
die API dafür verwenden. Diese API-Prüfung wird DroidCore hinzugefügt und um m -j
ausgeführt.
API-Listendateien erstellen
Für die API-Prüfungen sind im Quellcode Dateien von API-Listen erforderlich.
Die API-Listendateien enthalten Folgendes:
current.txt
undremoved.txt
prüfen, ob die APIs geändert wurden durch Vergleich mit generierten API-Dateien zur Erstellungszeit.last_current.txt
undlast_removed.txt
prüfen, ob die APIs durch den Vergleich mit API-Dateien abwärtskompatibel.
So erstellen Sie die API-Listendateien:
- Erstellen Sie leere Listendateien.
- Führen Sie den Befehl
make update-api
aus.
Generierten Parsercode verwenden
Wenn Sie den generierten Java-Code verwenden möchten, fügen Sie dem Modul xsd_config
:
als Präfix hinzu
Name in der srcs
-Eigenschaft von Java. Das Paket des generierten Java-Codes ist das
wie das Attribut package_name
.
java_library {
name: "vintf_test_java",
srcs: [
"srcs/**/*.java"
":hal_manifest"
],
}
Fügen Sie zur Verwendung des generierten C++-Codes den Modulnamen xsd_config
an die
generated_sources
- und generated_headers
-Properties. libxml2
hinzufügen zu
static_libs
oder shared_libs
, da libxml2
im generierten Parser erforderlich ist
Code. Der Namespace des
generierter C++-Code ist mit dem Attribut package_name
identisch. Wenn beispielsweise
der Name des Moduls xsd_config
hal.manifest
lautet, ist der Namespace
hal::manifest
cc_library{
name: "vintf_test_cpp",
srcs: ["main.cpp"],
generated_sources: ["hal_manifest"],
generated_headers: ["hal_manifest"],
shared_libs: ["libxml2"],
}
Parser verwenden
Um den Java-Parsercode zu verwenden, verwenden Sie XmlParser#read
oder
Methode read{class-name}
, um die Klasse des Stamms zurückzugeben
-Elements. Das Parsen erfolgt zu diesem Zeitpunkt.
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();
…
}
}
…
}
Fügen Sie zur Verwendung des C++-Parsercodes zuerst die Headerdatei ein. Der Name des
Headerdatei ist der Paketname mit Punkten (.), die in Unterstriche (_) umgewandelt werden.
Verwenden Sie dann die Methode read
oder read{class-name}
, um
die Klasse des Stammelements. Das Parsen erfolgt zu diesem Zeitpunkt. Der Rückgabewert ist
ein 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();
…
}
…
}
Alle zur Verwendung des Parsers bereitgestellten APIs befinden sich in api/current.txt
. Für
werden alle Element- und Attributnamen in die Camel-Case-Schreibweise
Beispiel: ElementName
) und als entsprechende Variable, Methode und
Kursname. Die Klasse des geparsten Stammelements kann mithilfe der Methode
read{class-name}
. Wenn nur eine Wurzel vorhanden ist
-Element enthält, lautet der Funktionsname read
. Der Wert eines geparsten Unterelements oder
kann mithilfe von get{variable-name}
abgerufen werden.
.
Parsercode generieren
In den meisten Fällen müssen Sie xsdc
nicht direkt ausführen. Build xsd_config
verwenden
wie oben beschrieben, wie in
Build-Regel „xsd_config“ in Android.bp konfigurieren Dieses
wird der Vollständigkeit halber die xsdc
-Befehlszeile erläutert. Dieses
bei der Fehlerbehebung hilfreich sein.
Du musst dem xsdc
-Tool den Pfad zur XSD-Datei und ein Paket angeben. Die
Package ist ein Paketname im Java-Code und ein Namespace im C++-Code. Die Optionen
um zu bestimmen, ob der generierte Code Java oder C ist, -j
oder -c
sind,
. Die Option -o
ist der Pfad des Ausgabeverzeichnisses.
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
Beispielbefehl:
$ xsdc audio_policy_configuration.xsd -p audio.policy -j