Dodaj właściwości systemowe

Ta strona zawiera kanoniczną metodę dodawania lub definiowania właściwości systemowych z wytycznymi dotyczącymi refaktoryzacji istniejących właściwości systemowych. Pamiętaj, aby przy refaktoryzacji korzystać z wytycznych, chyba że masz silne że jest to problem ze zgodnością, który dyktuje inne warunki.

Krok 1. Zdefiniuj właściwość systemową

Po dodaniu usługi systemowej wybierz jej nazwę i powiąż z kontekstem właściwości SELinux. Jeśli nie ma odpowiedniego kontekstu, utwórz nowy. Nazwa jest używana przy próbie uzyskania dostępu do usługi. obiekt jest używany do kontrolowania ułatwień dostępu w przypadku SELinux. Nazwy mogą być dowolnymi ciągami znaków, ale AOSP zaleca, aby były one uporządkowane w jasny sposób.

Nazwa właściwości

Użyj tego formatu, stosując wielkość liter w nazwie snake_case:

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

Użyj „” (pominięto), ro (w przypadku właściwości ustawionych tylko raz) lub persist (w przypadku właściwości, które utrzymują się po ponownym uruchomieniu) dla elementu prefix.

Uwagi

Używaj ro tylko wtedy, gdy masz pewność, że nie potrzebujesz prefix do zapisu w przyszłości. ** Nie podawaj prefiksu ro.** Zamiast tego użyj sepolicy, aby ustawić prefix jako tylko do odczytu (czyli tylko init będzie mieć uprawnienia do zapisu).

Używaj funkcji persist tylko wtedy, gdy masz pewność, że wartość musi być trwała restartów i użycie właściwości systemu to jedyna opcja.

Google ściśle sprawdza właściwości systemowe, które mają właściwości ro lub persist.

Termin group służy do agregowania powiązanych właściwości. Ma ona za zadanie być nazwą podsystemu podobną do nazwy audio lub telephony. Nie używaj niejednoznaczne lub przeciążone terminy, takie jak sys, system, dev, default lub config

Powszechną praktyką jest używanie nazwy typu domeny który ma wyłączny dostęp do właściwości systemu z uprawnieniami do odczytu lub zapisu. Na przykład w przypadku właściwości systemowych, do których proces vold ma uprawnienia do zapisu, często jako nazwę grupy używa się wartości vold (nazwa typu domeny dla procesu).

W razie potrzeby dodaj subgroup, aby jeszcze bardziej kategoryzować usługi. niejednoznacznych lub przeciążonych terminami opisującymi ten element. (Możesz mieć więcej niż jedną subgroup).

Wiele nazw grup jest już zdefiniowanych. Sprawdź plik system/sepolicy/private/property_contexts i w miarę możliwości używaj istniejących nazw grup zamiast tworzyć nowe. W poniższej tabeli podano Przykłady często używanych nazw grup.

Domena Grupa (i podgrupa)
związane z Bluetooth bluetooth
sysprops z cmdline jądra boot
sysprops, które identyfikują kompilację build
związane z telefonią telephony
związane z dźwiękiem audio
grafika graphics
Powiązane z Vold vold

Poniżej definiujemy użycie name i type w poprzednim przykładzie wyrażenia regularnego.

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

  • name identyfikuje właściwość systemu w grupie.

  • type to opcjonalny element, który wyjaśnia typ lub intencję właściwości systemowej. Na przykład zamiast nadawać nazwę audio.awesome_feature_enabled lub po prostu audio.awesome_feature, nadaj nazwę audio.awesome_feature.enabled, aby odzwierciedlała typ i zamierzenie właściwości systemowej.

Nie ma konkretnej reguły na to, jakiego typu musi być typ konta. to są użycie zalecenia:

  • enabled: użyj, jeśli typ jest właściwością systemową typu logicznego, która służy do włączania i wyłączania funkcji.
  • config: użyj, jeśli chcesz wyjaśnić, że właściwość systemowa nie reprezentuje dynamicznego stanu systemu, lecz skonfigurowaną wartość (np. element tylko do odczytu).
  • List: użyj tej właściwości, jeśli jest to właściwość systemowa, której wartość jest listą.
  • Timeoutmillis: użyj, jeśli jest to właściwość systemowa wartości limitu czasu w ms.

Przykłady:

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

