פלטפורמת אנדרואיד מכילה קבצי XML רבים לאחסון נתוני תצורה (לדוגמה, תצורת אודיו). רבים מקובצי ה-XML נמצאים במחיצת vendor
, אך הם נקראים במחיצת system
. במקרה זה, הסכימה של קובץ ה-XML משמשת כממשק על פני שתי המחיצות, ולכן יש לציין את הסכימה במפורש ועליה להתפתח באופן תואם לאחור.
לפני אנדרואיד 10, הפלטפורמה לא סיפקה מנגנונים לדרוש ציון ושימוש בסכימת XML, או כדי למנוע שינויים לא תואמים בסכימה. אנדרואיד 10 מספק מנגנון זה, הנקרא Config File Schema API. מנגנון זה מורכב מכלי שנקרא xsdc
ומכלל בנייה בשם xsd_config
.
הכלי xsdc
הוא מהדר XML Schema Document (XSD). הוא מנתח קובץ XSD המתאר את הסכימה של קובץ XML ומייצר קוד Java ו-C++. הקוד שנוצר מנתח קובצי XML התואמים את סכימת XSD לעץ של אובייקטים, שכל אחד מהם מדגמן תג XML. תכונות XML מעוצבות כשדות של האובייקטים.
כלל הבנייה xsd_config
משלב את הכלי xsdc
במערכת הבנייה. עבור קובץ קלט XSD נתון, כלל הבנייה מייצר ספריות Java ו-C++. אתה יכול לקשר את הספריות למודולים שבהם קוראים ומשתמשים בקבצי ה-XML התואמים ל-XSD. אתה יכול להשתמש בכלל הבנייה עבור קבצי XML משלך המשמשים בכל מחיצות system
vendor
.
בניית 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
מערכת ה-build מייצרת רשימת API באמצעות קוד ה-Java שנוצר ובודקת את ה-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
.
שימוש בקוד מנתח שנוצר
כדי להשתמש בקוד 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
or 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
or 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
. למען אחידות, כל שמות האלמנטים והתכונה מומרים לאותיות גמל (לדוגמה, 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