O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Implementando a API Config File Schema

A plataforma Android contém muitos arquivos XML para armazenar dados de configuração (por exemplo, configuração de áudio). Muitos dos arquivos XML estão no vendor de partição, mas eles são lidos no system partição. Nesse caso, o esquema do arquivo XML serve como interface entre as duas partições e, portanto, o esquema deve ser especificado explicitamente e deve evoluir de maneira compatível com versões anteriores.

Antes do Android 10, a plataforma não fornecia mecanismos para exigir a especificação e o uso do esquema XML ou para evitar alterações incompatíveis no esquema. O Android 10 fornece esse mecanismo, denominado Config File Schema API. Este mecanismo consiste em uma ferramenta chamada xsdc e uma regra de compilação chamado xsd_config .

O xsdc ferramenta é um compilador XML Schema Document (XSD). Ele analisa um arquivo XSD que descreve o esquema de um arquivo XML e gera código Java e C ++. O código gerado analisa os arquivos XML que estão em conformidade com o esquema XSD em uma árvore de objetos, cada um dos quais modela uma marca XML. Os atributos XML são modelados como campos dos objetos.

O xsd_config regra de construção integra o xsdc ferramenta no sistema de compilação. Para um determinado arquivo de entrada XSD, a regra de construção gera bibliotecas Java e C ++. Você pode vincular as bibliotecas aos módulos onde os arquivos XML que estão em conformidade com o XSD são lidos e usados. Você pode usar a regra de construção para seus próprios arquivos XML usado em todo o system e vendor partições.

API Building Config File Schema

Esta seção descreve como construir a API do esquema de arquivo de configuração.

Configurando a regra de compilação xsd_config em Android.bp

O xsd_config regra de construção gera o código do analisador com a xsdc ferramenta. O xsd_config da regra de construção package_name propriedade determina o nome do pacote do código Java gerado.

Exemplo xsd_config regra de construção em Android.bp :

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

Exemplo de estrutura de diretório:

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

O sistema de construção gera uma lista de APIs usando o código Java gerado e verifica a API em relação a ele. Esta verificação API é adicionado ao DroidCore e executado pelo m -j .

Criação de arquivos de listas de API

As verificações de API requerem arquivos de listas de API no código-fonte.

Os arquivos de listas de APIs incluem:

  • current.txt e removed.txt verificação se as APIs são alteradas através da comparação com os arquivos API geradas em tempo de compilação.
  • last_current.txt e last_removed.txt verificação se as APIs são compatíveis comparando com arquivos API.

Para criar os arquivos de listas de API:

  1. Crie arquivos de listas vazias.
  2. Execute o comando make update-api .

Usando código de analisador gerado

Para usar o código Java gerado, adicione : como um prefixo para o xsd_config nome do módulo no Java srcs propriedade. O pacote do código Java gerado é o mesmo que o package_name propriedade.

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

Para usar o código gerado C ++, adicione o xsd_config nome do módulo para os generated_sources e generated_headers propriedades. E adicione libxml2 para static_libs ou shared_libs , desde libxml2 é necessária em código do analisador gerado. O namespace do código gerado C ++ é o mesmo que o package_name propriedade. Por exemplo, se o xsd_config nome do módulo é hal.manifest , o namespace é hal::manifest .

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

Usando o analisador

Para usar o código do analisador Java, utilize o XmlParser#read ou read{ class-name } método para retornar a classe do elemento raiz. A análise ocorre neste 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 o código do analisador C ++, primeiro inclua o arquivo de cabeçalho. O nome do arquivo de cabeçalho é o nome do pacote com pontos (.) Convertidos em sublinhados (_). Em seguida, use a read ou read{ class-name } método para retornar a classe do elemento raiz. A análise ocorre neste momento. O valor de retorno é um 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 as APIs fornecidas para usar o analisador estão em api/current.txt . Para uniformidade, todos os nomes de elementos de atributo e são convertidos em caso de camelo (por exemplo, ElementName ) e usado como a variável, o método e o nome de classe correspondente. A classe do elemento raiz analisada, pode ser obtida usando a read{ class-name } função. Se houver apenas um elemento raiz, em seguida, o nome da função é read . O valor de um sub-elemento analisado ou atributo pode ser obtida usando o get{ variable-name } função.

Gerando código do analisador

Na maioria dos casos, você não precisa executar xsdc diretamente. Use o xsd_config regra de construção em vez disso, conforme descrito em Configurar a regra de construção xsd_config em Android.bp . Esta secção explica o xsdc interface de linha de comando, apenas para ser completo. Isso pode ser útil para depuração.

Você deve dar o xsdc ferramenta o caminho para o arquivo XSD, e um pacote. O pacote é um nome de pacote no código Java e um namespace no código C ++. As opções para determinar se o código gerado é Java ou C são -j ou -c , respectivamente. O -o opção é o caminho do diretório de saída.

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 exemplo:

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