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

تحتوي منصة Android على العديد من ملفات XML لتخزين بيانات الإعداد (مثل إعدادات الصوت). توجد العديد من ملفات XML في القسم vendor، ولكن تتم قراءتها في القسم system. في هذه الحالة، يعمل مخطط ملف XML كواجهة بين القسمين، وبالتالي يجب تحديد المخطط بشكل صريح ويجب أن يتطوّر بطريقة متوافقة مع الإصدارات السابقة.

قبل الإصدار 10 من نظام التشغيل Android، لم تكن المنصة توفّر آليات تتيح فرض تحديد واستخدام مخطط 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 المتوافقة مع XSD واستخدامها. يمكنك استخدام قاعدة الإنشاء لملفات XML الخاصة بك المستخدَمة في كل من قسمَي system وvendor.

Build 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 في السمة srcs في Java. حزمة رمز 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. للحفاظ على التناسق، يتم تحويل جميع أسماء العناصر والسمات إلى تنسيق camel case (على سبيل المثال، 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