Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Implementación de propiedades del sistema como API

Las propiedades del sistema proporcionan una forma conveniente de compartir información, generalmente configuraciones, en todo el sistema. Cada partición puede utilizar sus propias propiedades del sistema internamente. Puede ocurrir un problema cuando se accede a las propiedades a través de particiones, como /vendor accediendo /system propiedades definidas por el /system . Desde Android 8.0, algunas particiones, como /system , se pueden actualizar, mientras que /vendor se modifica. Debido a que las propiedades del sistema son solo un diccionario global de pares clave / valor de cadena sin esquema, es difícil estabilizar las propiedades. La partición /system podría cambiar o eliminar propiedades de las que depende la partición /vendor sin previo aviso.

A partir de la versión de Android 10, las propiedades del sistema a las que se accede a través de las particiones se esquematizan en archivos de descripción de Sysprop, y las API para acceder a las propiedades se generan como funciones concretas para C ++ y clases para Java. Estas API son más convenientes de usar porque no se necesitan cadenas mágicas (como ro.build.date ) para acceder y porque se pueden escribir estáticamente. La estabilidad de ABI también se comprueba en el momento de la compilación, y la compilación se interrumpe si se producen cambios incompatibles. Esta verificación actúa como interfaces definidas explícitamente entre particiones. Estas API también pueden proporcionar coherencia entre Java y C ++.

Definición de propiedades del sistema como API

Defina las propiedades del sistema como API con archivos de descripción de Sysprop ( .sysprop ), que utilizan 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 Establezca la partición que posee las propiedades: Platform , Vendor u Odm .
module Se utiliza para crear un espacio de nombres (C ++) o una clase final estática (Java) en la que se colocan las API 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 en 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 El tipo de esta propiedad.
access Readonly : genera solo la API de captador

Writeonce , ReadWrite : genera API getter y setter

Nota: Propiedades con el prefijo ro. no puede utilizar el acceso de ReadWrite y ReadWrite .

scope Internal : solo el propietario puede acceder.

Public : todos pueden acceder, excepto los módulos NDK.

prop_name El nombre de la propiedad del sistema subyacente, por ejemplo, ro.build.date .
enum_values ( Enum , EnumList solamente) Una cadena separada por barras (|) que consta de posibles valores de enumeración. Por ejemplo, value1|value2 .
integer_as_bool ( BooleanList Boolean , BooleanList ) Haga que los establecedores usen 0 y 1 lugar de false y verdadero.
legacy_prop_name (opcional, Readonly propiedades de solo Readonly ) El nombre heredado de la propiedad del sistema subyacente. Al llamar a getter, la API de getter intenta leer prop_name y usa legacy_prop_name si prop_name no existe. Use legacy_prop_name cuando legacy_prop_name una propiedad existente y se legacy_prop_name a una nueva propiedad.

Cada tipo de propiedad se asigna a los siguientes tipos en C ++ y Java.

Tipo C ++ Java
Booleano std::optional<bool> Optional<Boolean>
Entero std::optional<std::int32_t> Optional<Integer>
UInt std::optional<std::uint32_t> Optional<Integer>
Largo std::optional<std::int64_t> Optional<Long>
ULong std::optional<std::uint64_t> Optional<Long>
Doble std::optional<double> Optional<Double>
Cuerda std::optional<std::string> Optional<String>
Enum std::optional<{api_name}_values> Optional<{api_name}_values>
Lista T std::vector<std::optional<T>> List<T>

A continuación, se muestra 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
}

Definición de bibliotecas de propiedades del sistema

Ahora puede definir sysprop_library módulos con Sysprop archivos de descripción. sysprop_library sirve como API tanto para C ++ como para Java. El sistema de compilación genera internamente una java_library y una 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,
}

Debe incluir archivos de listas de API en el origen para las comprobaciones de API. Para hacer esto, cree archivos API y un directorio api . Coloque el directorio api en el mismo directorio que 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 API de los códigos fuente actuales, y <module_name>-latest.txt contiene las firmas API congeladas más recientes. El sistema comprueba si la acumulación API se cambian mediante la comparación de estos archivos de la API con archivos de la API generados en tiempo de compilación y emite un mensaje de error y las instrucciones para actualizar current.txt archivo si current.txt no coincide con los códigos fuente. Aquí hay un ejemplo de organización de directorio y archivo:

├── api
│   ├── PlatformProperties-current.txt
│   └── PlatformProperties-latest.txt
└── Android.bp

Los módulos de cliente de Java y C ++ pueden vincularse con sysprop_library para utilizar las API generadas. El sistema de compilación crea enlaces desde los clientes a las bibliotecas C ++ y Java generadas, lo que les da a los clientes acceso a las API generadas.

java_library {
    name: "JavaClient",
    srcs: ["foo/bar.java"],
    libs: ["PlatformProperties"],
}

cc_binary {
    name: "cc_client",
    srcs: ["baz.cpp"],
    shared_libs: ["PlatformProperties"],
}

En el ejemplo anterior, puede acceder a las propiedades definidas de la siguiente manera.

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);
    }
    …
}
…