Kontekst usługi

Nowy schemat kontekstu usługi SELinux umożliwia bardziej szczegółowe i opisowe nazwy. Podobnie jak w przypadku nazw właściwości, AOSP zaleca w tym formacie:

{group}[_{subgroup}]*_prop

Terminy są zdefiniowane w następujący sposób:

Znaczenie group i subgroup jest takie samo jak w poprzednim przykładowe wyrażenie regularne. Na przykład vold_config_prop oznacza właściwości, które są konfiguracjami od dostawcy i mają być ustawiane przez vendor_init, a vold_status_prop lub tylko vold_prop oznaczają właściwości, które mają wyświetlać bieżący stan vold.

Nadając nazwę kontekstowi właściwości, wybierz nazwy, które odzwierciedlają ogólne użycie z właściwościami. Unikaj zwłaszcza tych typów haseł:

  • Terminy, które wydają się zbyt ogólne i niejednoznaczne, np. sys, system, default.
  • Hasła bezpośrednio związane z dostępnością: exported, apponly, ro, public, private.

Preferuj użycie nazw, takie jak vold_config_propexported_vold_prop, lub vold_vendor_writable_prop.

Typ

Typ usługi może być jednym z tych wymienionych w tabeli.

Typ Definicja
Wartość logiczna true lub 1 – tak, false lub 0 – fałsz
Liczba całkowita 64-bitowa liczba całkowita ze znakiem
liczba całkowita bez znaku 64-bitowa liczba całkowita bez znaku
Podwójny podwójna precyzja zmiennoprzecinkowa
Ciąg znaków dowolny prawidłowy ciąg UTF-8
enum wartościami mogą być dowolne prawidłowe ciągi znaków UTF-8 bez spacji
Lista powyżej Jako separatora (,) używana jest przecinka (
)
Lista liczb całkowitych [1, 2, 3] jest przechowywana jako 1,2,3

Wewnętrznie wszystkie właściwości są przechowywane jako ciągi znaków. Możesz wymusić ten typ przez i określić go jako plik property_contexts. Więcej informacji: property_contexts w kroku 3.

Krok 2. Określ wymagane poziomy ułatwień dostępu

Właściwość definiują 4 makro pomocnicze.

Typ ułatwień dostępu Znaczenie
system_internal_prop Właściwości używane tylko w /system
system_restricted_prop Właściwości, które są odczytywane na zewnątrz /system, ale nie są zapisywane
system_vendor_config_prop Właściwości odczytywane poza /system i zapisywane tylko przez vendor_init
system_public_prop Właściwości odczytywane i zapisywane poza /system

Jak najwęższy zakres dostępu do właściwości systemowych. W przeszłości powszechnego dostępu do danych spowodował awarię aplikacji i luki w zabezpieczeniach. Rozważ następujące pytania przy określaniu zakresu:

  • Czy ta właściwość systemu musi być zachowana? (jeśli tak, dlaczego?)
  • Który proces powinien mieć uprawnienia do odczytu tej usługi?
  • Który proces powinien mieć uprawnienia do zapisu w tej usłudze?

Użyj poprzednich pytań i poniższego schematu decyzyjnego jako narzędzi do określając odpowiedni zakres dostępu.

Schemat decyzyjny służący do określania zakresu dostępu

Rysunek 1. Schemat decyzyjny służący do określania zakresu dostępu do właściwości systemu

Krok 3. Dodaj do system/sepolicy

Podczas uzyskiwania dostępu do sysprop SELinux kontroluje dostępność procesów. Po określeniu wymaganego poziomu dostępności zdefiniuj konteksty usługi w sekcji system/sepolicy, a także dodatkowe reguły allowneverallow dotyczące tego, które procesy mogą (lub nie) czytać i pisać.

Najpierw określ kontekst usługi w pliku system/sepolicy/public/property.te. Jeśli właściwość jest wewnętrzna, zdefiniuj ją w pliku system/sepolicy/private/property.te. Użyj jednego z makro system_[accessibility]_prop([context]), które zapewnia wymaganą dostępność dla właściwości systemu. To jest przykład dla funkcji Plik system/sepolicy/public/property.te:

system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)

Przykład dodania do pliku system/sepolicy/private/property.te:

system_internal_prop(audio_baz_prop)

