Adicionar propriedades do sistema

Esta página fornece um método canônico para adicionar ou definir propriedades do sistema no Android, com diretrizes para refatorar as propriedades do sistema existentes. Certifique-se de usar as diretrizes ao refatorar, a menos que tenha um problema de compatibilidade forte que determine o contrário.

Fundo

As propriedades do sistema são usadas para vários propósitos porque são fáceis de usar. Embora sejam semelhantes a variáveis ​​globais em linguagens de programação, não há um conjunto de requisitos de processo formalizados ou convenções de nomenclatura a serem seguidas ao criá-las. Portanto, as propriedades do sistema podem ser difíceis de entender e manter. As etapas nesta página definem as propriedades do sistema e fornecem etapas para adicioná-las e mantê-las.

Preparação: Considere alternativas

Determine se uma propriedade do sistema é realmente o que você deseja e se é sua única opção. As propriedades do sistema são recursos de todo o sistema que oferecem certas vantagens. Eles são fáceis de usar e suas propriedades não dinâmicas têm uma sobrecarga de desempenho relativamente baixa. Ao usar as propriedades do sistema, você não precisa usar a comunicação entre processos (IPC), mesmo que uma propriedade do sistema seja compartilhada entre vários processos. No entanto, eles também podem ser prejudiciais quando usados ​​incorretamente, semelhantes às variáveis ​​globais. O uso indevido das propriedades do sistema resultou em problemas como aplicativos inacessíveis para os usuários e a introdução de vulnerabilidades de segurança.

Considere as muitas alternativas para as propriedades do sistema a seguir, para avaliar se uma delas pode fornecer a solução de que você precisa.

Preferências Compartilhadas

Para uma configuração persistente local para um aplicativo, use a interface Shared Preferences , em vez das propriedades do sistema.

HAL

Quando a fonte de verdade para uma configuração é de um componente de hardware em um dispositivo, a HAL deve fornecer as informações para esse componente. Não configure o HAL para gravar uma propriedade do sistema para permitir que outros processos a leiam (ou vice-versa). Em vez disso, defina um novo método HAL para acessar a configuração. Em outras palavras, não use as propriedades do sistema como um mecanismo de comunicação de canal lateral para HALs.

Observe que você não precisa de um novo HAL para este caso de uso, pois é uma opção cara. Use esta sugestão somente quando você tiver um HAL existente para abstrair o componente de hardware.

Arquivo de configuração

Quando os dados de configuração são estáticos, mas complicados (em outras palavras, estruturados), considere usar XML ou outros formatos para os dados de configuração. Certifique-se de que o esquema de arquivo permaneça estável. Para arquivos XML, você pode usar xsd_config para manter o esquema estável e aproveitar um analisador XML gerado automaticamente.

Serviço de fichário

As propriedades do sistema são frequentemente usadas para compartilhar o estado dinâmico de um subsistema com vários processos. Esses estados podem ser implementados dentro de um serviço de binder (como um campo de objeto) e outros processos podem ler (ou mesmo modificar) o estado, usando chamadas de binder para o serviço. Esta é a solução preferida, pois tornar o estado uma propriedade do sistema e conceder acesso direto a ele requer um processo semelhante a este:

  1. Execute uma verificação de sanidade no estado.
  2. Execute o pós-processamento no estado para torná-lo consumível.
  3. Execute uma função de controle de acesso refinada.
  4. Manter o estado estruturado.

Concluir esse processo com êxito é impossível ou, na melhor das hipóteses, muito difícil quando você está implementando um estado como uma propriedade do sistema. Portanto, use a opção de serviço de fichário quando os leitores do estado já tiverem acesso ao serviço de fichário.

Etapa 1: Definindo a propriedade do sistema

