Sistem özellikleri, bilgileri (genellikle yapılandırmaları) sistem genelinde paylaşmak için kullanışlı bir yol sunar. Her bölüm, kendi sistem özelliklerini dahili olarak kullanabilir. Özelliklere bölümlerden erişildiğinde (ör. /vendor
, /system
tarafından tanımlanan özelliklere eriştiğinde) bir sorun oluşabilir. Android 8.0'dan itibaren /system
gibi bazı bölümler yükseltilebilir ve /vendor
değiştirilmeden bırakılır. Sistem özellikleri, şema içermeyen dize anahtar/değer çiftlerinin yalnızca genel bir sözlüğü olduğundan, özellikleri sabitlemek zordur. /system
bölümü, /vendor
bölümünün bağımlı olduğu özellikleri herhangi bir bildirimde bulunmadan değiştirebilir veya kaldırabilir.
Android 10 sürümünden itibaren, bölümlerden erişilen sistem özellikleri Sysprop Description dosyalarına şematikleştirilerek, özelliklere erişmek için kullanılan API'ler C++ ve Rust için somut işlevler, Java için sınıflar şeklinde oluşturulur. Erişim için sihirli dizelere (ro.build.date
gibi) gerek olmadığından ve bunlar statik olarak yazılabileceğinden bu API'lerin kullanımı daha kolaydır. Derleme sırasında ABI kararlılığı ve uyumsuz değişiklikler olursa derleme araları da kontrol edilir. Bu kontrol, bölümler arasında açıkça tanımlanmış arayüzler olarak işlev görür. Bu API'ler ayrıca Rust, Java ve C++ arasında
tutarlılık sağlayabilir.
Sistem özelliklerini API olarak tanımlama
Sistem özelliklerini, aşağıdaki şemaya göre Protobuf TextFormat 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 özellik grubunu açıklayan bir özellik mesajı içerir. Alanlarının anlamı aşağıdaki gibidir.
Alan | Anlamı |
---|---|
owner
|
Şu mülklerin sahibi olan bölüm olarak 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++'ta com::android::sysprop::BuildProperties ad alanı ve Java'da com.android.sysprop paketinde bulunan BuildProperties sınıfı olur.
|
prop
|
Tesis 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 oluşturur
Writeonce , ReadWrite : Alıcı ve setter API'leri oluşturur
Not: ro. ön ekine sahip mülkler ReadWrite erişimini kullanamaz.
|
scope
|
Internal : Yalnızca sahibi erişebilir.
Public : NDK modülleri dışında 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 ) Setterların false ve true yerine 0 ve 1 kullanmasını sağlayın.
|
legacy_prop_name
|
(isteğe bağlı, yalnızca Readonly mülkleri) Temel sistem özelliğinin eski adı. Alıcı çağrırken, alıcı API prop_name okumaya çalışır ve prop_name yoksa legacy_prop_name kullanır. Mevcut bir mülkü kullanımdan kaldırıp 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.
Tür | C++ | Java | Rust |
---|---|---|---|
Boole | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Tam sayı | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
Kullanıcı arayüzü | 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
|
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ğini 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 özelliği kitaplıklarını tanımlama
Artık Sysprop Açıklama dosyalarıyla sysprop_library
modül tanımlayabilirsiniz.
sysprop_library
; C++, Java ve Rust için bir API işlevi 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 kaynağa API listesi dosyaları 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
şeklindedir. <module_name>-current.txt
, mevcut kaynak kodlarının API imzalarını barındırır. <module_name>-latest.txt
ise en son dondurulmuş API imzalarını barındırır. Derleme sistemi, API dosyalarını derleme sırasında oluşturulan API dosyalarıyla karşılaştırarak API'lerin değiştirilip değiştirilmediğini kontrol eder. current.txt
, kaynak kodlarıyla eşleşmiyorsa hata mesajı ve current.txt
dosyasını güncelleme talimatları gönderir. Aşağıda örnek bir dizin ve dosya düzeni 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
ile bağlantı kurabilir. Derleme sistemi, istemcilerden oluşturulan C++, Java ve Rust kitaplıklarına bağlantı oluşturarak istemcilerin, 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ı küçük harfe dönüştürüldükten, .
ve -
yerine _
dönüştürülüp lib
eklenerek ve _rust
eklenerek oluşturulduğunu unutmayın.
Yukarıdaki örnekte, tanımlanan ö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);
}
…
}
…