تنفيذ واجهة برمجة التطبيقات Config File Schema API

يحتوي نظام Android الأساسي على العديد من ملفات XML لتخزين بيانات الضبط (مثل إعدادات الصوت). تقع العديد من ملفات XML في القسم vendor ، ولكن يتم قراءتها في القسم system. في هذه الحالة، يُعدّ المخطّط لملف XML بمثابة الواجهة بين القسمَين، وبالتالي πρέπει تحديد المخطّط صراحةً ويجب تطويره بطريقة متوافقة مع الإصدارات السابقة.

قبل الإصدار 10 من Android، لم توفّر المنصة mekanismes لطلب تحديد مخطّط XML واستخدامه، أو لمنع التغيُّرات غير المتوافقة في المخطّط. يقدّم نظام التشغيل Android 10 هذه الآلية التي تُعرف باسم Config File Schema API. تتألف هذه الآلية من أداة تُسمى xsdc وقاعدة إنشاء تُسمى xsd_config.

أداة xsdc هي أداة تجميع لمستند مخطّط XML ‏ (XSD). وهي تُحلِّل ملف XSD الذي يصف مخطّط ملف XML وتُنشئ رمز Java وC++. يُحلِّل الرمز المبرمَج المُنشئ ملفات XML المتوافقة مع مخطّط XSD إلى شجرة من العناصر، يمثّل كلّ منها علامة XML. يتم وضع سمات XML في حقول الكائنات.

تدمج قاعدة الإنشاء xsd_config أداة xsdc في نظام الإنشاء. بالنسبة إلى ملف إدخال XSD معيّن، تنشئ قاعدة الإنشاء مكتبتَي Java وC++. يمكنك ربط المكتبات بالوحدات التي يتم فيها قراءة ملفات XML المتوافقة مع schemaDTD واستخدامها. يمكنك استخدام قاعدة الإنشاء لملفات XML الخاصة بك المستخدَمة في قسمَي system وvendor.

Build Config File Schema API

يوضّح هذا القسم كيفية إنشاء واجهة برمجة التطبيقات Config File Schema 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

يُنشئ نظام الإنشاء قائمة بواجهة برمجة التطبيقات باستخدام رمز Java الذي تم إنشاؤه ويتحقّق من واجهة برمجة التطبيقات. تتم إضافة عملية التحقّق من واجهة برمجة التطبيقات هذه إلى DroidCore ويتم تنفيذها في m -j.

إنشاء ملفات قوائم واجهات برمجة التطبيقات

تتطلّب عمليات التحقّق من واجهة برمجة التطبيقات أن تُدرِج واجهة برمجة التطبيقات الملفات في رمز المصدر.

تشمل قائمة واجهة برمجة التطبيقات الملفات التالية:

  • يتحقّق current.txt وremoved.txt ممّا إذا تم تغيير واجهات برمجة التطبيقات من خلال مقارنة ملفات واجهات برمجة التطبيقات التي تم إنشاؤها في وقت الإنشاء.
  • يتحقق last_current.txt وlast_removed.txt مما إذا كانت واجهات برمجة التطبيقات متوافقة مع الإصدارات القديمة من خلال المقارنة مع ملفات واجهات برمجة التطبيقات.

لإنشاء ملفات قوائم واجهات برمجة التطبيقات:

  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/current.txt. من أجل الاتساق، يتم تحويل جميع أسماء العناصر والسمات إلى كتابة الجمل بالتنسيق اللاتيني (مثل ElementName) واستخدامها كسمة المتغيّر والطريقة واسم الفئة المقابلَين. يمكن الحصول على فئة العنصر الجذر الذي تم تحليله باستخدام الدالة read{class-name}. إذا كان هناك عنصر جذر واحد فقط، يكون اسم الدالة هو read. يمكن الحصول على قيمة عنصر فرعي أو سمة تم تحليلهما باستخدام الدالة get{variable-name}.

إنشاء رمز المُحلِّل

في معظم الحالات، ليس عليك تشغيل xsdc مباشرةً. استخدِم قاعدة الإنشاء xsd_config بدلاً من ذلك، كما هو موضّح في ضبط قاعدة الإنشاء xsd_config في Android.bp. يوضّح هذا القسم واجهة سطر الأوامر xsdc، وذلك من باب الكمال فقط. قد يكون هذا مفيدًا لتصحيح الأخطاء.

يجب منح أداة xsdc مسار ملف XSD وحزمة. تمثل الحزمة اسم حزمة في رمز 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