تحتوي منصة 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
مما إذا كانت واجهات برمجة التطبيقات متوافقة مع الإصدارات القديمة من خلال مقارنتها بملفات واجهة برمجة التطبيقات.
لإنشاء ملفات قوائم واجهة برمجة التطبيقات، اتّبِع الخطوات التالية:
- إنشاء ملفات قوائم فارغة
- نفِّذ الأمر
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