Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Implementación de la API de esquema de archivo de configuración

La plataforma Android contiene muchos archivos XML para almacenar datos de configuración (por ejemplo, configuración de audio). Muchos de los archivos XML están en la partición del vendor , pero se leen en la partición del system . En este caso, el esquema del archivo XML sirve como interfaz entre las dos particiones y, por lo tanto, el esquema debe especificarse explícitamente y debe evolucionar de manera compatible con versiones anteriores.

Antes de Android 10, la plataforma no proporcionaba mecanismos para requerir la especificación y el uso del esquema XML, o para evitar cambios incompatibles en el esquema. Android 10 proporciona este mecanismo, llamado API de esquema de archivo de configuración. Este mecanismo consta de una herramienta llamada xsdc y una regla de construcción llamada xsd_config .

La herramienta xsdc es un compilador de documentos de esquema XML (XSD). Analiza un archivo XSD que describe el esquema de un archivo XML y genera código Java y C ++. El código generado analiza los archivos XML que se ajustan al esquema XSD en un árbol de objetos, cada uno de los cuales modela una etiqueta XML. Los atributos XML se modelan como campos de los objetos.

La xsd_config compilación xsd_config integra la herramienta xsdc en el sistema de compilación. Para un archivo de entrada XSD determinado, la regla de compilación genera bibliotecas Java y C ++. Puede vincular las bibliotecas a los módulos donde se leen y utilizan los archivos XML que se ajustan al XSD. Puede utilizar la regla de compilación para sus propios archivos XML utilizados en todo el system y vendor particiones de los vendor .

Creación de API de esquema de archivo de configuración

Esta sección describe cómo construir la API de esquema de archivo de configuración.

Configuración de la regla de compilación xsd_config en Android.bp

La xsd_config compilación xsd_config genera el código del analizador con la herramienta xsdc . El xsd_config de regla de construcción package_name propiedad determina el nombre del paquete de código Java generado.

Ejemplo de xsd_config compilación Android.bp en Android.bp :

xsd_config {
    name: "hal_manifest",
    srcs: ["hal_manifest.xsd"],
    package_name: "hal.manifest",
}

Estructura de directorio de ejemplo:

├── Android.bp
├── api
│   ├── current.txt
│   ├── last_current.txt
│   ├── last_removed.txt
│   └── removed.txt
└── hal_manifest.xsd

El sistema de compilación genera una lista de API utilizando el código Java generado y compara la API. Esta verificación de API se agrega a DroidCore y se ejecuta en m -j .

Crear archivos de listas de API

Las comprobaciones de API requieren archivos de listas de API en el código fuente.

Los archivos de listas de API incluyen:

  • current.txt y removed.txt comprueban si las API se modifican comparándolas con los archivos de API generados en el momento de la compilación.
  • last_current.txt y last_removed.txt comprueban si las API son compatibles con versiones anteriores comparándolas con los archivos API.

Para crear los archivos de listas de API:

  1. Crea archivos de listas vacías.
  2. Ejecute el comando make update-api .

Usando código de analizador generado

Para utilizar el código Java generado, agregue : como prefijo al nombre del módulo xsd_config en la propiedad srcs Java. El paquete del código Java generado es el mismo que la propiedad package_name .

java_library {
    name: "vintf_test_java",
    srcs: [
        "srcs/**/*.java"
        ":hal_manifest"
    ],
}

Para usar el código C ++ generado, agregue el nombre del módulo xsd_config a las propiedades generated_sources y generated_headers . Y agregue libxml2 a static_libs o shared_libs , ya que se requiere libxml2 en el código del analizador generado. El espacio de nombres del código C ++ generado es el mismo que el de la propiedad package_name . Por ejemplo, si el nombre del módulo xsd_config es hal.manifest , el espacio de nombres es hal::manifest .

cc_library{
    name: "vintf_test_cpp",
    srcs: ["main.cpp"],
    generated_sources: ["hal_manifest"],
    generated_headers: ["hal_manifest"],
    shared_libs: ["libxml2"],
}

Usando el analizador

Para usar el código del analizador de Java, use el XmlParser#read o read{ class-name } para devolver la clase del elemento raíz. El análisis ocurre en este 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();
            …
        }
    }
    …
}

Para usar el código del analizador de C ++, primero incluya el archivo de encabezado. El nombre del archivo de encabezado es el nombre del paquete con puntos (.) Convertido en guiones bajos (_). Luego use el método read o read{ class-name } para devolver la clase del elemento raíz. El análisis ocurre en este momento. El valor de retorno es un 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();
        …
    }
    …
}

Todas las API proporcionadas para usar el analizador están en api/current.txt . Para uniformidad, todos los nombres de elementos y atributos se convierten a mayúsculas y minúsculas (por ejemplo, ElementName ) y se utilizan como la variable, el método y el nombre de clase correspondientes. La clase del elemento raíz analizado se puede obtener utilizando la función read{ class-name } . Si solo hay un elemento raíz, se read nombre de la función. El valor de un subelemento o atributo analizado se puede obtener usando la función get{ variable-name } .

Generando código de analizador

En la mayoría de los casos, no es necesario ejecutar xsdc directamente. En su lugar, utilice la xsd_config compilación xsd_config , como se describe en Configuración de la regla de compilación xsd_config en Android.bp . Esta sección explica la interfaz de línea de comandos xsdc , solo para completar. Esto puede resultar útil para depurar.

Debe proporcionar a la herramienta xsdc la ruta al archivo XSD y un paquete. El paquete es un nombre de paquete en código Java y un espacio de nombres en código C ++. Las opciones para determinar si el código generado es Java o C son -j o -c , respectivamente. La opción -o es la ruta del directorio de salida.

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 de ejemplo:

$ xsdc audio_policy_configuration.xsd -p audio.policy -j