ใช้ API สคีมาไฟล์กำหนดค่า

แพลตฟอร์ม Android มีไฟล์ XML จำนวนมากสำหรับจัดเก็บการกำหนดค่า (เช่น การกำหนดค่าเสียง) ไฟล์ XML หลายไฟล์อยู่ใน vendor แต่จะอ่านในพาร์ติชัน system ในกรณีนี้ สคีมา ไฟล์ XML ทำหน้าที่เป็นอินเทอร์เฟซใน 2 พาร์ติชัน ดังนั้น ต้องระบุสคีมาอย่างชัดเจนและต้องพัฒนาให้สอดคล้องกับเวอร์ชันย้อนหลัง ลักษณะ

ก่อน Android 10 แพลตฟอร์มนี้ไม่มี เพื่อกำหนดให้ระบุและใช้สคีมา XML หรือเพื่อป้องกัน การเปลี่ยนแปลงที่เข้ากันไม่ได้ในสคีมา Android 10 มาพร้อมกับ กลไกนี้ซึ่งเรียกว่า API สคีมาไฟล์การกำหนดค่า กลไกนี้ประกอบด้วยเครื่องมือ ชื่อ xsdc และกฎบิลด์ xsd_config

เครื่องมือ xsdc คือคอมไพเลอร์เอกสารสคีมา XML (XSD) แยกวิเคราะห์ไฟล์ XSD ซึ่งอธิบายสคีมาของไฟล์ XML และสร้างโค้ด Java และ C++ โค้ดที่สร้างขึ้นจะแยกวิเคราะห์ไฟล์ XML ที่สอดคล้องกับสคีมา XSD เป็นแผนผัง แต่ละโมเดลมีโมเดลแท็ก XML แอตทริบิวต์ XML จะมีโมเดลเป็นฟิลด์ ของออบเจ็กต์

กฎของบิลด์ xsd_config จะผสานรวมเครื่องมือ xsdc เข้ากับระบบบิลด์ สำหรับไฟล์อินพุต XSD ที่ระบุ กฎการสร้างจะสร้างไลบรารี Java และ C++ คุณ สามารถลิงก์ไลบรารีกับโมดูลซึ่งไฟล์ XML ที่สอดคล้องกับ อ่านและใช้ XSD แล้ว คุณสามารถใช้กฎบิลด์สำหรับไฟล์ XML ของคุณเองที่ใช้ ในพาร์ติชัน system และ vendor

API สคีมาไฟล์การกำหนดค่าบิลด์

ส่วนนี้จะอธิบายวิธีสร้าง API สคีมาไฟล์การกำหนดค่า

กำหนดค่ากฎบิลด์ xsd_config ใน Android.bp

กฎการสร้าง xsd_config จะสร้างโค้ดโปรแกรมแยกวิเคราะห์ด้วยเครื่องมือ xsdc พร็อพเพอร์ตี้ package_name ของ xsd_config ของกฎบิลด์จะระบุชื่อแพ็กเกจของ โค้ด Java ที่สร้างขึ้น

ตัวอย่างกฎของบิลด์ xsd_config ใน Android.bp

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

ตัวอย่างโครงสร้างไดเรกทอรี

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

ระบบบิลด์จะสร้างรายการ API โดยใช้โค้ด Java ที่สร้างขึ้นและการตรวจสอบ API นั้นตรงกันไม่ได้ การตรวจสอบ API นี้จะเพิ่มลงใน DroidCore และดำเนินการในเวลา m -j

สร้างไฟล์รายการ API

การตรวจสอบ API จำเป็นต้องมีรายการไฟล์ API ในซอร์สโค้ด

ไฟล์รายการ API ประกอบด้วย

  • current.txt และ removed.txt ตรวจสอบว่า API มีการเปลี่ยนแปลงหรือไม่ โดยเปรียบเทียบกับไฟล์ API ที่สร้างขึ้น ณ เวลาบิลด์
  • last_current.txt และ last_removed.txt ตรวจสอบว่า API มีการ ที่เข้ากันได้แบบย้อนหลัง โดยการเปรียบเทียบกับไฟล์ API

