Las propiedades del sistema proporcionan una forma conveniente de compartir información, generalmente
de configuración de seguridad en todo el sistema. Cada partición puede usar sus propias propiedades del sistema
internamente. Un problema puede ocurrir cuando se accede a las propiedades desde varias particiones,
como cuando /vendor
accede a propiedades definidas por /system
. A partir de Android 8.0,
algunas particiones, como /system
, se pueden actualizar, mientras que /vendor
queda.
sin cambios. Porque las propiedades del sistema son solo un diccionario global de cadenas.
pares clave-valor sin esquema, es difícil estabilizar propiedades. El
La partición /system
podría cambiar o quitar las propiedades que /vendor
de la que depende la partición sin aviso.
A partir de la versión de Android 10, las propiedades del sistema
se esquematizan en archivos de descripción Sysprop
Las APIs para acceder a propiedades se generan como funciones concretas para C++ y Rust.
y clases para Java. Estas APIs son más convenientes de usar porque no existen métodos
cadenas (como ro.build.date
) son necesarias para el acceso y, ya que se pueden
se escribe estáticamente. Durante el tiempo de compilación, también se verifica la estabilidad de la ABI, y la compilación
se rompe si se producen cambios incompatibles. Esta verificación actúa según lo definido de manera explícita
las interfaces entre particiones. Estas APIs también pueden brindar coherencia
Rust, Java y C++.
Cómo definir las propiedades del sistema como APIs
Define propiedades del sistema como APIs con archivos de descripción de Sysprop (.sysprop
)
que usan un TextFormat de protobuf, con el siguiente esquema:
// 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 archivo de descripción de Sysprop contiene un mensaje de propiedades, que describe un conjunto de propiedades. El significado de sus campos es el siguiente.
Campo | Significado |
---|---|
owner
|
Configúralo en la partición propietaria de las propiedades: Platform ,
Vendor o Odm .
|
module
|
Se usa para crear un espacio de nombres (C++) o una clase final estática (Java) en la que
las APIs generadas. Por ejemplo:
com.android.sysprop.BuildProperties
será el espacio de nombres com::android::sysprop::BuildProperties en C++,
y la clase BuildProperties en el paquete de
com.android.sysprop en Java.
|
prop
|
Lista de propiedades. |
Los significados de los campos del mensaje Property
son los siguientes.
Campo | Significado |
---|---|
api_name
|
El nombre de la API generada. |
type
|
Es el tipo de esta propiedad. |
access
|
Readonly : Solo genera la API del método get.
Writeonce , ReadWrite : Genera APIs de métodos get y set
Nota: Las propiedades con el prefijo ro. no pueden usar
ReadWrite .
|
scope
|
Internal : Solo el propietario tiene acceso.
Public : Todos pueden acceder, excepto los módulos del NDK.
|
prop_name
|
El nombre de la propiedad del sistema subyacente, por ejemplo
ro.build.date
|
enum_values
|
Una cadena separada por barras (|) (solo Enum , EnumList )
que consiste en posibles valores de enumeración. Por ejemplo, value1|value2 .
|
integer_as_bool
|
(Solo Boolean , BooleanList ) Haz que usen métodos set
0 y 1 en lugar de false y
true
|
legacy_prop_name
|
El nombre heredado del nombre (opcional, solo para propiedades Readonly )
propiedad del sistema subyacente. Cuando se llama al método get, su API intenta leer
prop_name y usa legacy_prop_name si
prop_name no existe. Usa legacy_prop_name cuando
dar de baja una propiedad existente y migrar a una nueva.
|
Cada tipo de propiedad se asigna a los siguientes tipos en C++, Java y Rust.
Tipo | C++ | Java | Rust |
---|---|---|---|
Booleano | std::optional<bool>
|
Optional<Boolean>
|
bool
|
Entero | std::optional<std::int32_t>
|
Optional<Integer>
|
i32
|
IU | std::optional<std::uint32_t>
|
Optional<Integer>
|
u32
|
Largo | std::optional<std::int64_t>
|
Optional<Long>
|
i64
|
ULong | 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
|
Lista T | std::vector<std::optional<T>>
|
List<T>
|
Vec<T>
|
Este es un ejemplo de un archivo de descripción de Sysprop que define tres propiedades:
# 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
}
Cómo definir bibliotecas de propiedades del sistema
Ahora puedes definir módulos sysprop_library
con archivos de descripción Sysprop.
sysprop_library
funciona como API para C++, Java y Rust. Sistema de compilación
genera internamente un rust_library
, un java_library
y un cc_library
.
para cada instancia de sysprop_library
.
// File: Android.bp
sysprop_library {
name: "PlatformProperties",
srcs: ["android/sysprop/PlatformProperties.sysprop"],
property_owner: "Platform",
vendor_available: true,
}
Debes incluir los archivos de listas de la API en la fuente para las verificaciones de API. Para ello,
Crea archivos de API y un directorio api
. Coloca el directorio api
en el mismo
como Android.bp
. Los nombres de archivo de la API son <module_name>-current.txt
,
<module_name>-latest.txt
<module_name>-current.txt
contiene las firmas de la API
de los códigos fuente actuales y <module_name>-latest.txt
contiene el último congelado
Firmas de APIs. El sistema de compilación verifica si las APIs cambian
compara estos archivos de API con archivos de API generados al momento de la compilación y emite un
y las instrucciones para actualizar el archivo current.txt
si es current.txt
no coincide con los códigos fuente. Este es un ejemplo de directorio y archivo
organización:
├── api
│ ├── PlatformProperties-current.txt
│ └── PlatformProperties-latest.txt
└── Android.bp
Los módulos cliente de Rust, Java y C++ se pueden vincular con sysprop_library
para usarlos.
las APIs generadas. El sistema de compilación crea vínculos de clientes a C++ generado,
las bibliotecas Java y Rust, lo que otorga a los clientes acceso a las APIs generadas.
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"],
}
Ten en cuenta que el nombre de la biblioteca de Rust se genera convirtiendo sysprop_library
a minúsculas, reemplazando .
y -
por _
y, luego, anteponiendo lib
y
anexando _rust
.
En el ejemplo anterior, podrías acceder a las propiedades definidas de la siguiente manera.
Ejemplo de 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);
}
…
}
Ejemplo de 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
);
}
…
}
…
Ejemplo de 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);
}
…
}
…