Ao adicionar uma propriedade do sistema, decida um nome para a propriedade e associe-a a um contexto de propriedade do SELinux. Se não houver um contexto existente apropriado, crie um novo. O nome é utilizado ao acessar a propriedade; o contexto da propriedade é usado para controlar a acessibilidade em termos de SELinux. Os nomes podem ser qualquer string, mas o AOSP recomenda que você siga um formato estruturado para torná-los claros.

Nome da propriedade

Use este formato com caixa snake_case:

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

Use “” (omitido), ro (para propriedades definidas apenas uma vez) ou persist (para propriedades que persistem entre reinicializações) para o prefix do elemento .

Ressalvas

Use ro somente quando tiver certeza de que não precisa de prefix para ser gravável no futuro. ** Não especifique o prefixo ro .** Em vez disso, confie na sepolicy para tornar o prefix somente leitura (em outras palavras, gravável apenas por init ).

Use persist apenas quando tiver certeza de que o valor deve ser persistido nas reinicializações e que usar as propriedades do sistema é sua única opção. (Para obter detalhes, consulte a seção Preparação .)

O Google analisa estritamente as propriedades do sistema que têm propriedades ro ou persist .

O termo group é usado para agregar propriedades relacionadas. Destina-se a ser um nome de subsistema semelhante ao uso de audio ou telephony . Não use termos ambíguos ou sobrecarregados como sys , system , dev , default ou config .

É uma prática comum usar o nome do tipo de domínio de um processo que tenha acesso exclusivo de leitura ou gravação às propriedades do sistema. Por exemplo, para as propriedades do sistema às quais o processo vold tem acesso de gravação, é comum usar vold (o nome do tipo de domínio para o processo) como o nome do grupo.

Se necessário, adicione subgroup para categorizar ainda mais as propriedades, mas evite termos ambíguos ou sobrecarregados para descrever esse elemento. (Você também pode ter mais de um subgroup .)

Muitos nomes de grupos já foram definidos. Verifique o arquivo system/sepolicy/private/property_contexts e use nomes de grupos existentes sempre que possível, em vez de criar novos. A tabela a seguir fornece exemplos de nomes de grupos usados ​​com frequência.

Domínio Grupo (e subgrupo)
relacionado ao bluetooth bluetooth
sysprops do kernel cmdline boot
sysprops que identificam uma compilação build
relacionado à telefonia telephony
relacionado a áudio audio
gráficos relacionados graphics
vold relacionado vold

O seguinte define o uso de name e type no exemplo de regex anterior.

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

  • name identifica uma propriedade do sistema dentro de um grupo.

  • type é um elemento opcional que esclarece o tipo ou a intenção da propriedade do sistema. Por exemplo, em vez de nomear um audio.awesome_feature_enabled como audio.awesome_feature_enabled ou apenas audio.awesome_feature , renomeie-o como audio.awesome_feature.enabled para refletir o tipo e a intenção da propriedade do sistema.

Não há uma regra específica sobre qual deve ser o tipo; estas são recomendações de uso:

  • enabled : use se o tipo for uma propriedade booleana do sistema usada para ativar ou desativar um recurso.
  • config : Use se a intenção for esclarecer que a propriedade do sistema não representa um estado dinâmico do sistema; ele representa um valor pré-configurado (por exemplo, uma coisa somente leitura).
  • List : Use se for uma propriedade do sistema cujo valor é uma lista.
  • Timeoutmillis : Use se for uma propriedade do sistema para um valor de tempo limite em unidades de ms.

Exemplos:

  • persist.radio.multisim.config
  • drm.service.enabled

Contexto da propriedade

O novo esquema de contexto de propriedade do SELinux permite granularidade mais fina e nomes mais descritivos. Semelhante ao que é usado para nomes de propriedades, o AOSP recomenda o seguinte formato:

{group}[_{subgroup}]*_prop

Os termos são definidos da seguinte forma:

group e subgroup têm o mesmo significado definido para a regex de amostra anterior. Por exemplo, vold_config_prop significa propriedades que são configurações de um fornecedor e devem ser definidas por vendor_init , enquanto vold_status_prop ou apenas vold_prop significa propriedades que devem expor o status atual de vold .

