Android প্ল্যাটফর্মে কনফিগারেশন
ডেটা (যেমন, অডিও কনফিগারেশন) সেভ করার জন্য অনেক XML ফাইল থাকে। অনেক XML ফাইল vendor
পার্টিশনে আছে, কিন্তু সেগুলি system পার্টিশনে পড়া হয়। এই ক্ষেত্রে, XML ফাইলের স্কিমা
দুটি পার্টিশন জুড়ে ইন্টারফেস হিসেবে কাজ করে এবং সেইজন্য
স্কিমা স্পষ্টভাবে উল্লেখ করতে হবে এবং ব্যাকওয়ার্ড-কম্প্যাটিবল
পদ্ধতিতে তা উন্নত করতে হবে।
Android 10-এর আগে, প্ল্যাটফর্ম XML স্কিমা নির্দিষ্ট করা ও ব্যবহার করার জন্য
কোনও মেকানিজম প্রদান করেনি অথবা স্কিমায় মানানসই নয় এমন পরিবর্তন
প্রতিরোধ করার জন্য কোনও মেকানিজম প্রদান করেনি। Android 10
এই মেকানিজম প্রদান করে, যাকে কনফিগারেশন ফাইল স্কিমা API বলা হয়। এই মেকানিজমে xsdc নামক একটি টুল
এবং xsd_config নামক একটি বিল্ড রুল থাকে।
xsdc টুলটি হল XML স্কিমা ডকুমেন্ট (XSD) কম্পাইলার। এটি XML ফাইলের স্কিমা বর্ণনা করে এমন একটি XSD ফাইল
পার্স করে এবং Java ও C++ কোড তৈরি করে। জেনারেট করা কোড XSD স্কিমা মেনে চলা XML ফাইলগুলিকে
অবজেক্টের ট্রি-তে পার্স করে, যার প্রতিটি একটি XML ট্যাগ মডেল করে।
XML অ্যাট্রিবিউটকে অবজেক্টের ফিল্ড
হিসেবে মডেল করা হয়।
xsd_config বিল্ড রুল, বিল্ড সিস্টেমে xsdc টুলকে ইন্টিগ্রেট করে।
প্রদত্ত XSD ইনপুট ফাইলের জন্য, বিল্ড রুল Java এবং C++ লাইব্রেরি তৈরি করে। আপনি
লাইব্রেরিগুলিকে সেইসব মডিউলের সাথে লিঙ্ক করতে পারেন যেখানে XSD-এর সাথে মানানসই XML ফাইলগুলি
পড়া ও ব্যবহার করা হয়। system ও vendor পার্টিশন জুড়ে ব্যবহৃত আপনার নিজস্ব XML ফাইলের জন্য
বিল্ড নিয়ম ব্যবহার করতে পারবেন।
Build Config File Schema API
এই বিভাগে, কীভাবে কনফিগারেশন ফাইল স্কিমা API তৈরি করতে হয় তা বর্ণনা করা হয়েছে।
Android.bp-তে xsd_config বিল্ড নিয়ম কনফিগার করা
xsd_config বিল্ড রুল xsdc টুলের সাহায্যে পার্সার কোড তৈরি করে। জেনারেট করা Java কোডের
প্যাকেজের নাম xsd_config বিল্ড রুলের package_name প্রপার্টি নির্ধারণ করে।
Android.bp-এ xsd_config বিল্ড রুলের উদাহরণ:
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.txtAPI ফাইলের সাথে তুলনা করে API ব্যাকওয়ার্ড কম্প্যাটিবল কিনা তা চেক করে।
API তালিকা ফাইল তৈরি করতে:
- খালি তালিকার ফাইল তৈরি করা।
make update-apiকমান্ডটি রান করুন।
জেনারেট করা পার্সার কোড ব্যবহার করুন
জেনারেট করা Java কোড ব্যবহার করতে, Java srcs প্রপার্টিতে xsd_config মডিউল
নামের আগে : প্রিফিক্স যোগ করুন। জেনারেট করা 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 api/current.txt-এ আছে। একই রকম রাখার জন্য, সব এলিমেন্ট ও অ্যাট্রিবিউটের নাম ক্যামেল কেসে (যেমন, ElementName) কনভার্ট করা হয় এবং সংশ্লিষ্ট ভেরিয়েবল, মেথড ও
ক্লাসের নাম হিসেবে ব্যবহার করা হয়। পার্স করা রুট এলিমেন্টের ক্লাস
read{class-name} ফাংশন ব্যবহার করে পাওয়া যেতে পারে। যদি শুধুমাত্র একটি রুট
এলিমেন্ট থাকে, তাহলে ফাংশনের নাম হবে read। get{variable-name} ফাংশন ব্যবহার করে পার্স করা সাব-এলিমেন্ট বা অ্যাট্রিবিউটের ভ্যালু পাওয়া যেতে পারে।
পার্সার কোড জেনারেট করুন
বেশিরভাগ ক্ষেত্রে, আপনাকে xsdc সরাসরি রান করতে হবে না। এর পরিবর্তে xsd_config build
rule ব্যবহার করুন, যেমন
Android.bp-তে xsd_config build rule কনফিগার করা নিবন্ধে বর্ণনা করা হয়েছে। এই
বিভাগে 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