Sistem özellikleri, genellikle yapılandırmalar olmak üzere bilgileri sistem genelinde paylaşmanın kolay bir yolunu sunar. Her bölüm, kendi sistem özelliklerini dahili olarak kullanabilir. Mülklere bölümler arasında erişildiğinde (ör. /vendor
, /system
tanımlı mülklere eriştiğinde) sorun oluşabilir. Android 8.0'dan itibaren /system
gibi bazı bölümler yükseltilebilirken /vendor
bölümü değiştirilmez. Sistem özellikleri, şeması olmayan yalnızca genel bir dize anahtar-değer çiftleri sözlüğü olduğundan özellikleri sabitlemek zordur. /system
bölümü, /vendor
bölümünün bağlı olduğu özellikleri herhangi bir bildirimde bulunmadan değiştirebilir veya kaldırabilir.
Android 10 sürümünden itibaren, bölümler arasında erişilen sistem özellikleri Sysprop Açıklama dosyaları olarak şematize edilir ve özelliklere erişmek için API'ler C++ ve Rust için somut işlevler, Java için ise sınıflar olarak oluşturulur. Bu API'ler, erişim için sihirli dizeler (ör. ro.build.date
) gerekmediğinden ve statik olarak yazılabildiklerinden daha kolay kullanılır. ABI kararlılığı, derleme sırasında da kontrol edilir ve uyumsuz değişiklikler olursa derleme bozulur. Bu kontrol, bölümler arasında açıkça tanımlanmış arayüzler olarak işlev görür. Bu API'ler, Rust, Java ve C++ arasında tutarlılık da sağlayabilir.
Sistem özelliklerini API olarak tanımlama
Sistem özelliklerini, aşağıdaki şemaya sahip protobuf'un TextFormat'ını kullanan Sysprop Açıklama dosyaları (.sysprop
) ile API 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 özellikler mesajı içerir. Bu mesaj, bir özellikler grubunu açıklar. Alanlarının anlamı aşağıdaki gibidir.
Alan | Anlamı |
---|---|
owner
|
Platform , Vendor veya Odm özelliklerinin sahibi olan bölüme ayarlayın.
|
module
|
Oluşturulan API'lerin yerleştirildiği bir ad alanı (C++) veya statik nihai 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ı,
Java'da ise com.android.sysprop paketindeki BuildProperties sınıfı olur.
|
prop
|
Tesislerin listesi. |
Property
mesaj alanlarının anlamları aşağıdaki gibidir.
Alan | Anlamı |
---|---|
api_name
|
Oluşturulan API'nin adı. |
type
|
Bu mülkün türü. |
access
|
Readonly : Yalnızca getter API'si oluşturur.
Writeonce , ReadWrite : Getter ve setter API'leri oluşturur.
Not: ro. önekine sahip özellikler ReadWrite erişimini kullanamayabilir.
|
scope
|
Internal : Yalnızca sahibi erişebilir.
Public : NDK modülleri hariç herkes erişebilir.
|
prop_name
|
Temel sistem özelliğinin adı (ör. ro.build.date ).
|
enum_values
|
(Yalnızca Enum , EnumList ) Olası enum 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 özellikleri) Temel sistem özelliğinin eski adı. Getter çağrıldığında, getter API'si prop_name değerini okumaya çalışır ve prop_name değeri yoksa legacy_prop_name değerini kullanır. Mevcut bir mülkün desteğini sonlandırıp yeni bir mülke geçerken legacy_prop_name özelliğini kullanın.
|
Her özellik türü, C++, Java ve Rust'ta aşağıdaki türlerle eşlenir.
Tür | C++ | Java | Rust |
---|---|---|---|
Boole | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Tam sayı | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
UInt | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Uzun | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
ULong | std::optional<std::uint64_t>
|
Optional<Long>
|
u64
|
Çift | std::optional<double>
|
Optional<Double>
|
f64
|
Dize | std::optional<std::string>
|
Optional<String>
|
String
|
Enum | std::optional<{api_name}_values>
|
Optional<{api_name}_values>
|
{ApiName}Values
|
T List | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Üç özelliği tanımlayan bir Sysprop Açıklama dosyası örneğini aşağıda bulabilirsiniz:
# 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 Açıklama dosyalarıyla sysprop_library
modüllerini tanımlayabilirsiniz.
sysprop_library
, C++, Java ve Rust için bir API görevi görür. Derleme sistemi, her sysprop_library
örneği için dahili olarak 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 kaynakta API listeleri dosyalarını eklemeniz 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
. <module_name>-current.txt
, mevcut kaynak kodlarının API imzalarını, <module_name>-latest.txt
ise en son dondurulmuş API imzalarını içerir. Derleme sistemi, bu API dosyalarını derleme zamanında oluşturulan API dosyalarıyla karşılaştırarak API'lerin değiştirilip değiştirilmediğini kontrol eder ve current.txt
kaynak kodlarla eşleşmezse current.txt
dosyasını güncellemek için bir hata mesajı ve talimatlar yayınlar. Aşağıda bir dizin ve dosya düzeni örneği verilmiştir:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Oluşturulan API'leri kullanmak için Rust, Java ve C++ istemci modülleri sysprop_library
ile bağlantı oluşturabilir. Derleme sistemi, istemcilerden oluşturulan C++, Java ve Rust kitaplıklarına bağlantılar oluşturarak istemcilere oluşturulan API'lere erişim sağlar.
java_library {
name: "JavaClient",
srcs: ["foo/bar.java"],
libs: ["PlatformProperties"],
}
cc_binary {
name: "cc_client",
srcs: ["baz.cpp"],
shared_libs: ["libPlatformProperties"],
}
rust_binary {
name: "rust_client",
srcs: ["src/main.rs"],
rustlibs: ["libplatformproperties_rust"],
}
Rust kitaplık adının, sysprop_library
adını küçük harfe dönüştürerek, .
ve -
yerine _
koyarak, ardından lib
ekleyip _rust
ekleyerek oluşturulduğunu unutmayın.
Önceki örnekte, tanımlanan özelliklere aşağıdaki gibi erişebilirsiniz.
Rust ö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);
}
…
}
…