Ao nomear um contexto de propriedade, escolha nomes que reflitam o uso geral das propriedades. Em particular, evite os seguintes tipos de termos:

  • Termos que parecem muito gerais e ambíguos, como sys , system , default .
  • Termos que codificam diretamente a acessibilidade: como exported , apponly , ro , public , private .

Prefira usos de nomes como vold_config_prop para exported_vold_prop ou vold_vendor_writable_prop e assim por diante.

Modelo

Um tipo de propriedade pode ser um dos seguintes, conforme listado na tabela.

Modelo Definição
boleano true ou 1 para verdadeiro, false ou 0 para falso
inteiro inteiro de 64 bits assinado
Inteiro não assinado inteiro de 64 bits sem sinal
Dobro ponto flutuante de precisão dupla
Corda qualquer string UTF-8 válida
enumerar valores podem ser qualquer string UTF-8 válida sem espaços em branco
Lista de acima Uma vírgula ( , ) é usada como delimitador
A lista de inteiros [1, 2, 3] é armazenada como 1,2,3

Internamente, todas as propriedades são armazenadas como strings. Você pode impor o tipo especificando-o como um arquivo property_contexts . Para obter mais informações, consulte property_contexts na Etapa 3 .

Etapa 2: determinar os níveis de acessibilidade necessários

Existem quatro macros auxiliares que definem uma propriedade.

Tipo de acessibilidade Significado
system_internal_prop Propriedades que são usadas apenas em /system
system_restricted_prop Propriedades que são lidas fora /system , mas não escritas
system_vendor_config_prop Propriedades que são lidas fora /system e escritas apenas por vendor_init
system_public_prop Propriedades que são lidas e escritas fora /system

O escopo do acesso às propriedades do sistema é o mais restrito possível. No passado, o acesso amplo resultou em quebra de aplicativos e vulnerabilidades de segurança. Considere as seguintes perguntas ao definir o escopo:

  • Essa propriedade do sistema precisa ser persistida? (se sim, por quê?)
  • Qual processo deve ter acesso de leitura a esta propriedade?
  • Qual processo deve ter acesso de gravação a essa propriedade?

Use as perguntas anteriores e a seguinte árvore de decisão como ferramentas para determinar um escopo apropriado para acesso.

Decision tree for determining the scope of access

Figura 1. Árvore de decisão para determinar o escopo de acesso às propriedades do sistema

Etapa 3: Adicionando-o ao sistema/sepolicy

Ao acessar o sysprop, o SELinux controla a acessibilidade dos processos. Depois de determinar qual nível de acessibilidade é necessário, defina contextos de propriedade em system/sepolicy , juntamente com regras adicionais de permissão e nunca permissão sobre o que os processos podem (e não) ler ou gravar.

Primeiro, defina o contexto da propriedade no arquivo system/sepolicy/public/property.te . Se a propriedade for interna ao sistema, defina-a no arquivo system/sepolicy/private/property.te . Use uma das macros system_[accessibility]_prop([context]) que fornece a acessibilidade necessária de sua propriedade de sistema. Este é um exemplo para o arquivo system/sepolicy/public/property.te :

system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)

Exemplo para adicionar no arquivo system/sepolicy/private/property.te :

system_internal_prop(audio_baz_prop)

Segundo, conceda acesso de leitura e (ou) gravação ao contexto da propriedade. Use as macros set_prop e get_prop para conceder acesso, no system/sepolicy/public/{domain}.te ou system/sepolicy/private/{domain}.te . Use private sempre que possível; public é adequado apenas se a macro set_prop ou get_prop afetar qualquer domínio fora do domínio principal.

Exemplo, no arquivo system/sepolicy/private/audio.te :

set_prop(audio, audio_foo_prop)
set_prop(audio, audio_bar_prop)