Po drugie, przyznaj uprawnienia do odczytu lub zapisu w kontekście usługi. Aby przyznać dostęp, użyj makr set_prop i get_prop w pliku system/sepolicy/public/{domain}.te lub system/sepolicy/private/{domain}.te. W miarę możliwości używaj zasady private. public jest odpowiedni tylko wtedy, gdy Makro set_prop lub get_prop wpływa na wszystkie domeny spoza domeny podstawowej.

Przykład w pliku system/sepolicy/private/audio.te:

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

Przykład w pliku system/sepolicy/public/domain.te:

get_prop(domain, audio_bar_prop)

Po trzecie dodaj reguły nigdy nie zezwalaj, aby jeszcze bardziej ograniczyć ograniczony do zakresu przez makro. Załóżmy na przykład, że użyliśmy system_restricted_prop, ponieważ właściwości systemu muszą być odczytywane przez procesy dostawcy. Jeśli uprawnienia do odczytu nie są wymagane przez wszystkie procesy dostawcy są wymagane tylko przez określony zestaw procesów (np. vendor_init), zakazują procesów dostawcy, które nie potrzebują uprawnień do odczytu.

Aby ograniczyć dostęp do zapisu i odczytu, użyj tej składni:

Aby ograniczyć uprawnienia do zapisu:

neverallow [domain] [context]:property_service set;

Aby ograniczyć dostęp do odczytu:

neverallow [domain] [context]:file no_rw_file_perms;

Umieść reguły neverallow w pliku system/sepolicy/private/{domain}.te, jeśli reguła neverallow jest powiązana z konkretną domeną. Aby stosować ogólniejsze reguły nigdy nie zezwalaj, użyj ogólnych domen, takich jak te, gdy jest to konieczne:

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

W pliku system/sepolicy/private/audio.te umieść:

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

W pliku system/sepolicy/private/property.te umieść:

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

Pamiętaj, że {domain -coredomain} rejestruje wszystkie procesy dostawcy. No więc {domain -coredomain -vendor_init} oznacza „wszystkie procesy dostawcy oprócz vendor_init”.

Na koniec powiąż usługę systemową z kontekstem usługi. Dzięki temu masz pewność, że przyznany dostęp oraz reguły nigdy nie zezwalaj, które są stosowane do są stosowane do rzeczywistych właściwości. Aby to zrobić, dodaj wpis do pliku property_contexts, który opisuje mapowanie między właściwościami systemu a kontekstami właściwości. W tym pliku możesz określić lub prefiks usług, które mają zostać zmapowane w kontekście.

Oto składnia mapowania pojedynczej usługi:

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

Oto składnia mapowania prefiksu:

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

Opcjonalnie możesz określić typ usługi, który może być jednym z tych:

  • bool
  • int
  • uint
  • double
  • enum [list of possible values...]
  • string (w przypadku usług list używaj wartości string).

Gdy tylko jest to możliwe, każdy wpis ma wyznaczony typ, ponieważ type jest wymuszane podczas konfigurowania ustawienia property. Ten przykład pokazuje, jak napisać mapowanie:

# 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

W przypadku konfliktu wpisu dokładnego i wpisu z prefiksem pierwszeństwo ma wpis dokładny. Więcej przykładów: system/sepolicy/private/property_contexts.

Krok 4. Określ wymagania dotyczące stabilności

Stabilność to kolejny aspekt właściwości systemu, który różni się od ułatwienia dostępu. Stabilność oznacza, czy w przyszłości można zmienić (np. zmienić nazwę lub nawet usunąć) daną właściwość systemu. To jest szczególnie ważne, ponieważ system operacyjny Android staje się modułowy. Dzięki Treble partycje systemu, dostawcy i produktu można aktualizować niezależnie od siebie. Z Mainline, niektóre części systemu operacyjnego są modułowe w postaci modułów możliwych do aktualizacji (w APEX lub pliki APK).

Jeśli właściwość systemowa jest przeznaczona do użytku w aktualizacjach oprogramowania, na przykład między partycjami systemu i dostawcy, musi być stabilny. Jeśli jednak używasz atrybutu tylko w ramach określonego modułu Mainline, możesz zmienić jego nazwę, i kontekstów właściwości, a nawet je usuwać.