วิธีสร้างไฟล์รายการ API

  1. สร้างไฟล์รายการที่ว่างเปล่า
  2. เรียกใช้คำสั่ง make update-api

ใช้โค้ดโปรแกรมแยกวิเคราะห์ที่สร้างขึ้น

หากต้องการใช้โค้ด Java ที่สร้างขึ้น ให้เพิ่ม : เป็นคำนำหน้าไปยังโมดูล xsd_config ในพร็อพเพอร์ตี้ Java srcs แพ็กเกจของโค้ด Java ที่สร้างขึ้นคือ เหมือนกับพร็อพเพอร์ตี้ package_name

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

หากต้องการใช้โค้ด C++ ที่สร้างขึ้น ให้เพิ่มชื่อโมดูล xsd_config ลงใน generated_sources และพร็อพเพอร์ตี้ generated_headers และเพิ่ม libxml2 ไปที่ static_libs หรือ shared_libs เนื่องจากต้องใช้ libxml2 ในโปรแกรมแยกวิเคราะห์ที่สร้างขึ้น โค้ด เนมสเปซของ โค้ด C++ ที่สร้างขึ้นเหมือนกับพร็อพเพอร์ตี้ package_name ตัวอย่างเช่น หาก ชื่อโมดูล xsd_config คือ hal.manifest เนมสเปซคือ hal::manifest

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

ใช้โปรแกรมแยกวิเคราะห์

หากต้องการใช้โค้ดโปรแกรมแยกวิเคราะห์ Java ให้ใช้ XmlParser#read หรือ read{class-name} เพื่อแสดงผลคลาสของรูท การแยกวิเคราะห์จะเกิดขึ้นในเวลานี้

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++ ให้รวมไฟล์ส่วนหัวก่อน ชื่อของ ไฟล์ส่วนหัวคือชื่อแพ็กเกจที่มีจุด (.) แปลงเป็นขีดล่าง (_) จากนั้นใช้เมธอด read หรือ read{class-name} เพื่อแสดงผล คลาสขององค์ประกอบราก การแยกวิเคราะห์จะเกิดขึ้นในเวลานี้ ผลลัพธ์คือ 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();
        …
    }
    …
}

API ทั้งหมดที่ระบุให้ใช้โปรแกรมแยกวิเคราะห์อยู่ใน api/current.txt สำหรับ แบบเดียวกัน ชื่อองค์ประกอบและแอตทริบิวต์ทั้งหมดจะถูกแปลงเป็นตัวพิมพ์อูฐ (สำหรับ เช่น ElementName) และใช้เป็นตัวแปร เมธอด และ ชื่อชั้นเรียน คลาสขององค์ประกอบรากที่แยกวิเคราะห์แล้วสามารถหาได้โดยใช้ฟังก์ชัน read{class-name} หากมีเพียงรูทเดียว ชื่อฟังก์ชันจะเป็น read ค่าขององค์ประกอบย่อยที่แยกวิเคราะห์แล้ว หรือ รับแอตทริบิวต์ได้โดยใช้ get{variable-name}

สร้างโค้ดโปรแกรมแยกวิเคราะห์

ในกรณีส่วนใหญ่ คุณไม่จำเป็นต้องเรียกใช้ xsdc โดยตรง ใช้บิลด์ xsd_config แทน ตามที่อธิบายไว้ใน การกำหนดค่ากฎบิลด์ xsd_config ใน Android.bp ช่วงเวลานี้ ส่วนนี้จะอธิบายอินเทอร์เฟซบรรทัดคำสั่ง xsdc เพื่อความครบถ้วนสมบูรณ์ ช่วงเวลานี้ อาจเป็นประโยชน์ในการแก้ไขข้อบกพร่อง

คุณต้องกำหนดเส้นทางไปยังไฟล์ XSD และแพ็กเกจให้เครื่องมือ xsdc แพ็กเกจคือชื่อแพ็กเกจในโค้ด Java และเนมสเปซในโค้ด C++ ตัวเลือก เพื่อระบุว่าโค้ดที่สร้างขึ้นคือ Java หรือ C นั้นคือ -j หรือ -c ตามลำดับ ตัวเลือก -o คือเส้นทางของไดเรกทอรีเอาต์พุต

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

ตัวอย่างคำสั่ง

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