Exemplo, no arquivo system/sepolicy/public/domain.te :

get_prop(domain, audio_bar_prop)

Em terceiro lugar, adicione algumas regras neverallow para reduzir ainda mais a acessibilidade no escopo da macro. Por exemplo, suponha que você tenha usado system_restricted_prop porque as propriedades do seu sistema devem ser lidas pelos processos do fornecedor. Se o acesso de leitura não for exigido por todos os processos do fornecedor e for exigido apenas por um determinado conjunto de processos (como vendor_init ), proíba os processos do fornecedor que não precisam do acesso de leitura.

Use a seguinte sintaxe para restringir o acesso de gravação e leitura:

Para restringir o acesso de gravação:

neverallow [domain] [context]:property_service set;

Para restringir o acesso de leitura:

neverallow [domain] [context]:file no_rw_file_perms;

Coloque as regras neverallow no arquivo system/sepolicy/private/{domain}.te se a regra neverallow estiver vinculada a um domínio específico. Para regras de nunca permitir mais amplas, use domínios gerais como estes sempre que apropriado:

  • system/sepolicy/private/property.te
  • system/sepolicy/private/coredomain.te
  • system/sepolicy/private/domain.te

No arquivo system/sepolicy/private/audio.te , coloque o seguinte:

neverallow {
    domain -init -audio
} {audio_foo_prop audio_bar_prop}:property_service set;

No arquivo system/sepolicy/private/property.te , coloque o seguinte:

neverallow {
    domain -coredomain -vendor_init
} audio_prop:file no_rw_file_perms;

Observe que {domain -coredomain} captura todos os processos do fornecedor. Portanto {domain -coredomain -vendor_init} significa "todos os processos do fornecedor, exceto vendor_init ."

Por fim, associe uma propriedade do sistema ao contexto da propriedade. Isso garante que o acesso concedido e as regras neverallow aplicadas aos contextos de propriedade sejam aplicadas às propriedades reais. Para fazer isso, inclua uma entrada no arquivo property_contexts , um arquivo que descreve o mapeamento entre as propriedades do sistema e os contextos de propriedade. Nesse arquivo, você pode especificar uma única propriedade ou um prefixo para que as propriedades sejam mapeadas em um contexto.

Esta é a sintaxe para mapear uma única propriedade:

[property_name] u:object_r:[context_name]:s0 exact [type]

Esta é a sintaxe para mapear um prefixo:

[property_name_prefix] u:object_r:[context_name]:s0 prefix [type]

Opcionalmente, você pode especificar o tipo da propriedade, que pode ser um dos seguintes:

  • bool
  • int
  • uint
  • double
  • enum [list of possible values...]
  • string (Use string para propriedades de lista.)

Certifique-se de que cada entrada tenha seu tipo designado sempre que possível, pois o type é aplicado ao definir a property . O exemplo a seguir mostra como escrever um mapeamento:

# binds a boolean property "ro.audio.status.enabled"
# to the context "audio_foo_prop"
ro.audio.status.enabled u:object_r:audio_foo_prop:s0 exact bool

# binds a boolean property "vold.decrypt.status"
# to the context "vold_foo_prop"
# The property can only be set to one of these: on, off, unknown
vold.decrypt.status u:object_r:vold_foo_prop:s0 exact enum on off unknown

# binds any properties starting with "ro.audio.status."
# to the context "audio_bar_prop", such as
# "ro.audio.status.foo", or "ro.audio.status.bar.baz", and so on.
ro.audio.status. u:object_r:audio_bar_prop:s0 prefix

Quando uma entrada exata e uma entrada de prefixo entram em conflito, a entrada exata tem precedência. Para obter mais exemplos, consulte system/sepolicy/private/property_contexts .

Etapa 4: Determinando os requisitos de estabilidade

