कॉन्फ़िग फ़ाइल स्कीमा एपीआई लागू करना

एंड्रॉइड प्लेटफ़ॉर्म में कॉन्फ़िगरेशन डेटा संग्रहीत करने के लिए कई XML फ़ाइलें हैं (उदाहरण के लिए, ऑडियो कॉन्फ़िगरेशन)। कई XML फ़ाइलें vendor विभाजन में हैं, लेकिन वे system विभाजन में पढ़ी जाती हैं। इस मामले में, XML फ़ाइल का स्कीमा दो विभाजनों में इंटरफ़ेस के रूप में कार्य करता है, और इसलिए स्कीमा को स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए और पिछड़े-संगत तरीके से विकसित होना चाहिए।

एंड्रॉइड 10 से पहले, प्लेटफ़ॉर्म XML स्कीमा को निर्दिष्ट करने और उपयोग करने या स्कीमा में असंगत परिवर्तनों को रोकने के लिए तंत्र प्रदान नहीं करता था। एंड्रॉइड 10 यह तंत्र प्रदान करता है, जिसे कॉन्फ़िग फ़ाइल स्कीमा एपीआई कहा जाता है। इस तंत्र में xsdc नामक एक उपकरण और xsd_config नामक एक बिल्ड नियम शामिल है।

xsdc टूल एक XML स्कीमा दस्तावेज़ (XSD) कंपाइलर है। यह एक XML फ़ाइल की स्कीमा का वर्णन करते हुए एक XSD फ़ाइल को पार्स करता है और Java और C++ कोड उत्पन्न करता है। जेनरेट किया गया कोड XSD स्कीमा के अनुरूप XML फ़ाइलों को ऑब्जेक्ट के एक पेड़ में पार्स करता है, जिनमें से प्रत्येक एक XML टैग को मॉडल करता है। XML विशेषताओं को ऑब्जेक्ट के फ़ील्ड के रूप में मॉडल किया गया है।

xsd_config बिल्ड नियम xsdc टूल को बिल्ड सिस्टम में एकीकृत करता है। किसी दिए गए XSD इनपुट फ़ाइल के लिए, बिल्ड नियम जावा और C++ लाइब्रेरी उत्पन्न करता है। आप पुस्तकालयों को उन मॉड्यूल से लिंक कर सकते हैं जहां XSD के अनुरूप XML फ़ाइलें पढ़ी और उपयोग की जाती हैं। आप system और vendor विभाजन में उपयोग की जाने वाली अपनी स्वयं की XML फ़ाइलों के लिए बिल्ड नियम का उपयोग कर सकते हैं।

कॉन्फ़िग फ़ाइल स्कीमा एपीआई का निर्माण

यह अनुभाग बताता है कि कॉन्फ़िग फ़ाइल स्कीमा एपीआई कैसे बनाया जाए।

Android.bp में xsd_config बिल्ड नियम को कॉन्फ़िगर करना

xsd_config बिल्ड नियम xsdc टूल के साथ पार्सर कोड उत्पन्न करता है। xsd_config बिल्ड नियम का package_name गुण जेनरेट किए गए जावा कोड का पैकेज नाम निर्धारित करता है।

Android.bp में उदाहरण xsd_config बिल्ड नियम:

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

बिल्ड सिस्टम जेनरेट किए गए जावा कोड का उपयोग करके एक एपीआई सूची तैयार करता है और इसके विरुद्ध एपीआई की जांच करता है। यह एपीआई जांच DroidCore में जोड़ी गई है और m -j पर निष्पादित की गई है।

एपीआई सूची फ़ाइलें बनाना

एपीआई जांच के लिए स्रोत कोड में एपीआई सूची फ़ाइलों की आवश्यकता होती है।

एपीआई सूची फ़ाइलों में शामिल हैं:

  • current.txt और removed.txt बिल्ड समय पर जेनरेट की गई एपीआई फ़ाइलों के साथ तुलना करके जांच करते हैं कि एपीआई बदले गए हैं या नहीं।
  • last_current.txt और last_removed.txt एपीआई फ़ाइलों के साथ तुलना करके जांच करते हैं कि एपीआई पिछड़े संगत हैं या नहीं।

एपीआई सूची फ़ाइलें बनाने के लिए:

  1. खाली सूचियाँ फ़ाइलें बनाएँ।
  2. make update-api कमांड चलाएँ।

उत्पन्न पार्सर कोड का उपयोग करना

जेनरेट किए गए जावा कोड का उपयोग करने : लिए, जावा srcs प्रॉपर्टी में xsd_config मॉड्यूल नाम के उपसर्ग के रूप में जोड़ें। जनरेट किए गए जावा कोड का पैकेज 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"],
}

पार्सर का उपयोग करना

जावा पार्सर कोड का उपयोग करने के लिए, मूल तत्व की कक्षा को वापस करने के लिए 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/current.txt में हैं। एकरूपता के लिए, सभी तत्व और विशेषता नामों को कैमल केस में परिवर्तित किया जाता है (उदाहरण के लिए, ElementName ) और संबंधित चर, विधि और वर्ग नाम के रूप में उपयोग किया जाता है। पार्स किए गए रूट तत्व का वर्ग read{ class-name } फ़ंक्शन का उपयोग करके प्राप्त किया जा सकता है। यदि केवल एक मूल तत्व है, तो फ़ंक्शन नाम read है। पार्स किए गए उपतत्व या विशेषता का मान get{ variable-name } फ़ंक्शन का उपयोग करके प्राप्त किया जा सकता है।

पार्सर कोड जनरेट करना

अधिकांश मामलों में, आपको सीधे xsdc चलाने की आवश्यकता नहीं है। इसके बजाय xsd_config बिल्ड नियम का उपयोग करें, जैसा कि Android.bp में xsd_config बिल्ड नियम को कॉन्फ़िगर करना में वर्णित है। यह अनुभाग पूर्णता के लिए xsdc कमांड लाइन इंटरफ़ेस की व्याख्या करता है। यह डिबगिंग के लिए उपयोगी हो सकता है.

आपको xsdc टूल को XSD फ़ाइल का पथ और एक पैकेज देना होगा। पैकेज जावा कोड में एक पैकेज नाम और 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