Le proprietà di sistema offrono un modo conveniente per condividere le informazioni,
a livello di sistema. Ogni partizione può utilizzare le proprie proprietà di sistema
internamente. Può verificarsi un problema quando si accede alle proprietà tra le partizioni
come /vendor
che accede alle proprietà definite da /system
. A partire da Android 8.0,
è possibile eseguire l'upgrade di alcune partizioni, come /system
, mentre /vendor
rimane
senza modifiche. Poiché le proprietà di sistema sono solo un dizionario globale di stringhe
coppie chiave-valore senza schema, è difficile stabilizzare le proprietà. La
La partizione /system
potrebbe modificare o rimuovere le proprietà /vendor
dipende senza preavviso.
A partire dalla release Android 10, le proprietà di sistema
alle partizioni è possibile creare uno schematizzato in file di descrizione Sysprop,
Le API per accedere alle proprietà sono generate come funzioni concrete per C++ e Rust,
e classi per Java. Queste API sono più facili da usare perché non servono
(ad esempio ro.build.date
) sono necessarie per l'accesso e perché possono essere
digitate in modo statico. La stabilità dell'ABI viene verificata anche al momento della build
si interrompono se si verificano modifiche incompatibili. Questo controllo agisce come definito in modo esplicito
le interfacce tra le partizioni. Queste API possono inoltre fornire coerenza
Rust, Java e C++.
Definisci le proprietà di sistema come API
Definisci le proprietà di sistema come API con i file di descrizione Sysprop (.sysprop
),
che utilizzano TextFormat di protobuf, con il seguente schema:
// 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;
}
Un file di descrizione Sysprop contiene un messaggio di proprietà, che descrive un insieme di proprietà. Il significato dei relativi campi è il seguente.
Campo | Significato |
---|---|
owner
|
Imposta la partizione proprietaria delle proprietà: Platform ,
Vendor o Odm .
|
module
|
Utilizzato per creare uno spazio dei nomi (C++) o una classe finale statica (Java) in cui
le API generate. Ad esempio:
com.android.sysprop.BuildProperties
sarà lo spazio dei nomi com::android::sysprop::BuildProperties in C++,
e la classe BuildProperties nel pacchetto
com.android.sysprop in Java.
|
prop
|
Elenco di proprietà. |
I significati dei campi del messaggio Property
sono i seguenti.
Campo | Significato |
---|---|
api_name
|
Il nome dell'API generata. |
type
|
Il tipo di questa proprietà. |
access
|
Readonly : genera solo l'API getter
Writeonce , ReadWrite : genera API getter e setter
Nota: le proprietà con il prefisso ro. non possono utilizzare
Accesso a ReadWrite .
|
scope
|
Internal : solo il proprietario può accedere.
Public : tutti possono accedere, ad eccezione dei moduli NDK.
|
prop_name
|
Il nome della proprietà di sistema sottostante, ad esempio
ro.build.date .
|
enum_values
|
(Solo Enum , EnumList ) Una stringa separata da barre(|)
che è composto da possibili valori enum. Ad esempio, value1|value2 .
|
integer_as_bool
|
(Solo Boolean , BooleanList ) Consenti ai setter di utilizzare
0 e 1 anziché false e
true ,
|
legacy_prop_name
|
(facoltativo, solo proprietà Readonly ) Il nome precedente della proprietà
proprietà di sistema sottostante. Quando chiami il getter, l'API getter prova a leggere
prop_name e utilizza legacy_prop_name se
prop_name non esiste. Usa legacy_prop_name quando
il ritiro di una proprietà esistente
e il suo trasferimento a una nuova.
|
Ogni tipo di proprietà è mappato ai seguenti tipi in C++, Java e Rust.
Tipo | C++ | Java | Rust |
---|---|---|---|
Booleano | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Numero intero | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
UInt | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Lungo | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
ULungo | std::optional<std::uint64_t>
|
Optional<Long>
|
u64
|
Doppio | std::optional<double>
|
Optional<Double>
|
f64
|
Stringa | std::optional<std::string>
|
Optional<String>
|
String
|
Enum | std::optional<{api_name}_values>
|
Optional<{api_name}_values>
|
{ApiName}Values
|
Elenco T | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Ecco un esempio di file di descrizione Sysprop che definisce tre proprietà:
# 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
}
Definisci le librerie delle proprietà di sistema
Ora puoi definire moduli sysprop_library
con i file di descrizione Sysprop.
sysprop_library
funge da API per C++, Java e Rust. Il sistema di compilazione
genera internamente uno rust_library
, uno java_library
e un cc_library
per ogni istanza di sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
Per i controlli delle API, devi includere i file degli elenchi delle API nell'origine. Per farlo,
creare file API e una directory api
. Inserisci la directory api
nella stessa
come Android.bp
. I nomi file dell'API sono <module_name>-current.txt
,
<module_name>-latest.txt
. <module_name>-current.txt
contiene le firme dell'API
di codici sorgente correnti e <module_name>-latest.txt
blocca l'ultimo
Firme delle API. Il sistema di compilazione controlla se le API vengono modificate
confrontando questi file API con i file API generati al momento della build ed emette un codice
messaggio di errore e istruzioni per aggiornare il file current.txt
se current.txt
non corrisponde ai codici sorgente. Ecco un esempio di directory e file
organizzazione:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
I moduli client Rust, Java e C++ possono collegarsi a sysprop_library
per l'utilizzo
le API generate. Il sistema di compilazione crea collegamenti dai client al C++ generato,
librerie Java e Rust, che consentono ai client di accedere alle API generate.
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"],
}
Tieni presente che il nome della libreria Rust viene generato convertendo sysprop_library
nome in minuscolo, sostituendo .
e -
con _
, quindi anteponendo lib
e
aggiungendo _rust
.
Nell'esempio precedente, potevi accedere a proprietà definite nel seguente modo.
Esempio di ruggine:
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);
}
…
}
Esempio di 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
);
}
…
}
…
Esempio 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);
}
…
}
…