A estabilidade é outro aspecto das propriedades do sistema e difere da acessibilidade. A estabilidade é sobre se uma propriedade do sistema pode ou não ser alterada (por exemplo, renomeada ou até mesmo removida) no futuro. Isso é particularmente importante à medida que o sistema operacional Android se torna modular. Com o Treble, as partições do sistema, do fornecedor e do produto podem ser atualizadas independentemente umas das outras. Com o Mainline, algumas partes do SO são modularizadas como módulos atualizáveis ​​(em APEXes ou APKs).

Se uma propriedade do sistema for usada em softwares atualizáveis, por exemplo, em partições do sistema e do fornecedor, ela deverá ser estável. No entanto, se for usado apenas em, por exemplo, um módulo Mainline específico, você poderá alterar seu nome, tipo ou contextos de propriedade e até removê-lo.

Faça as seguintes perguntas para determinar a estabilidade de uma propriedade do sistema:

  • Essa propriedade do sistema deve ser configurada por parceiros (ou configurada de forma diferente por dispositivo)? Se sim, deve ser estável.
  • Essa propriedade de sistema definida por AOSP deve ser gravada ou lida de código (não processo) que existe em partições que não são do sistema, como vendor.img ou product.img ? Se sim, deve ser estável.
  • Essa propriedade do sistema é acessada nos módulos Mainline ou em um módulo Mainline e na parte não atualizável da plataforma? Se sim, deve ser estável.

Para as propriedades estáveis ​​do sistema, defina formalmente cada uma como uma API e use a API para acessar a propriedade do sistema, conforme explicado na Etapa 6 .

Etapa 5: definir propriedades em tempo de compilação

Defina as propriedades em tempo de compilação com variáveis ​​makefile. Tecnicamente, os valores são enviados para {partition}/build.prop . Em seguida, o init{partition}/build.prop para definir as propriedades. Existem dois conjuntos dessas variáveis: PRODUCT_{PARTITION}_PROPERTIES e TARGET_{PARTITION}_PROP .

PRODUCT_{PARTITION}_PROPERTIES contém uma lista de valores de propriedade. A sintaxe é {prop}={value} ou {prop}?={value} .

{prop}={value} é uma atribuição normal que garante que {prop} seja definido como {value} ; apenas uma atribuição desse tipo é possível por uma única propriedade.

{prop}?={value} é uma atribuição opcional; {prop} é definido como {value} somente se não houver atribuições {prop}={value} . Se existirem várias atribuições opcionais, a primeira vence.

# sets persist.traced.enable to 1 with system/build.prop
PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1

# sets ro.zygote to zygote32 with system/build.prop
# but only when there are no other assignments to ro.zygote
# optional are useful when giving a default value to a property
PRODUCT_SYSTEM_PROPERTIES += ro.zygote?=zygote32

# sets ro.config.low_ram to true with vendor/build.prop
PRODUCT_VENDOR_PROPERTIES += ro.config.low_ram=true

TARGET_{PARTITION}_PROP contém uma lista de arquivos, que é emitida diretamente para {partition}/build.prop . Cada arquivo contém uma lista de pares {prop}={value} .

# example.prop

ro.cp_system_other_odex=0
ro.adb.secure=0
ro.control_privapp_permissions=disable

# emits example.prop to system/build.prop
TARGET_SYSTEM_PROP += example.prop

Para obter mais detalhes, consulte build/make/core/sysprop.mk .

Etapa 6: acessar as propriedades em tempo de execução

Claro, as propriedades podem ser lidas e escritas em tempo de execução.

Scripts de inicialização

Arquivos de script de inicialização (geralmente arquivos *.rc) podem ler uma propriedade por ${prop} ou ${prop:-default} , podem definir uma ação que é executada sempre que uma propriedade se tornar um valor específico e podem escrever as propriedades usando o setprop comando.

# when persist.device_config.global_settings.sys_traced becomes 1,
# set persist.traced.enable to 1
on property:persist.device_config.global_settings.sys_traced=1
    setprop persist.traced.enable 1

