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. Mülklere bölümler arasında erişildiğinde (ör. /vendor
tarafından tanımlanan mülklere /system
tarafından erişilmesi) 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, şeması olmayan dize anahtar/değer çiftlerinin bulunduğu genel bir sözlük olduğundan mülkleri 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 Description dosyalarında şematize edilir ve özelliklere erişmek için API'ler C++ ve Rust için somut işlevler, Java için sınıflar olarak oluşturulur. Bu API'lerin kullanımı, erişim için sihirli dizelere (ro.build.date
gibi) ihtiyaç duyulmaması ve statik olarak yazılabilmeleri nedeniyle daha kolaydır. ABI kararlılığı derleme sırasında da kontrol edilir ve uyumlu olmayan değişiklikler olursa derleme işlemi kesintiye uğrar. Bu kontrol, bölümler arasında açıkça tanımlanmış arayüzler gibi çalışı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 şemayı kullanan protobuf TextFormat'ı kullanan Sysprop Description dosyalarıyla (.sysprop
) 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 Description dosyası, bir dizi özelliği açıklayan bir properties mesajı içerir. Alanlarının anlamları aşağıdaki gibidir.
Alan | Anlamı |
---|---|
owner
|
Mülklerin sahibi 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++'ta com::android::sysprop::BuildProperties ad alanı,
Java'da ise com.android.sysprop paketindeki BuildProperties sınıfı olur.
|
prop
|
Tesis listesi. |
Property
mesaj alanlarının anlamları aşağıda verilmiştir.
Alan | Anlamı |
---|---|
api_name
|
Oluşturulan API'nin adı. |
type
|
Bu mülkün türü. |
access
|
Readonly : Yalnızca alıcı API'si oluşturur
Writeonce , ReadWrite : Alıcı ve ayarlayıcı API'leri oluşturur
Not: ro. ön ekiyle başlayan mülkler ReadWrite erişimini kullanamaz.
|
scope
|
Internal : Yalnızca sahip erişebilir.
Public : NDK modülleri hariç herkes erişebilir.
|
prop_name
|
Temel sistem mülkünün adı (ör. ro.build.date ).
|
enum_values
|
(yalnızca Enum , EnumList ) Olası enum değerlerinden oluşan, dikey çizgiyle 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 mülkleri) Temel sistem mülkünün eski adı. Geter API'si, getter'ı çağırırken prop_name değerini okumaya çalışır ve prop_name yoksa legacy_prop_name değerini kullanır. Mevcut bir mülkün desteği sonlandırılırken ve yeni bir mülke taşınırken legacy_prop_name değerini kullanın.
|
Her mülk 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 Listesi | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Aşağıda, üç özelliği tanımlayan bir Sysprop Description 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 Açıklama dosyalarıyla sysprop_library
modül tanımlayabilirsiniz.
sysprop_library
, C++, Java ve Rust için 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 API listeleri dosyalarını kaynağa eklemeniz gerekir. Bunu yapmak için API dosyaları ve bir api
dizini oluşturun. api
dizinini Android.bp
ile aynı dizine koyun. 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ı, <module_name>-latest.txt
ise en son dondurulmuş API imzalarını içerir. 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 kodlarla eşleşmiyorsa hata mesajı ve current.txt
dosyasını güncelleme talimatları gönderir. Aşağıda bir dizin ve dosya düzenleme örneği 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ının küçük harfe dönüştürülmesi, .
ve -
'nin _
ile değiştirilmesi ve ardından lib
'nin başına _rust
eklenmesiyle oluşturulduğunu unutmayın.
Yukarıdaki örnekte, tanımlanan özelliklere aşağıdaki gibi erişebilirsiniz.
Pas rengi ö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);
}
…
}
…