Properti sistem (sysprops) menyediakan cara mudah untuk membagikan 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 yang mengakses properti yang ditentukan /system. Sejak
Android 8.0, beberapa partisi, seperti /system, dapat diupgrade,
sementara /vendor tidak berubah. Karena properti sistem hanyalah kamus global
pasangan nilai kunci string tanpa skema, properti sulit distabilkan. Partisi /system dapat mengubah atau menghapus properti yang bergantung pada partisi
/system tanpa pemberitahuan apa pun./vendor
Di Android 10 dan yang lebih tinggi, properti sistem yang diakses di seluruh partisi diskemakan 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 memerlukan string ajaib (seperti ro.build.date) untuk akses, dan karena dapat diketik secara statis. Stabilitas ABI juga diperiksa pada waktu build, dan build akan gagal jika terjadi perubahan yang tidak kompatibel. Pemeriksaan ini berfungsi sebagai antarmuka yang ditentukan secara eksplisit 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 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;
}
File deskripsi sysprop berisi 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
adalah 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 dibuat. |
type
|
Jenis properti ini. |
access
|
Readonly: Hanya membuat API getter
Writeonce, ReadWrite: Membuat API getter dan setter
|
scope
|
Internal: Hanya pemilik yang dapat mengakses.
Public: Semua orang dapat mengakses, kecuali modul NDK.
|
prop_name
|
Nama properti sistem pokok, misalnya
ro.build.date.
|
enum_values
|
(Enum, EnumList saja) String yang dipisahkan dengan batang(|)
yang terdiri dari kemungkinan nilai enum. Misalnya, value1|value2.
|
integer_as_bool
|
(Boolean, BooleanList saja) Buat setter menggunakan
0 dan 1, bukan false dan
true.
|
legacy_prop_name
|
(opsional, hanya properti Readonly) Nama lama
properti sistem yang mendasarinya. Saat memanggil getter, API getter 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++ (dapat bernilai null) | Java (dapat bernilai null) | Rust (opsional atau nullable) |
|---|---|---|---|
| Boolean | std::optional<bool> |
Optional<Boolean> |
Option<bool> |
| Bilangan Bulat | std::optional<std::int32_t> |
Optional<Integer> |
Option<i32> |
| UInt | std::optional<std::uint32_t> |
Optional<Integer> |
Option<u32> |
| Long | std::optional<std::int64_t> |
Optional<Long> |
Option<i64> |
| ULong | std::optional<std::uint64_t> |
Optional<Long> |
Option<u64> |
| Double | std::optional<double> |
Optional<Double> |
Option<f64> |
| String | std::optional<std::string> |
Optional<String> |
Option<String> |
| Enum | std::optional<{api\_name}\_values> |
Optional<{api\_name}\_values> |
Option<{ApiName}Values> |
| T List | std::vector<std::optional<T>> |
List<T> |
Vec<T> |
Berikut adalah contoh file Deskripsi Sysprop yang menentukan 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
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 dalam 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 dan
<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 memeriksa apakah API diubah dengan
membandingkan file API ini dengan file API yang dihasilkan pada waktu build dan menampilkan
pesan error dan petunjuk untuk memperbarui file current.txt jika current.txt
tidak cocok dengan kode sumber. Berikut contoh organisasi file dan direktori:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Modul klien Rust, Java, dan C++ dapat ditautkan dengan sysprop_library untuk menggunakan
API yang dihasilkan. Sistem build membuat link dari klien ke library C++,
Java, dan Rust yang dihasilkan, sehingga memberikan akses klien ke API yang dihasilkan.
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"],
}
Dalam contoh sebelumnya, Anda dapat mengakses properti yang ditentukan sebagai berikut.
Contoh Rust:
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);
}
…
}
…