# when security.perf_harden becomes 0,
# write /proc/sys/kernel/sample_rate to the value of
# debug.sample_rate. If it's empty, write -100000 instead
on property:security.perf_harden=0
    write /proc/sys/kernel/sample_rate ${debug.sample_rate:-100000}

comandos shell getprop e setprop

Você pode usar os comandos shell getprop ou setprop , respectivamente, para ler ou gravar as propriedades. Para obter mais detalhes, invoque getprop --help ou setprop --help .

$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0

Sysprop como API para C++/Java

Com sysprop como API, você pode definir propriedades do sistema e usar API gerada automaticamente que são concretas e tipadas. Definir o scope com Public também disponibiliza APIs geradas para módulos além dos limites e garante a estabilidade da API. Aqui está uma amostra de um arquivo .sysprop , um módulo Android.bp e código C++ e Java usando-os.

# AudioProps.sysprop
# module becomes static class (Java) / namespace (C++) for serving API
module: "android.sysprop.AudioProps"
# owner can be Platform or Vendor or Odm
owner: Platform
# one prop defines one property
prop {
    prop_name: "ro.audio.volume.level"
    type: Integer
    scope: Public
    access: ReadWrite
    api_name: "volume_level"
}
…

// Android.bp
sysprop_library {
    name: "AudioProps",
    srcs: ["android/sysprop/AudioProps.sysprop"],
    property_owner: "Platform",
}

// Both java and cc module can link against sysprop_library
java_library {
    static_libs: ["AudioProps"],
    …
}

cc_binary {
    static_libs: ["AudioProps"],
    …
}

// Java codes accessing generated API
// get volume. use 50 as the default value.
int vol = android.sysprop.AudioProps.volume_level().orElse(50);
// add 10 to the volume level.
android.sysprop.AudioProps.volume_level(vol + 10);

// C++ codes accessing generated API
// get volume. use 50 as the default value.
int vol = android::sysprop::AudioProps::volume_level().value_or(50);
// add 10 to the volume level.
android::sysprop::AudioProps::volume_level(vol + 10);

Para obter mais informações, consulte Implementando propriedades do sistema como APIs .

Funções e métodos de propriedades de baixo nível C/C++ e Java

Use Sysprop como API, mesmo que funções C/C++ de baixo nível ou métodos Java de baixo nível estejam disponíveis para você. Prefira o uso do Sysprop sobre eles sempre que puder.

libc , libbase e libcutils oferecem funções de propriedade do sistema C++. libc tem a API subjacente, enquanto as funções libbase e libcutils são wrappers. Se for possível, use as funções libbase sysprop; eles são os mais convenientes, e os binários do host podem usar as funções libbase . Para obter mais detalhes, consulte sys/system_properties.h ( libc ), android-base/properties.h ( libbase ) e cutils/properties.h ( libcutils ).

A classe android.os.SystemProperties oferece métodos de propriedade do sistema Java.

Apêndice: Adicionando propriedades específicas do fornecedor

Os parceiros (incluindo Googlers que trabalham no contexto de desenvolvimento do Pixel) desejam definir propriedades do sistema específicas do hardware (ou do dispositivo). As propriedades específicas do fornecedor são propriedades de propriedade do parceiro que são exclusivas de seu próprio hardware ou dispositivo, não da plataforma. Como eles são dependentes de hardware ou dispositivo, eles devem ser usados ​​nas partições /vendor ou /odm .

Desde o Project Treble, as propriedades da plataforma e do fornecedor foram completamente divididas para evitar conflitos. O seguinte descreve como definir as propriedades do fornecedor e informa quais propriedades do fornecedor devem sempre ser usadas.

Namespace em nomes de propriedades e contextos

