توفر خصائص النظام طريقة مناسبة لمشاركة المعلومات، عادةً ما تكون التكوينات، على مستوى النظام. يمكن لكل قسم استخدام خصائص النظام الخاصة به داخليًا. يمكن أن تحدث مشكلة عند الوصول إلى الخصائص عبر الأقسام، مثل /vendor
الذي يصل إلى /system
. منذ Android 8.0، يمكن ترقية بعض الأقسام، مثل /system
، بينما يتم ترك /vendor
دون تغيير. نظرًا لأن خصائص النظام هي مجرد قاموس عالمي لأزواج المفاتيح/القيم بدون مخطط، فمن الصعب تثبيت الخصائص. يمكن لقسم /system
تغيير أو إزالة الخصائص التي يعتمد عليها قسم /vendor
دون أي إشعار.
بدءًا من إصدار Android 10، يتم تخطيط خصائص النظام التي يتم الوصول إليها عبر الأقسام في ملفات وصف Sysprop، ويتم إنشاء واجهات برمجة التطبيقات للوصول إلى الخصائص كوظائف ملموسة لـ C++ وRust، وفئات لـ Java. تعد واجهات برمجة التطبيقات هذه أكثر ملاءمة للاستخدام نظرًا لعدم الحاجة إلى سلاسل سحرية (مثل ro.build.date
) للوصول إليها، ولأنه يمكن كتابتها بشكل ثابت. يتم أيضًا التحقق من استقرار واجهة برمجة التطبيقات (ABI) في وقت الإنشاء، وينقطع الإنشاء في حالة حدوث تغييرات غير متوافقة. يعمل هذا الفحص بمثابة واجهات محددة بوضوح بين الأقسام. يمكن لواجهات برمجة التطبيقات هذه أيضًا توفير الاتساق بين Rust وJava وC++.
تحديد خصائص النظام كواجهات برمجة التطبيقات (APIs).
قم بتعريف خصائص النظام كواجهات برمجة التطبيقات (APIs) مع ملفات وصف Sysprop ( .sysprop
)، والتي تستخدم تنسيق TextFormat الخاص بـ protobuf، مع المخطط التالي:
// File: sysprop.proto
syntax = "proto3";
package sysprop;
enum Access {
Readonly = 0;
Writeonce = 1;
ReadWrite = 2;
}
enum Owner {
Platform = 0;
Vendor = 1;
Odm = 2;
}
enum Scope {
Public = 0;
Internal = 2;
}
enum Type {
Boolean = 0;
Integer = 1;
Long = 2;
Double = 3;
String = 4;
Enum = 5;
UInt = 6;
ULong = 7;
BooleanList = 20;
IntegerList = 21;
LongList = 22;
DoubleList = 23;
StringList = 24;
EnumList = 25;
UIntList = 26;
ULongList = 27;
}
message Property {
string api_name = 1;
Type type = 2;
Access access = 3;
Scope scope = 4;
string prop_name = 5;
string enum_values = 6;
bool integer_as_bool = 7;
string legacy_prop_name = 8;
}
message Properties {
Owner owner = 1;
string module = 2;
repeated Property prop = 3;
}
يحتوي ملف وصف Sysprop واحد على رسالة خصائص واحدة تصف مجموعة من الخصائص. معنى مجالاتها هي كما يلي.
مجال | معنى |
---|---|
owner | اضبط على القسم الذي يمتلك الخصائص: Platform أو Vendor أو Odm . |
module | يُستخدم لإنشاء مساحة اسم (C++) أو فئة نهائية ثابتة (Java) حيث يتم وضع واجهات برمجة التطبيقات التي تم إنشاؤها. على سبيل المثال، سيكون com.android.sysprop.BuildProperties عبارة عن مساحة الاسم com::android::sysprop::BuildProperties في C++، وفئة BuildProperties في الحزمة في com.android.sysprop في Java. |
prop | قائمة الخصائص. |
معاني حقول رسالة Property
هي كما يلي.
مجال | معنى |
---|---|
api_name | اسم واجهة برمجة التطبيقات التي تم إنشاؤها. |
type | نوع هذا العقار. |
access | Readonly : يُنشئ واجهة برمجة تطبيقات getter فقط ملحوظة: الخصائص ذات البادئة |
scope | Internal : يمكن للمالك فقط الوصول إليه. |
prop_name | اسم خاصية النظام الأساسي، على سبيل المثال ro.build.date . |
enum_values | ( Enum و EnumList فقط) سلسلة مفصولة بشريط (|) تتكون من قيم التعداد المحتملة. على سبيل المثال، value1|value2 . |
integer_as_bool | ( Boolean ، BooleanList فقط) اجعل أدوات الضبط تستخدم 0 و 1 بدلاً من false و true . |
legacy_prop_name | (اختياري، خصائص Readonly فقط) الاسم القديم لخاصية النظام الأساسية. عند استدعاء getter، تحاول واجهة برمجة تطبيقات getter قراءة prop_name وتستخدم legacy_prop_name إذا لم يكن prop_name موجودًا. استخدم legacy_prop_name عند إيقاف خاصية موجودة والانتقال إلى خاصية جديدة. |
يرتبط كل نوع من الخصائص بالأنواع التالية في C++ وJava وRust.
يكتب | سي ++ | جافا | الصدأ |
---|---|---|---|
منطقية | std::optional<bool> | Optional<Boolean> | bool |
عدد صحيح | std::optional<std::int32_t> | Optional<Integer> | i32 |
UInt | std::optional<std::uint32_t> | Optional<Integer> | u32 |
طويل | std::optional<std::int64_t> | Optional<Long> | i64 |
ULong | std::optional<std::uint64_t> | Optional<Long> | u64 |
مزدوج | std::optional<double> | Optional<Double> | f64 |
خيط | std::optional<std::string> | Optional<String> | String |
التعداد | std::optional<{api_name}_values> | Optional<{api_name}_values> | {ApiName}Values |
قائمة T | std::vector<std::optional<T>> | List<T> | Vec<T> |
فيما يلي مثال لملف وصف Sysprop الذي يحدد ثلاث خصائص:
# File: android/sysprop/PlatformProperties.sysprop
owner: Platform
module: "android.sysprop.PlatformProperties"
prop {
api_name: "build_date"
type: String
prop_name: "ro.build.date"
scope: Public
access: Readonly
}
prop {
api_name: "date_utc"
type: Integer
prop_name: "ro.build.date_utc"
scope: Internal
access: Readonly
}
prop {
api_name: "device_status"
type: Enum
enum_values: "on|off|unknown"
prop_name: "device.status"
scope: Public
access: ReadWrite
}
تعريف مكتبات خصائص النظام
يمكنك الآن تحديد وحدات sysprop_library
باستخدام ملفات وصف Sysprop. يعمل sysprop_library
كواجهة برمجة تطبيقات لـ C++ وJava وRust. يقوم نظام البناء داخليًا بإنشاء rust_library
واحدة java_library
واحدة ومكتبة cc_library
واحدة لكل مثيل من sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
يجب عليك تضمين ملفات قوائم واجهة برمجة التطبيقات (API) في المصدر لإجراء عمليات فحص واجهة برمجة التطبيقات (API). للقيام بذلك، قم بإنشاء ملفات API ودليل api
. ضع دليل api
في نفس الدليل مثل Android.bp
. أسماء ملفات API هي <module_name>-current.txt
و <module_name>-latest.txt
. يحمل <module_name>-current.txt
توقيعات واجهة برمجة التطبيقات (API) لأكواد المصدر الحالية، ويحتفظ <module_name>-latest.txt
بأحدث توقيعات واجهة برمجة التطبيقات (API) المجمدة. يتحقق نظام البناء مما إذا تم تغيير واجهات برمجة التطبيقات من خلال مقارنة ملفات API هذه بملفات API التي تم إنشاؤها في وقت الإنشاء ويصدر رسالة خطأ وتعليمات لتحديث ملف current.txt
إذا لم يتطابق current.txt
مع أكواد المصدر. فيما يلي مثال لتنظيم الدليل والملف:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
يمكن ربط وحدات عملاء Rust وJava وC++ مع sysprop_library
لاستخدام واجهات برمجة التطبيقات التي تم إنشاؤها. يقوم نظام البناء بإنشاء روابط من العملاء إلى مكتبات C++ وJava وRust التي تم إنشاؤها، مما يمنح العملاء إمكانية الوصول إلى واجهات برمجة التطبيقات التي تم إنشاؤها.
java_library {
name: "JavaClient",
srcs: ["foo/bar.java"],
libs: ["PlatformProperties"],
}
cc_binary {
name: "cc_client",
srcs: ["baz.cpp"],
shared_libs: ["PlatformProperties"],
}
rust_binary {
name: "rust_client",
srcs: ["src/main.rs"],
rustlibs: ["libplatformproperties_rust"],
}
لاحظ أنه يتم إنشاء اسم مكتبة Rust عن طريق تحويل اسم sysprop_library
إلى أحرف صغيرة، واستبدال .
و -
مع _
، ثم إضافة lib
وإلحاق _rust
.
في المثال أعلاه، يمكنك الوصول إلى الخصائص المحددة على النحو التالي.
مثال الصدأ:
use platformproperties::DeviceStatusValues;
fn foo() -> Result<(), Error> {
// Read "ro.build.date_utc". default value is -1.
let date_utc = platformproperties::date_utc()?.unwrap_or_else(-1);
// set "device.status" to "unknown" if "ro.build.date" is not set.
if platformproperties::build_date()?.is_none() {
platformproperties::set_device_status(DeviceStatusValues::UNKNOWN);
}
…
}
مثال جافا:
import android.sysprop.PlatformProperties;
…
static void foo() {
…
// read "ro.build.date_utc". default value is -1
Integer dateUtc = PlatformProperties.date_utc().orElse(-1);
// set "device.status" to "unknown" if "ro.build.date" is not set
if (!PlatformProperties.build_date().isPresent()) {
PlatformProperties.device_status(
PlatformProperties.device_status_values.UNKNOWN
);
}
…
}
…
مثال C++:
#include <android/sysprop/PlatformProperties.sysprop.h>
using namespace android::sysprop;
…
void bar() {
…
// read "ro.build.date". default value is "(unknown)"
std::string build_date = PlatformProperties::build_date().value_or("(unknown)");
// set "device.status" to "on" if it's "unknown" or not set
using PlatformProperties::device_status_values;
auto status = PlatformProperties::device_status();
if (!status.has_value() || status.value() == device_status_values::UNKNOWN) {
PlatformProperties::device_status(device_status_values::ON);
}
…
}
…