Platforma Androida zawiera wiele plików XML do przechowywania konfiguracji
danych (np. konfiguracji audio). Wiele plików XML znajduje się w folderze vendor
ale są odczytywane w partycji system
. W tym przypadku schemat
pliku XML służy jako interfejs między dwiema partycjami i dlatego
schemat musi być wyraźnie określony i rozwijać się w sposób zgodny wstecznie;
w dobrym stylu.
Przed Androidem 10 platforma nie udostępniała
mechanizmów wymagających określenia schematu XML i użycia go do tego celu,
niezgodne zmiany w schemacie. Android 10 zapewnia
ten mechanizm nazywany interfejsem Config File Schema API. Mechanizm ten składa się z narzędzia,
o nazwie xsdc
i regułie kompilacji o nazwie xsd_config
.
Narzędzie xsdc
to kompilator XML Schema Document (XSD). Przetwarza on plik XSD opisujący schemat pliku XML i generuje kod Java i C++. Wygenerowany kod analizuje pliki XML zgodne ze schematem XSD i przekształca je w drzewo obiektów, z których każdy modeluje tag XML. Atrybuty XML są modelowane jako pola obiektów.
Reguła kompilacji xsd_config
integruje narzędzie xsdc
z systemem kompilacji.
W przypadku danego pliku wejściowego XSD reguła kompilacji generuje biblioteki Java i C++. Ty
może łączyć biblioteki z modułami, w których pliki XML zgodne z
XSD są odczytywane i używane. Zasady kompilacji możesz używać w przypadku własnych plików XML używanych w particjach system
i vendor
.
Interfejs API schematu pliku konfiguracyjnego kompilacji
W tej sekcji opisaliśmy, jak tworzyć interfejs API schematu pliku konfiguracji.
Skonfiguruj regułę kompilacji xsd_config w Android.bp
Reguła kompilacji xsd_config
generuje kod parsowania za pomocą narzędzia xsdc
. Właściwość package_name
reguły kompilacji xsd_config
określa nazwę pakietu wygenerowanego kodu Javy.
Przykładowa reguła kompilacji xsd_config
w Android.bp
:
xsd_config {
name: "hal_manifest",
srcs: ["hal_manifest.xsd"],
package_name: "hal.manifest",
}
Przykładowa struktura katalogów:
├── Android.bp
├── api
│ ├── current.txt
│ ├── last_current.txt
│ ├── last_removed.txt
│ └── removed.txt
└── hal_manifest.xsd
System kompilacji generuje listę interfejsów API za pomocą wygenerowanego kodu Java i porównuje ją z interfejsami API. Ten test interfejsu API jest dodawany do DroidCore i wykonywany w m -j
.
Tworzenie plików list interfejsów API
Kontrole interfejsu API wymagają, aby interfejsy API zawierały listę plików w kodzie źródłowym.
Lista plików w interfejsie API obejmuje:
current.txt
iremoved.txt
sprawdź, czy interfejsy API zostały zmienione, porównując je z wygenerowanymi plikami API w momencie kompilacji.last_current.txt
ilast_removed.txt
sprawdź, czy interfejsy API są zgodne wstecz, porównując je z plikami API.
Aby utworzyć pliki list interfejsu API:
- Utwórz pliki pustych list.
- Uruchom polecenie
make update-api
.
Użyj wygenerowanego kodu parsera
Aby użyć wygenerowanego kodu Java, dodaj :
jako prefiks do nazwy modułu xsd_config
w usłudze w Java srcs
. Pakiet wygenerowanego kodu Java jest taki sam jak usługa package_name
.
java_library {
name: "vintf_test_java",
srcs: [
"srcs/**/*.java"
":hal_manifest"
],
}
Aby użyć wygenerowanego kodu C++, dodaj nazwę modułu xsd_config
do sekcji
Usługi generated_sources
i generated_headers
. Dodaj też libxml2
do static_libs
lub shared_libs
, ponieważ libxml2
jest wymagany w wygenerowanym kodzie parsowania. Przestrzeń nazw wygenerowanego kodu C++ jest taka sama jak w przypadku właściwości package_name
. Na przykład, jeśli
nazwa modułu xsd_config
to hal.manifest
, przestrzeń nazw to
hal::manifest
cc_library{
name: "vintf_test_cpp",
srcs: ["main.cpp"],
generated_sources: ["hal_manifest"],
generated_headers: ["hal_manifest"],
shared_libs: ["libxml2"],
}
Używanie parsowania
Aby skorzystać z kodu parsera Java, użyj instrukcji XmlParser#read
lub
Metoda read{class-name}
zwracająca klasę pierwiastka
. W tym momencie następuje analiza.
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();
…
}
}
…
}
Aby użyć kodu parsowania C++, najpierw dołącz plik nagłówka. Nazwa
plik nagłówka to nazwa pakietu z kropkami (.) przekonwertowanymi na podkreślenia (_).
Następnie użyj metody read
lub read{class-name}
, aby zwrócić klasę elementu . W tym momencie następuje analiza. Zwracana wartość to 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();
…
}
…
}
Wszystkie interfejsy API udostępniane do korzystania z parsera mają język api/current.txt
. Dla:
jednorodność, nazwy wszystkich elementów i atrybutów są konwertowane na wielkość liter wielbłąda (na
np. ElementName
) i jest używany jako odpowiednia zmienna, metoda i
nazwę zajęć. klasę przeanalizowanego elementu głównego można uzyskać za pomocą funkcji
read{class-name}
. Jeśli jest tylko 1 element główny, nazwa funkcji to read
. Wartość przeanalizowanego podelementu lub
atrybutu można uzyskać za pomocą funkcji get{variable-name}
.
Generowanie kodu parsowania
W większości przypadków nie musisz uruchamiać xsdc
bezpośrednio. Użyj kompilacji xsd_config
zgodnie z opisem w sekcji
Konfigurowanie reguły kompilacji xsd_config w pliku Android.bp Ten
wyjaśnia, jak działa interfejs wiersza poleceń xsdc
. Może to być przydatne podczas debugowania.
Musisz podać narzędziu xsdc
ścieżkę do pliku XSD oraz pakiet. W kodzie Java jest to nazwa pakietu, a w kodzie C++ – nazwa przestrzeni nazw. Opcje określające, czy wygenerowany kod jest w języku Java czy C, to odpowiednio -j
lub -c
. Opcja -o
to ścieżka do katalogu wyjściowego.
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
Przykładowe polecenie:
$ xsdc audio_policy_configuration.xsd -p audio.policy -j