Systemeigenschaften bieten eine bequeme Möglichkeit, Informationen
systemweit implementiert. Jede Partition kann ihre eigenen Systemeigenschaften verwenden
intern. Probleme können auftreten, wenn über Partitionen hinweg auf Properties zugegriffen wird, z. B. wenn /vendor
auf von /system
definierte Properties zugreift. Seit Android 8.0
Einige Partitionen, z. B. /system
, können aktualisiert werden, während /vendor
übrig bleibt
unverändert lassen. Da Systemattribute nur ein globales Wörterbuch von Strings sind,
Schlüssel/Wert-Paare ohne Schema sind, lassen sich Eigenschaften stabilisieren. Die
Die Partition /system
könnte Eigenschaften ändern oder entfernen, die von der /vendor
von der Partition abhängig ist.
Ab Android 10 werden Systemeigenschaften
Der partitionsübergreifende Zugriff wird in Sysprop-Beschreibungsdateien schematisiert.
APIs für den Zugriff auf Attribute
werden als konkrete Funktionen für C++ und Rust generiert.
und Klassen für Java. Diese APIs sind praktischer, da es keine magischen
wie ro.build.date
, sind für den Zugriff erforderlich und können
statisch eingegeben wurde. Die ABI-Stabilität wird
auch zum Zeitpunkt der Erstellung überprüft und der Build
bei inkompatiblen Änderungen ab. Diese Prüfung dient als explizit definierte Schnittstelle zwischen Partitionen. Diese APIs können auch für Konsistenz zwischen
Rust, Java und C++.
Systemeigenschaften als APIs definieren
Definieren Sie Systemeigenschaften als APIs mit Sysprop-Beschreibungsdateien (.sysprop
).
die ein TextFormat von protobuf mit dem folgenden Schema verwenden:
// 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;
}
Eine Sysprop-Beschreibungsdatei enthält eine Eigenschaftennachricht, die ein Gruppe von Eigenschaften. Die Felder haben folgende Bedeutung.
Feld | Bedeutung |
---|---|
owner
|
Legen Sie als Wert die Partition fest, zu der die Attribute gehören: Platform ,
Vendor oder Odm .
|
module
|
Wird zum Erstellen eines Namespace (C++) oder einer statischen finalen Klasse (Java) verwendet, in dem
generierten APIs platziert werden. Beispiel:
com.android.sysprop.BuildProperties
wird der Namespace com::android::sysprop::BuildProperties in C++ sein,
und die Klasse BuildProperties im Paket in
com.android.sysprop in Java.
|
prop
|
Liste der Properties. |
Die Property
-Nachrichtenfelder haben folgende Bedeutung:
Feld | Bedeutung |
---|---|
api_name
|
Der Name der generierten API. |
type
|
Der Typ dieser Property. |
access
|
Readonly : Generiert nur die Getter API
Writeonce , ReadWrite : Generiert Getter- und Setter-APIs
Hinweis: In Properties mit dem Präfix ro. dürfen keine
ReadWrite -Zugriff.
|
scope
|
Internal : Nur der Eigentümer hat Zugriff.
Public : Jeder hat Zugriff, mit Ausnahme von NDK-Modulen.
|
prop_name
|
Der Name der zugrunde liegenden Systemeigenschaft, z. B.
ro.build.date
|
enum_values
|
(nur Enum , EnumList ) Ein durch Striche(|) getrennter String
die aus möglichen enum-Werten besteht. Beispiel: value1|value2 .
|
integer_as_bool
|
(Nur Boolean , BooleanList ) Setter verwenden
0 und 1 anstelle von false und
true
|
legacy_prop_name
|
(optional, nur Readonly -Attribute) Der alte Name des
zugrunde liegende Systemeigenschaft. Beim Aufrufen des Getters versucht die Getter API, Daten zu lesen,
prop_name und verwendet legacy_prop_name , wenn
prop_name ist nicht vorhanden. legacy_prop_name verwenden, wenn
Sie verwerfen eine bestehende Property und verschieben sie in eine neue.
|
Jeder Property-Typ wird den folgenden Typen in C++, Java und Rust zugeordnet.
Typ | C++ | Java | Rust |
---|---|---|---|
Boolesch | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Ganzzahl | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
UInt | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Lang | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
Lang | std::optional<std::uint64_t>
|
Optional<Long>
|
u64
|
Double | 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
|
T-Liste | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Hier ist ein Beispiel für eine Sysprop-Beschreibungsdatei, die drei Eigenschaften definiert:
# 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
}
Bibliotheken für Systemeigenschaften definieren
Sie können jetzt sysprop_library
-Module mit Sysprop-Beschreibungsdateien definieren.
sysprop_library
dient als API für C++, Java und Rust. Das Build-System
Generiert intern einen rust_library
, einen java_library
und einen cc_library
für jede Instanz von sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
Sie müssen Dateien mit API-Listen in die Quelle für API-Prüfungen aufnehmen. Gehen Sie dazu wie folgt vor:
API-Dateien und ein api
-Verzeichnis erstellen Legen Sie das Verzeichnis api
als Android.bp
. Die API-Dateinamen sind <module_name>-current.txt
,
<module_name>-latest.txt
. <module_name>-current.txt
enthält die API-Signaturen.
der aktuellen Quellcodes und <module_name>-latest.txt
enthält die letzten eingefrorenen Codes
API-Signaturen. Das Build-System prüft, ob die APIs durch
beim Vergleichen dieser API-Dateien mit generierten API-Dateien zur Build-Zeit und gibt einen
Fehlermeldung und Anleitung zum Aktualisieren der Datei current.txt
, wenn current.txt
nicht mit den Quellcodes übereinstimmt. Hier ist ein Beispiel für ein Verzeichnis und eine Datei
Organisation:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Rust-, Java- und C++-Clientmodule können zur Verwendung mit sysprop_library
verknüpft werden
generierten APIs. Das Build-System erstellt Links von Clients zu generierter C++-,
Java- und Rust-Bibliotheken, wodurch Clients Zugriff auf generierte APIs erhalten.
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"],
}
Der Name der Rust-Bibliothek wird durch Umwandeln des sysprop_library
-Objekts generiert.
Namen in Kleinbuchstaben, wobei .
und -
durch _
ersetzt und dann lib
und
_rust
wird angehängt.
Im vorherigen Beispiel könnten Sie folgendermaßen auf definierte Properties zugreifen:
Rust-Beispiel:
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-Beispiel:
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++-Beispiel:
#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);
}
…
}
…