Sistem özellikleri, genellikle konfigürasyonlar olmak üzere sistem çapında bilgi paylaşımı için uygun bir yol sağlar. Her bölüm kendi sistem özelliklerini dahili olarak kullanabilir. /vendor
/system
tanımlı özelliklere erişmesi gibi özelliklere bölümler arasında erişildiğinde bir sorun ortaya çıkabilir. Android 8.0'dan bu yana, /system
gibi bazı bölümler yükseltilebilirken /vendor
değişmeden bırakılır. Sistem özellikleri, şeması olmayan, yalnızca dize anahtar/değer çiftlerinden oluşan genel bir sözlük olduğundan, özellikleri dengelemek zordur. /system
bölümü, /vendor
bölümünün bağlı olduğu özellikleri herhangi bir bildirimde bulunmaksızın değiştirebilir veya kaldırabilir.
Android 10 sürümünden başlayarak, bölümler arasında erişilen sistem özellikleri Sysprop Açıklama dosyaları halinde şematize edilir ve özelliklere erişim için API'ler, C++ ve Rust için somut işlevler ve Java için sınıflar olarak oluşturulur. Erişim için sihirli dizelere ( ro.build.date
gibi) ihtiyaç duyulmadığından ve statik olarak yazılabildiklerinden bu API'lerin kullanımı daha uygundur. ABI kararlılığı aynı zamanda derleme sırasında da kontrol edilir ve uyumsuz değişiklikler meydana gelirse derleme kesilir. Bu kontrol, bölümler arasında açıkça tanımlanmış arayüzler olarak işlev görür. Bu API'ler aynı zamanda Rust, Java ve C++ arasında tutarlılık da sağlayabilir.
Sistem özelliklerini API olarak tanımlama
Sistem özelliklerini, aşağıdaki şemayla protobuf'un TextFormat'ını kullanan Sysprop Açıklama dosyalarına ( .sysprop
) sahip API'ler olarak tanımlayın:
// 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;
}
Bir Sysprop Açıklama dosyası, bir dizi özelliği açıklayan bir özellikler mesajı içerir. Alanlarının anlamları aşağıdaki gibidir.
Alan | Anlam |
---|---|
owner | Şu özelliklere sahip olan bölüme ayarlayın: Platform , Vendor veya Odm . |
module | Oluşturulan API'lerin yerleştirildiği bir ad alanı (C++) veya statik son sınıf (Java) oluşturmak için kullanılır. Örneğin, com.android.sysprop.BuildProperties , C++'da com::android::sysprop::BuildProperties ad alanı ve Java'da com.android.sysprop pakette BuildProperties sınıfı olacaktır. |
prop | Özelliklerin listesi. |
Property
mesaj alanlarının anlamları aşağıdaki gibidir.
Alan | Anlam |
---|---|
api_name | Oluşturulan API'nin adı. |
type | Bu özelliğin türü. |
access | Readonly : Yalnızca alıcı API'sini oluşturur Not: |
scope | Internal : Yalnızca sahibi erişebilir. |
prop_name | Temel sistem özelliğinin adı, örneğin ro.build.date . |
enum_values | ( Yalnızca Enum , EnumList ) Olası numaralandırma değerlerinden oluşan çubuk(|) ile ayrılmış bir dize. Örneğin value1|value2 . |
integer_as_bool | (Yalnızca Boolean , BooleanList ) Ayarlayıcıların false ve true yerine 0 ve 1 kullanmasını sağlayın. |
legacy_prop_name | (isteğe bağlı, Yalnızca Readonly özellikler) Temel sistem özelliğinin eski adı. Alıcıyı çağırırken, alıcı API'si prop_name okumaya çalışır ve prop_name yoksa, legacy_prop_name kullanır. Mevcut bir mülkü kullanımdan kaldırırken ve yeni bir mülke taşırken legacy_prop_name kullanın. |
Her özellik türü C++, Java ve Rust'ta aşağıdaki türlerle eşlenir.
Tip | C++ | Java | Pas |
---|---|---|---|
Boolean | std::optional<bool> | Optional<Boolean> | bool |
Tamsayı | std::optional<std::int32_t> | Optional<Integer> | i32 |
Unt | std::optional<std::uint32_t> | Optional<Integer> | u32 |
Uzun | std::optional<std::int64_t> | Optional<Long> | i64 |
Uuzun | std::optional<std::uint64_t> | Optional<Long> | u64 |
Çift | std::optional<double> | Optional<Double> | f64 |
Sicim | std::optional<std::string> | Optional<String> | String |
Sıralama | std::optional<{api_name}_values> | Optional<{api_name}_values> | {ApiName}Values |
T Listesi | std::vector<std::optional<T>> | List<T> | Vec<T> |
Burada üç özelliği tanımlayan bir Sysprop Açıklama dosyası örneği verilmiştir:
# 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
}
Sistem özellikleri kitaplıklarını tanımlama
Artık sysprop_library
modüllerini Sysprop Açıklama dosyalarıyla tanımlayabilirsiniz. sysprop_library
, C++, Java ve Rust için bir API görevi görür. Derleme sistemi dahili olarak her sysprop_library
örneği için bir rust_library
, bir java_library
ve bir cc_library
oluşturur.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
API kontrolleri için kaynağa API listeleri dosyalarını dahil etmeniz gerekir. Bunu yapmak için API dosyaları ve bir api
dizini oluşturun. api
dizinini Android.bp
ile aynı dizine yerleştirin. API dosya adları <module_name>-current.txt
, <module_name>-latest.txt
şeklindedir. <module_name>-current.txt
geçerli kaynak kodlarının API imzalarını tutar ve <module_name>-latest.txt
en son dondurulmuş API imzalarını tutar. Derleme sistemi, bu API dosyalarını derleme sırasında oluşturulan API dosyalarıyla karşılaştırarak API'lerin değişip değişmediğini kontrol eder ve current.txt
kaynak kodlarıyla eşleşmezse current.txt
dosyasını güncellemek için bir hata mesajı ve talimatlar verir. Aşağıda örnek bir dizin ve dosya organizasyonu verilmiştir:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Rust, Java ve C++ istemci modülleri, oluşturulan API'leri kullanmak için sysprop_library
bağlanabilir. Derleme sistemi, istemcilerden oluşturulan C++, Java ve Rust kitaplıklarına bağlantılar oluşturarak müşterilerin oluşturulan API'lere erişmesini sağlar.
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 kitaplığı adının, sysprop_library
adının yerine küçük harfe dönüştürülmesiyle oluşturulduğunu unutmayın .
ve -
_
ile ve ardından lib
başına ve _rust
eklenmesi.
Yukarıdaki örnekte tanımlı özelliklere aşağıdaki gibi erişebilirsiniz.
Pas örneği:
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);
}
…
}
Java örneği:
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++ örneği:
#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);
}
…
}
…