Aby określić stabilność właściwości systemu, zadaj sobie te pytania:

  • Czy ta właściwość systemu ma być konfigurowana przez partnerów (lub różni się w zależności od urządzenia)? Jeśli tak, musi być stabilny.
  • Czy ta właściwość systemowa zdefiniowana przez AOSP jest przeznaczona do zapisu lub odczytu kodu (nie procesu), który istnieje na partycjach niesystemowych, takich jak vendor.img lub product.img? Jeśli tak, musi być stabilny.
  • Czy ta usługa systemowa jest dostępna w modułach Mainline czy przez Mainline i niedostępnej do aktualizacji części platformy? Jeśli tak, musi być stabilna.

W przypadku stabilnych właściwości systemu zdefiniuj je formalnie jako interfejs API i użyj interfejsu API dostęp do właściwości systemowej, zgodnie z opisem na stronie Krok 6.

Krok 5. Ustaw właściwości w czasie kompilacji

Ustawianie właściwości podczas kompilacji za pomocą zmiennych Makefile. Technicznie rzecz biorąc, wartości są wbudowane w {partition}/build.prop. Następnie init odczytuje {partition}/build.prop, aby ustawić właściwości. Istnieją 2 zbiory takich zmiennych: PRODUCT_{PARTITION}_PROPERTIESTARGET_{PARTITION}_PROP.

PRODUCT_{PARTITION}_PROPERTIES zawiera listę wartości właściwości. Składnia to {prop}={value} lub {prop}?={value}.

{prop}={value} to normalne przypisanie, które zapewnia, że {prop} jest ustawione jako {value}. W przypadku jednej właściwości możliwe jest tylko jedno takie przypisanie.

Zadanie {prop}?={value} jest opcjonalne. Pole {prop} jest ustawiane na wartość {value} tylko wtedy, gdy Brak projektów {prop}={value}. Jeśli istnieje kilka opcjonalnych przypisań, pierwszeństwo ma pierwsze z nich.

# 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 zawiera listę plików, która jest bezpośrednio wysyłana do {partition}/build.prop Każdy plik zawiera listę {prop}={value} par.

# 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

Więcej informacji znajdziesz w sekcji build/make/core/sysprop.mk.

Krok 6. Uzyskaj dostęp do właściwości w czasie działania

Właściwości można odczytywać i zapisywać w czasie działania.

Skrypty inicjalizacji

Pliki skryptu init (zwykle pliki *.rc) mogą odczytywać właściwość przez ${prop} lub ${prop:-default} może ustawić działanie wywoływane za każdym razem, gdy usługa stanie się określoną wartość i może zapisać właściwości za pomocą polecenia setprop.

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

polecenia powłoki getprop i setprop

Aby odczytać lub zapisać właściwości, możesz użyć poleceń getprop lub setprop. Aby dowiedzieć się więcej, wywołaj getprop --help lub setprop --help.

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

Sysprop jako interfejs API dla C++, Javy i Rusta

Dzięki interfejsowi sysprop możesz definiować właściwości systemu i korzystać z automatycznie generowanych interfejsów API, które są konkretne i typowe. Ustawienie zasady scope z ustawieniem Public powoduje też wygenerowanie Interfejsy API są dostępne dla modułów bez ograniczeń i zapewniają stabilność interfejsu API. Oto przykład pliku .sysprop, modułu Android.bp oraz kodu w językach C++, Java i Rust, który z nich korzysta.

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

// Rust, Java and C++ modules can link against the sysprop_library
rust_binary {
    rustlibs: ["libaudioprops_rust"],
    …
}

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

cc_binary {
    static_libs: ["libAudioProps"],
    …
}
// Rust code accessing generated API.
// Get volume. Use 50 as the default value.
let vol = audioprops::volume_level()?.unwrap_or_else(50);
// 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);

Więcej informacji znajdziesz w artykule Implementowanie właściwości systemu jako interfejsów API.

Funkcje i metody właściwości niskopoziomowych w C/C++, Java i Rust

Jeśli to możliwe, używaj interfejsu Sysprop jako interfejsu API, mimo że masz dostęp do funkcji niskiego poziomu w językach C/C++ lub Rust oraz do niskiego poziomu metod w języku Java.

Biblioteki libc, libbaselibcutils udostępniają funkcje właściwości systemowych C++. libc ma bazowy interfejs API, natomiast funkcje libbase i libcutils są otoki. Jeśli to możliwe, użyj funkcji sysprop libbase; to oni a pliki binarne hosta mogą używać funkcji libbase. Więcej szczegóły: sys/system_properties.h (libc), android-base/properties.h (libbase) i cutils/properties.h (libcutils).

