Yapılandırma Dosyası Şeması API'sini Uygulama

Android platformu, yapılandırma verilerini (örneğin, ses yapılandırması) depolamak için birçok XML dosyası içerir. XML dosyalarının çoğu vendor bölümündedir ancak system bölümünde okunurlar. Bu durumda, XML dosyasının şeması iki bölüm arasında arayüz görevi görür ve bu nedenle şemanın açıkça belirtilmesi ve geriye dönük olarak uyumlu bir şekilde gelişmesi gerekir.

Android 10'dan önce platform, XML şemasının belirtilmesini ve kullanılmasını gerektirecek veya şemada uyumsuz değişiklikleri önleyecek mekanizmalar sağlamıyordu. Android 10, Yapılandırma Dosyası Şeması API'si adı verilen bu mekanizmayı sağlar. Bu mekanizma, xsdc adı verilen bir araç ve xsd_config adı verilen bir derleme kuralından oluşur.

xsdc aracı bir XML Şema Belgesi (XSD) derleyicisidir. Bir XML dosyasının şemasını açıklayan bir XSD dosyasını ayrıştırır ve Java ve C++ kodu üretir. Oluşturulan kod, XSD şemasına uygun XML dosyalarını, her biri bir XML etiketini modelleyen bir nesne ağacına ayrıştırır. XML nitelikleri nesnelerin alanları olarak modellenir.

xsd_config derleme kuralı, xsdc aracını derleme sistemine entegre eder. Belirli bir XSD giriş dosyası için derleme kuralı Java ve C++ kitaplıkları oluşturur. Kütüphaneleri XSD'ye uygun XML dosyalarının okunduğu ve kullanıldığı modüllere bağlayabilirsiniz. Yapı kuralını, system ve vendor bölümlerinde kullanılan kendi XML dosyalarınız için kullanabilirsiniz.

Yapılandırma Dosyası Şeması API'si Oluşturma

Bu bölümde Yapılandırma Dosyası Şeması API'sinin nasıl oluşturulacağı açıklanmaktadır.

Android.bp'de xsd_config derleme kuralını yapılandırma

xsd_config derleme kuralı, xsdc aracıyla ayrıştırıcı kodunu oluşturur. xsd_config derleme kuralının package_name özelliği, oluşturulan Java kodunun paket adını belirler.

Android.bp örnek xsd_config derleme kuralı:

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

Örnek dizin yapısı:

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

Derleme sistemi, oluşturulan Java kodunu kullanarak bir API listesi oluşturur ve API'yi buna göre kontrol eder. Bu API kontrolü DroidCore'a eklenir ve m -j konumunda yürütülür.

API listeleri dosyaları oluşturma

API kontrolleri, kaynak kodundaki API listeleme dosyalarını gerektirir.

API listeleri dosyaları şunları içerir:

  • current.txt ve removed.txt derleme sırasında oluşturulan API dosyalarıyla karşılaştırarak API'lerin değişip değişmediğini kontrol eder.
  • last_current.txt ve last_removed.txt API dosyalarıyla karşılaştırarak API'lerin geriye dönük uyumlu olup olmadığını kontrol eder.

API listeleri dosyalarını oluşturmak için:

  1. Boş liste dosyaları oluşturun.
  2. make update-api komutunu çalıştırın.

Oluşturulan ayrıştırıcı kodunu kullanma

Oluşturulan Java kodunu kullanmak için, Java srcs özelliğindeki xsd_config modülü adına önek olarak : ekleyin. Oluşturulan Java kodunun paketi package_name özelliği ile aynıdır.

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

Oluşturulan C++ kodunu kullanmak için xsd_config modül adını generated_sources ve generated_headers özelliklerine ekleyin. Ve oluşturulan ayrıştırıcı kodunda libxml2 gerekli olduğundan, static_libs veya shared_libs libxml2 ekleyin. Oluşturulan C++ kodunun ad alanı package_name özelliğiyle aynıdır. Örneğin, xsd_config modül adı hal.manifest ise ad alanı hal::manifest olur.

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

Ayrıştırıcıyı kullanma

Java ayrıştırıcı kodunu kullanmak için, kök öğenin sınıfını döndürmek üzere XmlParser#read veya read{ class-name } yöntemini kullanın. Ayrıştırma şu anda gerçekleşir.

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();
            …
        }
    }
    …
}

C++ ayrıştırıcı kodunu kullanmak için öncelikle başlık dosyasını ekleyin. Başlık dosyasının adı, noktaların (.) alt çizgiye (_) dönüştürüldüğü paket adıdır. Daha sonra kök öğenin sınıfını döndürmek için read veya read{ class-name } yöntemini kullanın. Ayrıştırma şu anda gerçekleşir. Dönüş değeri bir std::optional<> dir.

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();
        …
    }
    …
}

Ayrıştırıcıyı kullanmak için sağlanan tüm API'ler api/current.txt dosyasındadır. Tekdüzelik sağlamak için, tüm öğe ve öznitelik adları deve durumuna dönüştürülür (örneğin, ElementName ) ve karşılık gelen değişken, yöntem ve sınıf adı olarak kullanılır. Ayrıştırılan kök öğenin sınıfı read{ class-name } işlevi kullanılarak elde edilebilir. Yalnızca bir kök öğe varsa işlevin adı read olur. Ayrıştırılmış bir alt öğenin veya özniteliğin değeri get{ variable-name } işlevi kullanılarak elde edilebilir.

Ayrıştırıcı kodu oluşturuluyor

Çoğu durumda xsdc doğrudan çalıştırmanıza gerek yoktur. Bunun yerine, Android.bp'de xsd_config derleme kuralını yapılandırma bölümünde açıklandığı gibi xsd_config derleme kuralını kullanın. Bu bölüm, tamlık sağlamak amacıyla xsdc komut satırı arayüzünü açıklamaktadır. Bu hata ayıklama için yararlı olabilir.

xsdc aracına XSD dosyasının yolunu ve bir paket vermelisiniz. Paket, Java kodundaki bir paket adı ve C++ kodundaki bir ad alanıdır. Oluşturulan kodun Java mı yoksa C mi olduğunu belirleme seçenekleri sırasıyla -j veya -c . -o seçeneği çıktı dizininin yoludur.

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

Örnek komut:

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