Properti sistem menyediakan cara mudah
untuk berbagi informasi, biasanya
konfigurasi standar, di seluruh sistem. Setiap partisi dapat menggunakan properti sistemnya sendiri
secara internal. Masalah dapat terjadi ketika
properti diakses di seluruh partisi,
seperti /vendor
mengakses properti yang ditentukan /system
. Sejak Android 8.0,
beberapa partisi, seperti /system
, dapat diupgrade, sedangkan /vendor
dibiarkan
tidak berubah. Karena properti sistem hanyalah
kamus global dari {i>string<i}
pasangan nilai kunci tanpa skema, properti akan sulit distabilkan. Tujuan
Partisi /system
dapat mengubah atau menghapus properti yang /vendor
partisi bergantung pada tanpa pemberitahuan apa pun.
Dimulai dengan rilis Android 10, properti sistem
yang diakses di seluruh partisi diskemakan
ke dalam file {i>Sysprop Description<i}, dan
API untuk mengakses properti dibuat sebagai fungsi konkret untuk C++ dan Rust,
dan class untuk Java. API ini lebih nyaman digunakan karena tidak perlu
string (seperti ro.build.date
) diperlukan untuk akses, dan karena string tersebut dapat
diketik secara statis. Stabilitas ABI juga diperiksa pada waktu build, dan
rusak jika terjadi perubahan yang tidak kompatibel. Pemeriksaan ini berfungsi sebagaimana yang
didefinisikan secara eksplisit
antarmuka antar partisi. API ini juga dapat memberikan konsistensi antara
Rust, Java, dan C++.
Menentukan properti sistem sebagai API
Menentukan 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;
}
Satu file Deskripsi Sysprop berisi satu pesan properti, yang menjelaskan sekumpulan 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 akan 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 digunakan
Akses ReadWrite .
|
scope
|
Internal : Hanya pemilik yang dapat mengakses.
Public : Semua orang dapat mengakses, kecuali modul NDK.
|
prop_name
|
Nama properti sistem yang mendasarinya, misalnya
ro.build.date .
|
enum_values
|
(hanya Enum , EnumList ) String yang dipisahkan batang(|)
yang terdiri dari kemungkinan nilai enum. Misalnya, value1|value2 .
|
integer_as_bool
|
(Boolean , BooleanList saja) Menggunakan penyetel
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 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
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:
membuat file API dan direktori api
. Tempatkan direktori api
di
sebagai 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 kode beku terakhir
Tanda tangan API. Sistem build akan memeriksa apakah API diubah oleh
membandingkan file API ini dengan file API yang dihasilkan pada waktu build dan
pesan error dan petunjuk untuk memperbarui file current.txt
jika current.txt
tidak cocok dengan kode sumber. Berikut adalah contoh direktori dan file
organisasi:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Modul klien Rust, Java, dan C++ dapat ditautkan ke sysprop_library
untuk digunakan
API yang dihasilkan. Sistem build membuat link dari klien ke C++ yang dihasilkan,
Library Java dan Rust, 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"],
}
Perlu diperhatikan bahwa nama library Rust dibuat dengan mengonversi sysprop_library
nama 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);
}
…
}
…