Todas as propriedades do fornecedor devem começar com um dos seguintes prefixos para evitar colisões entre elas e as propriedades de outras partições.

  • ctl.odm.
  • ctl.vendor.
  • ctl.start$odm.
  • ctl.start$vendor.
  • ctl.stop$odm.
  • ctl.stop$vendor.
  • init.svc.odm.
  • init.svc.vendor.
  • ro.odm.
  • ro.vendor.
  • odm.
  • persist.odm.
  • persist.vendor.
  • vendor.

Observe que ro.hardware. é permitido como prefixo, mas apenas para compatibilidade. Não o use para propriedades normais.

Todos os exemplos a seguir usam um dos prefixos listados acima:

  • vendor.display.primary_red
  • persist.vendor.faceauth.use_disk_cache
  • ro.odm.hardware.platform

Todos os contextos de propriedade do fornecedor devem começar com vendor_ . Isso também é para compatibilidade. Seguem exemplos:

  • vendor_radio_prop .
  • vendor_faceauth_prop .
  • vendor_usb_prop .

É responsabilidade do fornecedor nomear e manter as propriedades, portanto, siga o formato sugerido na Etapa 2 , além dos requisitos de namespaces do fornecedor.

Regras de SEPolicy específicas do fornecedor e property_contexts

Semelhante às propriedades da plataforma, as propriedades do fornecedor podem ser definidas por uma das seguintes macros.

Tipo de acessibilidade Significado
vendor_internal_prop Propriedades que são usadas apenas em /vendor
vendor_restricted_prop Propriedades que são lidas fora /vendor , mas não escritas
vendor_public_prop Propriedades que são lidas e escritas fora /vendor

Coloque as regras específicas do fornecedor que você define no diretório BOARD_VENDOR_SEPOLICY_DIRS . Por exemplo, suponha que você esteja definindo uma propriedade de faceauth de fornecedor em coral.

No arquivo BoardConfig.mk (ou em qualquer inclui BoardConfig.mk ), coloque o seguinte:

BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy

No arquivo device/google/coral-sepolicy/private/property.te , coloque o seguinte:

vendor_internal_prop(vendor_faceauth_prop)

No arquivo device/google/coral-sepolicy/private/property_contexts , coloque o seguinte:

vendor.faceauth.trace u:object_r:vendor_faceauth_prop:s0 exact bool

Limitações das propriedades do fornecedor

Como as partições do sistema e do produto não podem depender do fornecedor, nunca permita que as propriedades do fornecedor sejam acessadas a partir das partições system , system-ext ou product .

Apêndice: Renomeando propriedades existentes

Quando você deve descontinuar uma propriedade e mover para uma nova, use Sysprop como APIs para renomear suas propriedades existentes. Isso mantém a compatibilidade com versões anteriores especificando o nome herdado e o novo nome da propriedade. Especificamente, você pode definir o nome legado pelo campo legacy_prop_name no arquivo .sysprop . A API gerada tenta ler prop_name e usa legacy_prop_name se prop_name não existir.

Por exemplo, as etapas a seguir renomeiam awesome_feature_foo_enabled para foo.awesome_feature.enabled .

No arquivo foo.sysprop (em Java)

module: "android.sysprop.foo"
owner: Platform
prop {
    api_name: "is_awesome_feature_enabled"
    type: Boolean
    scope: Public
    access: Readonly
    prop_name: "foo.awesome_feature.enabled"
    legacy_prop_name: "awesome_feature_foo_enabled"
}

Em código C++

// is_awesome_feature_enabled() reads "foo.awesome_feature.enabled".
// If it doesn't exist, reads "awesome_feature_foo_enabled" instead
using android::sysprop::foo;

bool enabled = foo::is_awesome_feature_enabled().value_or(false);

Observe as seguintes advertências:

  • Primeiro, você não pode alterar o tipo do sysprop. Por exemplo, você não pode transformar uma prop int em uma prop string . Você só pode alterar o nome.

  • Em segundo lugar, apenas a API de leitura retorna ao nome herdado. A API de gravação não faz fallback. Se o sysprop for gravável, você não poderá renomeá-lo.