پلتفرم اندروید حاوی بسیاری از فایل های XML برای ذخیره داده های پیکربندی (به عنوان مثال، پیکربندی صوتی) است. بسیاری از فایل های XML در پارتیشن vendor
هستند، اما در پارتیشن system
خوانده می شوند. در این مورد، طرح فایل XML به عنوان رابط بین دو پارتیشن عمل می کند، و بنابراین طرحواره باید به صراحت مشخص شود و باید به شیوه ای سازگار با عقب تکامل یابد.
قبل از اندروید 10، این پلتفرم مکانیسمهایی را برای نیاز به تعیین و استفاده از طرحواره XML یا جلوگیری از تغییرات ناسازگار در طرح ارائه نمیکرد. اندروید 10 این مکانیزم را به نام Config File Schema API ارائه می کند. این مکانیزم از ابزاری به نام xsdc
و یک قانون ساخت به نام xsd_config
تشکیل شده است.
ابزار xsdc
یک کامپایلر XML Schema Document (XSD) است. این یک فایل XSD را که طرحواره یک فایل XML را توصیف می کند، تجزیه می کند و کد جاوا و C++ را تولید می کند. کد تولید شده فایلهای XML را که با طرح XSD مطابقت دارند، به درختی از اشیاء تجزیه میکند، که هر کدام یک تگ XML را مدلسازی میکنند. ویژگی های XML به عنوان فیلدهای اشیاء مدل می شوند.
قانون ساخت xsd_config
ابزار xsdc
را در سیستم ساخت ادغام می کند. برای یک فایل ورودی XSD معین، قانون ساخت، کتابخانه های جاوا و C++ را تولید می کند. میتوانید کتابخانهها را به ماژولهایی پیوند دهید که فایلهای XML مطابق با XSD خوانده و استفاده میشوند. میتوانید از قانون ساخت برای فایلهای XML خود که در سراسر system
و پارتیشنهای vendor
استفاده میشوند استفاده کنید.
Build Config File Schema API
این بخش نحوه ساخت Config File Schema API را توضیح می دهد.
قانون ساخت xsd_config را در Android.bp پیکربندی کنید
قانون ساخت xsd_config
کد تجزیه کننده را با ابزار xsdc
تولید می کند. ویژگی package_name
قانون ساخت xsd_config
نام بسته کد جاوا تولید شده را تعیین می کند.
مثال قانون ساخت 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
سیستم ساخت یک لیست API را با استفاده از کد جاوا ایجاد می کند و API را در برابر آن بررسی می کند. این بررسی API به DroidCore اضافه شده و در m -j
اجرا می شود.
فایل های لیست های API را ایجاد کنید
بررسی های API به فهرست های API در کد منبع نیاز دارد.
فایل های لیست API عبارتند از:
-
current.txt
وremoved.txt
بررسی کنید که آیا APIها با مقایسه با فایلهای API تولید شده در زمان ساخت تغییر کردهاند یا خیر. -
last_current.txt
وlast_removed.txt
با مقایسه با فایلهای API بررسی میکنند که آیا APIها با نسخه قبلی سازگار هستند.
برای ایجاد فایل های لیست های API:
- فایل های لیست خالی ایجاد کنید.
- دستور
make update-api
را اجرا کنید.
از کد تجزیه کننده تولید شده استفاده کنید
برای استفاده از کد جاوای تولید شده، :
به عنوان پیشوند به نام ماژول xsd_config
در ویژگی Java srcs
اضافه کنید. بسته کد جاوای تولید شده همان ویژگی 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 های ارائه شده برای استفاده از تجزیه کننده در api/current.txt
هستند. برای یکنواختی، همه نامهای عناصر و ویژگیها به camel case (به عنوان مثال ElementName
) تبدیل میشوند و به عنوان متغیر، متد و نام کلاس مربوطه استفاده میشوند. کلاس عنصر ریشه تجزیه شده را می توان با استفاده از تابع read{ class-name }
بدست آورد. اگر فقط یک عنصر ریشه وجود داشته باشد، نام تابع read
می شود. مقدار یک عنصر فرعی یا ویژگی تجزیه شده را می توان با استفاده از تابع get{ variable-name }
بدست آورد.
کد تجزیه کننده را ایجاد کنید
در بیشتر موارد، نیازی به اجرای مستقیم xsdc
ندارید. به جای آن از قانون ساخت xsd_config
استفاده کنید، همانطور که در پیکربندی قانون ساخت xsd_config در Android.bp توضیح داده شده است. این بخش رابط خط فرمان xsdc
را فقط برای کامل بودن توضیح می دهد. این ممکن است برای رفع اشکال مفید باشد.
شما باید مسیر فایل XSD و یک بسته را به ابزار xsdc
بدهید. بسته یک نام بسته در کد جاوا و یک فضای نام در کد ++C است. گزینه های تعیین جاوا یا 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