Properti sistem menyediakan cara yang mudah untuk berbagi informasi, biasanya
konfigurasi, di seluruh sistem. Setiap partisi dapat menggunakan properti sistemnya sendiri
secara internal. Masalah dapat terjadi saat properti diakses di seluruh partisi,
seperti /vendor
mengakses properti yang ditentukan /system
. Mulai Android 8.0,
beberapa partisi, seperti /system
, dapat diupgrade, sedangkan /vendor
tidak
berubah. Karena properti sistem hanyalah kamus global dari pasangan nilai kunci string
tanpa skema, sulit untuk menstabilkan properti. Partisi
/system
dapat mengubah atau menghapus properti yang menjadi dependensi
partisi /vendor
tanpa pemberitahuan.
Mulai rilis Android 10, properti sistem
yang diakses di seluruh partisi dipetakan ke dalam file Deskripsi Sysprop, dan
API untuk mengakses properti dihasilkan sebagai fungsi konkret untuk C++ dan Rust,
serta class untuk Java. API ini lebih mudah digunakan karena tidak ada string
ajaib (seperti ro.build.date
) yang diperlukan untuk akses, dan karena dapat
dibuat secara statis. Stabilitas ABI juga diperiksa pada waktu build, dan build
akan berhenti berfungsi jika terjadi perubahan yang tidak kompatibel. Pemeriksaan ini berfungsi sebagai antarmuka yang ditentukan secara eksplisit
di antara partisi. API ini juga dapat memberikan konsistensi antara
Rust, Java, dan C++.
Menentukan properti sistem sebagai API
Tentukan properti sistem sebagai API dengan file Deskripsi Sysprop (.sysprop
),
yang menggunakan TextFormat dari protobuf, dengan skema berikut:
// 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;
}
Satu file Deskripsi Sysprop berisi satu pesan properti, yang mendeskripsikan serangkaian properti. Arti kolomnya adalah sebagai berikut.
Kolom | Arti |
---|---|
owner
|
Tetapkan ke partisi yang memiliki properti: Platform ,
Vendor , atau Odm .
|
module
|
Digunakan untuk membuat namespace (C++) atau class final statis (Java) tempat
API yang dihasilkan ditempatkan. Misalnya,
com.android.sysprop.BuildProperties
akan menjadi namespace com::android::sysprop::BuildProperties di C++,
dan class BuildProperties dalam paket di
com.android.sysprop di Java.
|
prop
|
Daftar properti. |
Arti kolom pesan Property
adalah sebagai berikut.
Kolom | Arti |
---|---|
api_name
|
Nama API yang dihasilkan. |
type
|
Jenis properti ini. |
access
|
Readonly : Hanya menghasilkan API pengambil
Writeonce , ReadWrite : Menghasilkan API pengambil dan penyetel
Catatan: Properti dengan awalan ro. mungkin tidak menggunakan
akses ReadWrite .
|
scope
|
Internal : Hanya pemilik yang dapat mengakses.
Public : Semua orang dapat mengakses, kecuali untuk modul NDK.
|
prop_name
|
Nama properti sistem yang mendasarinya, misalnya
ro.build.date .
|
enum_values
|
(Khusus Enum , EnumList ) String yang dipisahkan garis miring(|)
yang terdiri dari kemungkinan nilai enum. Misalnya, value1|value2 .
|
integer_as_bool
|
(Khusus Boolean , BooleanList ) Buat penyetel menggunakan
0 dan 1 , bukan false dan
true .
|
legacy_prop_name
|
(opsional, khusus properti Readonly ) Nama lama properti sistem yang mendasarinya. Saat memanggil pengambil, API pengambil mencoba membaca
prop_name dan menggunakan legacy_prop_name jika
prop_name tidak ada. Gunakan legacy_prop_name saat menghentikan penggunaan properti yang ada dan beralih ke properti baru.
|
Setiap jenis properti dipetakan ke jenis berikut di C++, Java, dan Rust.
Jenis | C++ | Java | Rust |
---|---|---|---|
Boolean | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Bilangan Bulat | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
UInt | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Panjang | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
ULong | std::optional<std::uint64_t>
|
Optional<Long>
|
u64
|
Ganda | std::optional<double>
|
Optional<Double>
|
f64
|
String | std::optional<std::string>
|
Optional<String>
|
String
|
Enum | std::optional<{api_name}_values>
|
Optional<{api_name}_values>
|
{ApiName}Values
|
Daftar T | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Berikut adalah contoh file Deskripsi Sysprop yang mendefinisikan tiga properti:
# 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
}
Menentukan library properti sistem
Sekarang Anda dapat menentukan modul sysprop_library
dengan file Deskripsi Sysprop.
sysprop_library
berfungsi sebagai API untuk C++, Java, dan Rust. Sistem build
secara internal menghasilkan satu rust_library
, satu java_library
, dan satu cc_library
untuk setiap instance sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
Anda harus menyertakan file daftar API di sumber untuk pemeriksaan API. Untuk melakukannya,
buat file API dan direktori api
. Tempatkan direktori api
di direktori
yang sama dengan Android.bp
. Nama file API adalah <module_name>-current.txt
,
<module_name>-latest.txt
. <module_name>-current.txt
menyimpan tanda tangan API
dari kode sumber saat ini, dan <module_name>-latest.txt
menyimpan tanda tangan API
terbaru yang dibekukan. Sistem build akan memeriksa apakah API diubah dengan
membandingkan file API ini dengan file API yang dihasilkan pada waktu build, serta memunculkan
pesan error dan petunjuk untuk mengupdate file current.txt
jika current.txt
tidak cocok dengan kode sumber. Berikut adalah contoh direktori dan pengaturan file:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Modul klien Rust, Java, dan C++ dapat ditautkan ke sysprop_library
untuk menggunakan
API yang dihasilkan. Sistem build membuat link dari klien ke library C++,
Java, dan Rust yang dihasilkan, sehingga memberi klien akses ke API yang dihasilkan.
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"],
}
Perhatikan bahwa nama library Rust dihasilkan dengan mengonversi nama sysprop_library
menjadi huruf kecil, mengganti .
dan -
dengan _
, lalu menambahkan lib
dan
menambahkan _rust
.
Pada contoh sebelumnya, Anda dapat mengakses properti yang ditentukan sebagai berikut.
Contoh karat:
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);
}
…
}
Contoh Java:
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
);
}
…
}
…
Contoh 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);
}
…
}
…