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). Analizuje plik XSD
opisuje schemat pliku XML i generuje kod w Javie i C++.
wygenerowany kod analizuje pliki XML zgodne ze schematem XSD, tworząc drzewo
obiektów, z których każdy modeluje tag XML. Atrybuty XML są modelowane jako pola
kilka obiektów.
Reguła kompilacji xsd_config
integruje narzędzie xsdc
z systemem kompilacji.
Dla 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. Możesz użyć reguły kompilacji dla własnych plików XML
w partycjach system
i vendor
.
Interfejs API schematu pliku konfiguracyjnego kompilacji
W tej sekcji opisujemy, jak utworzyć interfejs Config File Schema API.
Skonfiguruj regułę kompilacji xsd_config w Android.bp
Reguła kompilacji xsd_config
generuje kod parsera za pomocą narzędzia xsdc
.
Właściwość package_name
w regule kompilacji xsd_config
określa nazwę pakietu
w wygenerowanym kodzie Java.
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, korzystając z wygenerowanego kodu Java i sprawdza
interfejs 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
sprawdzają, czy interfejsy API zostały zmienione przez porównując je z plikami wygenerowanymi przez interfejs API podczas kompilacji.last_current.txt
ilast_removed.txt
sprawdzają, czy interfejsy API są kompatybilności wstecznej przez porównanie z plikami interfejsu API.
Aby utworzyć listę plików interfejsu API:
- Utwórz pliki pustych list.
- Uruchom polecenie
make update-api
.
Użyj wygenerowanego kodu parsera
Aby użyć wygenerowanego kodu Java, dodaj do modułu xsd_config
prefiks :
we właściwości srcs
środowiska Java. Pakiet wygenerowanego kodu Java jest
taka sama jak właściwość 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
. I dodaj libxml2
do
static_libs
lub shared_libs
, ponieważ w wygenerowanym parserze wymagany jest parametr libxml2
w kodzie. Przestrzeń nazw
wygenerowany kod w C++ jest taki sam jak właściwość 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żyj parsera
Aby skorzystać z kodu parsera Java, użyj instrukcji XmlParser#read
lub
Metoda read{class-name}
zwracająca klasę pierwiastka
. W tym momencie odbywa się 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 parsera 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ć
klasy elementu głównego. W tym momencie odbywa się 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
przykładowy ElementName
) i 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 istnieje tylko jeden pierwiastek
, nazwa funkcji to read
. Wartość przeanalizowanego podelementu lub
atrybutu można uzyskać za pomocą funkcji get{variable-name}
.
Wygeneruj kod parsera
W większości przypadków nie musisz bezpośrednio uruchamiać xsdc
. 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
. Ten
może być przydatne podczas debugowania.
Musisz podać narzędziu xsdc
ścieżkę do pliku XSD i pakietu.
package to nazwa pakietu w kodzie Javy i przestrzeń nazw w kodzie C++. Opcje
aby określić, czy wygenerowany kod to Java czy C, to -j
lub -c
,
. Opcja -o
to ścieżka 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