Les propriétés système sont un moyen pratique
de partager des informations, généralement
à l'échelle du système. Chaque partition peut utiliser ses propres propriétés système
en interne. Un problème peut survenir lorsque les propriétés
sont accessibles via des partitions,
comme /vendor
, qui accède aux propriétés définies par /system
. Depuis Android 8.0,
certaines partitions, telles que /system
, peuvent être mises à niveau, tandis que /vendor
reste
ne sont pas modifiées. Comme les propriétés système ne sont qu'un dictionnaire global de chaînes
sans schéma, il est difficile de stabiliser les propriétés. La
La partition /system
pourrait modifier ou supprimer les propriétés que la /vendor
dont dépend la partition sans préavis.
À partir de la version Android 10, les propriétés système
accessibles entre les partitions sont schématisés en fichiers de description Sysprop.
Les API permettant d'accéder aux propriétés sont générées sous forme de fonctions concrètes pour C++ et Rust,
et les classes pour Java. Ces API sont plus pratiques, car il n'existe pas
des chaînes (comme ro.build.date
) sont nécessaires pour l'accès, et comme elles peuvent être
de manière statique. La stabilité de l'ABI est également vérifiée au moment de la compilation.
en cas de modifications incompatibles. Cette vérification agit comme défini explicitement
entre les partitions. Ces API peuvent également assurer la cohérence entre
Rust, Java et C++.
Définir les propriétés système en tant qu'API
définir les propriétés système en tant qu'API à l'aide de fichiers de description Sysprop (.sysprop
) ;
qui utilisent un TextFormat de protobuf, avec le schéma suivant:
// 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 fichier de description Sysprop contient un message de propriétés, qui décrit une d'un ensemble de propriétés. La signification de ses champs est la suivante :
Champ | Signification |
---|---|
owner
|
Définissez-la sur la partition qui possède les propriétés: Platform ,
Vendor ou Odm .
|
module
|
Permet de créer un espace de noms (C++) ou une classe finale statique (Java) dans lequel
générées par des API sont placées. Par exemple :
com.android.sysprop.BuildProperties
sera l'espace de noms com::android::sysprop::BuildProperties en C++,
et la classe BuildProperties du package
com.android.sysprop en Java.
|
prop
|
Liste des établissements. |
La signification des champs de message Property
est la suivante.
Champ | Signification |
---|---|
api_name
|
Nom de l'API générée. |
type
|
Type de cette propriété. |
access
|
Readonly : génère uniquement l'API getter.
Writeonce , ReadWrite : génère les API getter et setter.
Remarque: Les propriétés avec le préfixe ro. ne peuvent pas utiliser
Accès à ReadWrite
|
scope
|
Internal : seul le propriétaire peut y accéder.
Public : tout le monde peut y accéder, à l'exception des modules du NDK.
|
prop_name
|
Nom de la propriété système sous-jacente, par exemple
ro.build.date
|
enum_values
|
(Enum , EnumList uniquement) Une chaîne séparée par une barre(|)
constitué de valeurs d'énumération possibles. Exemple : value1|value2 .
|
integer_as_bool
|
(Boolean , BooleanList uniquement) Faire utiliser les setters
0 et 1 au lieu de false , et
true
|
legacy_prop_name
|
(facultatif, propriétés Readonly uniquement) Ancien nom du
propriété système sous-jacente. Lors de l'appel de la méthode "getter", l'API "getter" tente de lire
prop_name et utilise legacy_prop_name si
prop_name n'existe pas. Utiliser legacy_prop_name lorsque
d'abandonner une propriété existante et de la déplacer vers une nouvelle propriété.
|
Chaque type de propriété correspond aux types suivants en C++, Java et Rust.
Type | C++ | Java | Rust |
---|---|---|---|
Booléen | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Nombre entier | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
UInt | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Longue | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
ULong | std::optional<std::uint64_t>
|
Optional<Long>
|
u64
|
Double | std::optional<double>
|
Optional<Double>
|
f64
|
Chaîne | std::optional<std::string>
|
Optional<String>
|
String
|
Énumération | std::optional<{api_name}_values>
|
Optional<{api_name}_values>
|
{ApiName}Values
|
Liste T | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Voici un exemple de fichier de description Sysprop définissant trois propriétés:
# 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
}
Définir des bibliothèques de propriétés système
Vous pouvez maintenant définir des modules sysprop_library
avec des fichiers de description Sysprop.
sysprop_library
sert d'API pour C++, Java et Rust. Système de compilation
génère en interne un rust_library
, un java_library
et un cc_library
.
pour chaque instance de sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
Vous devez inclure les fichiers de listes d'API dans la source pour les vérifications d'API. Pour ce faire,
créer des fichiers API et un répertoire api
. Placez le répertoire api
dans le même
en tant que Android.bp
. Les noms de fichiers de l'API sont <module_name>-current.txt
.
<module_name>-latest.txt
<module_name>-current.txt
contient les signatures d'API.
des codes sources actuels, et <module_name>-latest.txt
contient la dernière version figée
signatures d'API. Le système de compilation vérifie si les API sont modifiées par
en comparant ces fichiers d'API aux fichiers d'API générés au moment de la compilation et en émettant
message d'erreur et instructions pour mettre à jour le fichier current.txt
si current.txt
ne correspond pas aux codes sources. Voici un exemple de répertoire et de fichier
organisation:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Les modules clients Rust, Java et C++ peuvent être associés à sysprop_library
pour utiliser
générées par des API. Le système de compilation crée des liens
à partir des clients vers des fichiers C++ générés,
les bibliothèques Java et Rust, permettant ainsi aux clients d'accéder aux API générées.
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"],
}
Notez que le nom de la bibliothèque Rust est généré en convertissant sysprop_library
.
nom en minuscules, en remplaçant .
et -
par _
, puis en faisant précéder lib
et
l'ajout de _rust
.
Dans l'exemple précédent, vous pouvez accéder aux propriétés définies comme suit.
Exemple de rouille:
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);
}
…
}
Exemple 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
);
}
…
}
…
Exemple 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);
}
…
}
…