Klasa android.os.SystemProperties zawiera metody właściwości systemowych Java.

Moduł rustutils::system_properties zawiera funkcje i typy właściwości systemowych Rust.

Dodatek: dodawanie właściwości specyficznych dla dostawcy

Partnerzy (w tym pracownicy Google zajmujący się opracowywaniem telefonów Pixel) chcą aby zdefiniować właściwości systemowe specyficzne dla sprzętu (lub urządzenia). Usługi specyficzne dla dostawców to usługi należące do partnerów, które są unikalne z własnym sprzętem lub urządzeniem, a nie z platformą. Ponieważ są to urządzenia lub urządzenia zależne, są przeznaczone do użycia w partycjach /vendor lub /odm.

Od momentu wprowadzenia Project Treble właściwości platformy i dostawcy zostały zostały całkowicie podzielone, aby zapobiec konfliktom. Poniżej dowiesz się, jak definiują właściwości dostawcy i informuje, które z nich mają być zawsze używane.

Przestrzeń nazw w nazwach właściwości i kontekstów

Wszystkie właściwości dostawcy muszą zaczynać się od jednego z tych prefiksów, aby zapobiec kolizji z właściwościami innych partycji.

  • 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.

Pamiętaj, że znak ro.hardware. jest dozwolony jako prefiks, ale tylko ze względu na zgodność. Nie używaj go w przypadku zwykłych usług.

W podanych niżej przykładach użyto jednego z wymienionych powyżej prefiksów:

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

Wszystkie konteksty właściwości dostawcy muszą zaczynać się od vendor_. Dotyczy to także kompatybilności. Oto kilka przykładów:

  • vendor_radio_prop.
  • vendor_faceauth_prop.
  • vendor_usb_prop.

Nazewnictwo i utrzymywanie usług należy do dostawcy, dlatego stosuj format sugerowany w kroku 2, a także wymagania dotyczące przestrzeni nazw dostawcy.

Właściwe dla dostawcy reguły SEPolicy i property_contexts

Właściwości dostawcy można zdefiniować za pomocą makra vendor_internal_prop. Zdefiniowane przez Ciebie reguły dotyczące dostawcy umieść w katalogu BOARD_VENDOR_SEPOLICY_DIRS. Załóżmy na przykład, że definiujesz w kolorze koralowym usługę dostawcy faceauth.

W pliku BoardConfig.mk (lub w dowolnym pliku BoardConfig.mk) umieść:

BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy

W pliku device/google/coral-sepolicy/private/property.te umieść:

vendor_internal_prop(vendor_faceauth_prop)

W pliku device/google/coral-sepolicy/private/property_contexts umieść makro :

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

Ograniczenia właściwości dostawców

Systemy i partycje produktu nie mogą być zależne od dostawcy, nigdy zezwól na dostęp do usług dostawcy za pomocą platformy system, system-ext lub Partycje: product.

Dodatek: zmiana nazw istniejących usług

Jeśli musisz wycofać usługę i przejść na nową, użyj interfejsów Sysprop jako interfejsów API, aby zmienić nazwy dotychczasowych usług. Zapewnia to zgodność wsteczną przez podając zarówno starszą nazwę, jak i nazwę nowej usługi. W szczególności możesz ustaw starszą nazwę przez pole legacy_prop_name w pliku .sysprop. Wygenerowany interfejs API próbuje odczytać parametr prop_name i używa parametru legacy_prop_name, jeśli parametr prop_name nie istnieje.

Na przykład te kroki pozwalają zmienić nazwę awesome_feature_foo_enabled do: foo.awesome_feature.enabled.

W pliku foo.sysprop

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

W kodzie w 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);

Pamiętaj o tych ograniczeniach:

  • Po pierwsze, nie można zmienić typu właściwości sysprop. Na przykład nie można rekwizyt int w string. Możesz tylko zmienić nazwę.

  • Po drugie, tylko interfejs API do odczytu przyjmuje starszą nazwę. Interfejs API do zapisu nie korzysta z tego rozwiązania. Jeśli jest to obiekt sysprop z możliwością zapisu, nie możesz zmienić jego nazwy.