يحتوي نظام 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 المتوافقة مع schemaDTD واستخدامها. يمكنك استخدام قاعدة الإنشاء لملفات XML الخاصة بك المستخدَمة
في قسمَي system
وvendor
.
واجهة برمجة تطبيقات مخطط ملف ضبط الإعدادات
يوضّح هذا القسم كيفية إنشاء واجهة برمجة التطبيقات 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
في سمة 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
. من أجل
الاتساق، يتم تحويل جميع أسماء العناصر والسمات إلى كتابة الجمل بأسلوب CamelCase (على سبيل المثال،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