O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Implementando Propriedades do Sistema como APIs

As propriedades do sistema fornecem uma maneira conveniente de compartilhar informações, geralmente configurações, em todo o sistema. Cada partição pode usar suas próprias propriedades de sistema internamente. Pode ocorrer um problema quando as propriedades são acessadas através de partições, como /vendor accessing /system -defined properties. Desde o Android 8.0, algumas partições, como /system , podem ser atualizadas, enquanto /vendor permanece inalterado. Como as propriedades do sistema são apenas um dicionário global de pares de chave / valor de string sem esquema, é difícil estabilizar as propriedades. A partição /system pode alterar ou remover propriedades das quais a partição /vendor depende sem qualquer aviso.

A partir da versão Android 10, as propriedades do sistema acessadas através das partições são esquematizadas em arquivos de descrição Sysprop e APIs para acessar as propriedades são geradas como funções concretas para C ++ e classes para Java. Essas APIs são mais convenientes de usar porque nenhuma string mágica (como ro.build.date ) é necessária para o acesso e porque podem ser digitadas estaticamente. A estabilidade da ABI também é verificada no momento da compilação e a compilação é interrompida se ocorrerem alterações incompatíveis. Esta verificação atua como interfaces definidas explicitamente entre as partições. Essas APIs também podem fornecer consistência entre Java e C ++.

Definindo propriedades do sistema como APIs

Defina as propriedades do sistema como APIs com arquivos de descrição Sysprop ( .sysprop ), que usam um TextFormat de protobuf, com o seguinte 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;
}

Um arquivo de descrição Sysprop contém uma mensagem de propriedades, que descreve um conjunto de propriedades. O significado de seus campos são os seguintes.

Campo Significado
owner Defina como a partição que possui as propriedades: Platform , Vendor ou Odm .
module Usado para criar um namespace (C ++) ou classe final estática (Java) na qual APIs geradas são colocadas. Por exemplo, com.android.sysprop.BuildProperties será o namespace com::android::sysprop::BuildProperties em C ++ e a classe BuildProperties no pacote em com.android.sysprop em Java.
prop Lista de propriedades.

Os significados dos campos de mensagem de Property são os seguintes.

Campo Significado
api_name O nome da API gerada.
type O tipo desta propriedade.
access Somente Readonly : gera apenas API getter

Writeonce , ReadWrite : gera APIs getter e setter

Nota: Propriedades com o prefixo ro. não pode usar o acesso ReadWrite .

scope Internal : apenas o proprietário pode acessar.

Public : todos podem acessar, exceto para módulos NDK.

prop_name O nome da propriedade do sistema subjacente, por exemplo ro.build.date .
enum_values ( Enum , EnumList apenas) Uma string EnumList barras (|) que consiste em possíveis valores de enum. Por exemplo, value1|value2 .
integer_as_bool ( Boolean , BooleanList apenas) Faça os setters usarem 0 e 1 vez de false e verdadeiro.
legacy_prop_name (opcional, Readonly propriedades somente Readonly ) O nome legado da propriedade do sistema subjacente. Ao chamar getter, a API getter tenta ler prop_name e usa legacy_prop_name se prop_name não existir. Use legacy_prop_name ao descontinuar uma propriedade existente e mover para uma nova propriedade.

Cada tipo de propriedade mapeia para os seguintes tipos em C ++ e Java.

Tipo C ++ Java
boleano std::optional<bool> Optional<Boolean>
Inteiro std::optional<std::int32_t> Optional<Integer>
UInt std::optional<std::uint32_t> Optional<Integer>
Longo std::optional<std::int64_t> Optional<Long>
ULong std::optional<std::uint64_t> Optional<Long>
Duplo std::optional<double> Optional<Double>
Corda 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>

Aqui está um exemplo de um arquivo de descrição Sysprop definindo três propriedades:

# 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
}

Definindo bibliotecas de propriedades do sistema

Agora você pode definir sysprop_library módulos com Sysprop Inscrição arquivos. sysprop_library serve como uma API para C ++ e Java. O sistema de construção gera internamente uma java_library e uma cc_library para cada instância de sysprop_library .

// File: Android.bp
sysprop_library {
    name: "PlatformProperties",
    srcs: ["android/sysprop/PlatformProperties.sysprop"],
    property_owner: "Platform",
    vendor_available: true,
}

Você deve incluir arquivos de listas de API na fonte para verificações de API. Para fazer isso, crie arquivos API e um diretório api . Coloque o diretório api no mesmo diretório que Android.bp . Os nomes de arquivos da API são <module_name>-current.txt , <module_name>-latest.txt . <module_name>-current.txt contém as assinaturas de API dos códigos-fonte atuais e <module_name>-latest.txt contém as assinaturas de API congeladas mais recentes. O sistema verifica se o build APIs são alteradas, comparando esses arquivos API com arquivos API geradas em tempo de compilação e emite uma mensagem de erro e instruções para atualizar current.txt arquivo se current.txt não coincide com os códigos fonte. Aqui está um exemplo de diretório e organização de arquivos:

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

Ambos os módulos de cliente Java e C ++ podem ser vinculados a sysprop_library para usar APIs geradas. O sistema de construção cria links de clientes para bibliotecas C ++ e Java geradas, dando aos clientes acesso às APIs geradas.

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

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

No exemplo acima, você pode acessar as propriedades definidas a seguir.

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

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