Ta strona zawiera kanoniczną metodę dodawania lub definiowania właściwości systemowych na Androidzie, wraz ze wskazówkami dotyczącymi refaktoryzacji istniejących właściwości systemowych. Pamiętaj, aby podczas refaktoryzacji korzystać z tych wytycznych, chyba że masz poważny problem ze zgodnością, który dowodzi, że jest inaczej.
Krok 1. Zdefiniuj właściwość systemową
Po dodaniu właściwości systemowej wybierz dla niej nazwę i powiąż ją z kontekstem usługi SELinux. Jeśli brakuje odpowiedniego kontekstu, utwórz nowy. Ta nazwa jest używana podczas uzyskiwania dostępu do właściwości, a kontekst właściwości służy do kontrolowania ułatwień dostępu w SELinux. Nazwy mogą być dowolnymi ciągami znaków, ale AOSP zaleca stosowanie uporządkowanego formatu, który zapewni ich przejrzystość.
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ętego), ro
(w przypadku właściwości ustawionych tylko raz) lub persist
(w przypadku właściwości, które są trwałe po ponownym uruchomieniu) dla elementu prefix
.
Uwagi
Używaj ro
tylko wtedy, gdy masz pewność, że nie potrzebujesz elementu prefix
, aby umożliwić zapis. ** Nie określaj prefiksu ro
.** Zamiast tego użyj funkcji sepolicy, aby element prefix
był dostępny tylko do odczytu (innymi słowy, dostępny tylko do zapisu w usłudze init
).
Używaj metody persist
tylko wtedy, gdy masz pewność, że wartość musi być niezmienna po ponownym uruchomieniu, a jedyną opcją jest użycie właściwości systemowych.
Google ściśle sprawdza właściwości systemowe z właściwościami ro
lub persist
.
Termin group
służy do agregowania powiązanych usług. Powinna to być nazwa podsystemu podobna do audio
lub telephony
. Nie używaj
niejednoznacznych lub przeciążonych haseł, takich jak sys
, system
, dev
, default
czy config
.
Powszechną praktyką jest używanie nazwy typu domeny w procesie, który ma wyłączny dostęp do właściwości systemowych 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, jako nazwy grupy często używa się nazwy vold
(nazwa typu domeny procesu).
W razie potrzeby dodaj subgroup
, aby dodatkowo kategoryzować właściwości. Unikaj jednak niejasnych i przeciążonych określeń opisujących ten element. (Możesz też mieć więcej niż jeden subgroup
).
Zdefiniowano wiele nazw grup. Sprawdź plik system/sepolicy/private/property_contexts
i w miarę możliwości używaj istniejących nazw grup, zamiast tworzyć nowe. W tabeli poniżej znajdziesz przykłady często używanych nazw grup.
Domena | Grupa (i podgrupa) |
---|---|
Związane z Bluetoothem | bluetooth |
sysprop z wiersza cmdline jądra | boot |
sysprops, które identyfikują kompilację | build
|
telefonia | telephony |
związane z dźwiękiem | audio |
związane z grafiką | graphics |
Powiązane z Vold | vold |
Poniżej znajdziesz definicje użycia name
i type
w poprzednim przykładzie wyrażenia regularnego.
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
identyfikuje właściwość systemową w grupie.type
to opcjonalny element, który wyjaśnia typ lub intencję właściwości systemowej. Na przykład zamiast nazywać sysprop „audio.awesome_feature_enabled
” lub po prostuaudio.awesome_feature
, zmień nazwę naaudio.awesome_feature.enabled
, by odzwierciedlić typ i intencje systemu.
Nie ma konkretnej reguły określającej jego typ. Oto zalecenia dotyczące użytkowania:
enabled
: użyj, jeśli typ jest właściwością systemową z wartością logiczną używaną do włączania lub wyłączania funkcji.config
: użyj tej opcji, jeśli celem jest wyjaśnienie, że właściwość systemowa nie reprezentuje dynamicznego stanu systemu, tylko reprezentuje wstępnie skonfigurowaną wartość (np. rzecz 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 dla wartości czasu oczekiwania w jednostkach ms.
Przykłady:
persist.radio.multisim.config
drm.service.enabled
Kontekst usługi
Nowy schemat kontekstu właściwości SELinux zapewnia większą szczegółowość i bardziej opisowe nazwy. Podobnie jak w przypadku nazw właściwości, AOSP zaleca użycie tego formatu:
{group}[_{subgroup}]*_prop
Terminy są zdefiniowane w następujący sposób:
Hasła group
i subgroup
mają to samo znaczenie co poprzednie przykładowe wyrażenie regularne. Na przykład vold_config_prop
oznacza właściwości, które są konfiguracjami dostawcy i które mają być ustawiane przez vendor_init
, a vold_status_prop
lub po prostu vold_prop
– właściwości, które ujawniają bieżący stan vold
.
Nazywając kontekst właściwości, wybierz nazwy, które odzwierciedlają ogólne zastosowanie właściwości. Unikaj w szczególności tych rodzajów haseł:
- Terminy, które wyglądają na zbyt ogólne i niejednoznaczne, np.
sys
,system
,default
. - Terminy bezpośrednio kodujące ułatwienia dostępu:
exported
,apponly
,ro
,public
,private
.
Preferuj użycie nazw takie jak vold_config_prop
–exported_vold_prop
lub vold_vendor_writable_prop
.
Typ
Typ usługi może być jednym z tych typów podanych 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 | zmiennoprzecinkowa podwójnej precyzji |
Ciąg znaków | dowolny prawidłowy ciąg UTF-8 |
typ wyliczeniowy | Wartościami mogą być dowolny prawidłowy ciąg UTF-8 bez odstępów |
Lista powyżej | Jako separator używany jest przecinek (, ).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, określając go jako plik property_contexts
. Więcej informacji znajdziesz w sekcji property_contexts
w kroku 3.
Krok 2. Określ wymagane poziomy ułatwień dostępu
Istnieją 4 makra pomocnicze, które definiują właściwość.
Typ ułatwień dostępu | Znaczenie |
---|---|
system_internal_prop |
Usługi używane tylko w domenie /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, które są odczytywane poza domeną /system i zapisywane tylko przez vendor_init |
system_public_prop |
Właściwości, które są odczytywane i zapisywane poza domeną /system |
Jak najwęższy zakres dostępu do właściwości systemowych. W przeszłości szeroki dostęp do aplikacji powodował awarię aplikacji i luki w zabezpieczeniach. Podczas określania zakresu weź pod uwagę te pytania:
- 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?
Aby określić odpowiedni zakres dostępu, użyj poprzednich pytań i poniższego schematu decyzyjnego.
Rysunek 1. Drzewo decyzyjne służące do określania zakresu dostępu do usług systemowych
Krok 3. Dodaj do zasady systemowej/sepolicy
Podczas uzyskiwania dostępu do narzędzia sysprop SELinux kontroluje dostępność procesów. Gdy ustalisz, jaki poziom ułatwień dostępu jest wymagany, zdefiniuj kontekst właściwości w sekcji system/sepolicy
oraz dodatkowe reguły zezwalaj i nigdy dotyczące tego, co procesy mogą odczytywać lub zapisywać.
Najpierw określ kontekst właściwości w pliku system/sepolicy/public/property.te
. Jeśli właściwość jest ustawiona wewnętrznie, zdefiniuj ją w pliku system/sepolicy/private/property.te
. Użyj jednego z makr system_[accessibility]_prop([context])
, które zapewniają ułatwienia dostępu wymagane przez usługę systemową. Oto przykład pliku system/sepolicy/public/property.te
:
system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)
Przykład do dodania w pliku system/sepolicy/private/property.te
:
system_internal_prop(audio_baz_prop)
Następnie przyznaj uprawnienia do odczytu i zapisu w kontekście usługi. Aby przyznać dostęp w pliku system/sepolicy/public/{domain}.te
lub system/sepolicy/private/{domain}.te
, użyj makr set_prop
i get_prop
. W miarę możliwości używaj private
. public
jest odpowiedni tylko wtedy, gdy makro set_prop
lub get_prop
ma wpływ na 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ć ułatwienia dostępu ograniczone przez makro. Załóżmy na przykład, że używasz metody system_restricted_prop
, ponieważ właściwości systemowe muszą być odczytywane przez procesy dostawcy. Jeśli dostęp z możliwością odczytu nie jest wymagany przez wszystkie procesy dostawcy i tylko przez określony zestaw procesów (np. vendor_init
), zablokuj procesy dostawcy, które nie potrzebują tych uprawnień.
Aby ograniczyć uprawnienia 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;
Jeśli reguła nigdy nie jest powiązana z konkretną domeną, umieść reguły „Nigdy nie zezwalaj” w pliku system/sepolicy/private/{domain}.te
. Aby stosować ogólniejsze reguły nigdy nie zezwalaj,
używaj domen ogólnych, takich jak:
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. {domain -coredomain -vendor_init}
oznacza więc „wszystkie procesy dostawcy z wyjątkiem
vendor_init
”.
Na koniec powiąż usługę systemową z kontekstem usługi. Dzięki temu przyznany dostęp i reguły nigdy nie zezwalaj, które są stosowane do kontekstów usług, są stosowane do rzeczywistych usług. Aby to zrobić, dodaj wpis do pliku property_contexts
, który opisuje mapowanie między właściwościami systemowymi a kontekstami właściwości. W tym pliku możesz określić pojedynczą usługę lub prefiks usług, które mają być mapowane 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 właściwości:
bool
int
uint
double
enum [list of possible values...]
string
(użyjstring
w przypadku właściwości listy).
Gdy tylko jest to możliwe, każdy wpis ma wyznaczony typ, ponieważ przy ustawianiu property
wymuszana jest zasada type
. Poniższy przykład pokazuje, jak utworzyć 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 między dokładnym wpisem a wpisem prefiksu pierwszeństwo ma dokładny wpis. 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łatwień dostępu. Stabilność określa, czy właściwość systemową można zmienić (np. zmienić jej nazwę, a nawet usunąć) w przyszłości. Jest to szczególnie ważne, ponieważ system operacyjny Android staje się modułowy. W Treble podziały systemowe, dostawcy i produkty można aktualizować niezależnie. W Mainline niektóre części systemu operacyjnego są modułowe w postaci modułów z możliwością aktualizacji (w APEX lub plikach APK).
Jeśli właściwość systemowa jest przeznaczona do użytku w aktualizacjach oprogramowania, np. w ramach partycji systemu i dostawcy, musi być stabilna. Jeśli jednak jest on używany np. tylko w określonym module Mainline, możesz zmienić jego nazwę, typ lub kontekst właściwości, a nawet go usunąć.
Aby określić stabilność właściwości systemu, zadaj te pytania:
- Czy ta właściwość systemu ma być konfigurowana przez partnerów (lub oddzielnie dla każdego urządzenia)? Jeśli tak, musi być stabilny.
- Czy ta właściwość systemowa zdefiniowana przez AOSP jest przeznaczona do zapisywania lub odczytu w kodzie (a nie w procesie), który istnieje na partycjach niesystemowych, takich jak
vendor.img
lubproduct.img
? Jeśli tak, musi być stabilny. - Czy do tej właściwości systemowej uzyskuje się dostęp przez moduły Mainline, czy przez moduł Mainline i nieaktualizowaną część platformy? Jeśli tak, musi być stabilny.
W przypadku stabilnych właściwości systemu zdefiniuj je formalnie jako interfejs API i użyj interfejsu API, aby uzyskać dostęp do właściwości systemu, jak opisano w kroku 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 polecenie {partition}/build.prop
, aby ustawić właściwości. Istnieją 2 zestawy takich zmiennych: PRODUCT_{PARTITION}_PROPERTIES
i TARGET_{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 gwarantuje, że {prop}
ma wartość {value}
. W przypadku pojedynczej usługi możliwe jest tylko jedno takie przypisanie.
{prop}?={value}
to przypisanie opcjonalne. {prop}
ustawia wartość {value}
tylko wtedy, gdy nie ma żadnych przypisań {prop}={value}
. Jeśli jest kilka projektów opcjonalnych, wygrywa pierwsze.
# 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: 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 inicjujące
Pliki skryptów init (zwykle pliki *.rc) mogą odczytywać właściwość za pomocą polecenia ${prop}
lub ${prop:-default}
, ustawiać działanie wywoływane za każdym razem, gdy właściwość staje się określoną wartością, oraz zapisywać 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
Do odczytu lub zapisu właściwości możesz używać poleceń powłoki 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++/Java/Rust
Za pomocą interfejsu sysprop jako interfejsu API możesz definiować właściwości systemu i korzystać z automatycznie generowanego interfejsu API, który jest określony i wpisany. Ustawienie scope
z ustawieniem Public
udostępnia też wygenerowane interfejsy API modułom bez ograniczeń i zapewnia stabilność interfejsów API. Oto przykład pliku .sysprop
, modułu Android.bp
oraz kodu w językach C++, Java i Rust.
# 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
W miarę możliwości używaj Sysprop jako interfejsu API, nawet jeśli masz dostęp do niskopoziomowych funkcji w języku C/C++ lub Rust albo do niskopoziomowych metod Java.
libc
, libbase
i libcutils
udostępniają funkcje właściwości systemowych w C++. libc
ma bazowy interfejs API, a funkcje libbase
i libcutils
to funkcje opakowujące. Jeśli to możliwe, użyj funkcji sysprop libbase
. Jest to najwygodniejszy sposób, a w plikach binarnych hosta można używać funkcji libbase
. Więcej informacji znajdziesz w artykułach 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 systemu Rust.
Dodatek: dodawanie właściwości specyficznych dla dostawcy
Partnerzy (w tym pracownicy Google zajmujący się opracowywaniem telefonów Pixel) chcą zdefiniować właściwości systemowe związane ze sprzętem (lub urządzeniem).
Usługi specyficzne dla dostawców to należące do partnerów usługi, które są unikalne dla ich sprzętu lub urządzenia, a nie dla platformy. Zależą one od sprzętu lub urządzenia, dlatego należy ich używać w partycjach /vendor
lub /odm
.
Odkąd w Project Treble właściwości platformy i dostawcy zostały całkowicie podzielone, by zapobiec konfliktom. Poniżej opisujemy, jak definiować właściwości dostawcy, i wskazujemy, których z nich należy zawsze używać.
Przestrzeń nazw w nazwach właściwości i kontekstów
Aby uniknąć kolizji między właściwościami innych partycji, wszystkie usługi dostawców muszą zaczynać się od jednego z tych prefiksów.
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 prefiks ro.hardware.
jest dozwolony, ale tylko w celu zapewnienia zgodności.
Nie używaj go w przypadku zwykłych usług.
W poniższych przykładach używany jest jeden z wymienionych wyż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 też zgodności. Przykłady:
vendor_radio_prop
.vendor_faceauth_prop
.vendor_usb_prop
.
Za nazywanie i utrzymywanie usług odpowiada dostawca, dlatego poza wymaganiami dotyczącymi przestrzeni nazw dostawców przestrzegaj formatu zalecanego w kroku 2.
Reguły SEPolicy i właściwości_contexts specyficzne dla dostawcy
Właściwości dostawcy można określić za pomocą makra vendor_internal_prop
. Umieść zdefiniowane przez siebie reguły konkretnego dostawcy w katalogu BOARD_VENDOR_SEPOLICY_DIRS
.
Załóżmy na przykład, że definiujesz właściwość Faceauth dostawcy w koralu.
W pliku BoardConfig.mk
(lub w dowolnym elemencie 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ść:
vendor.faceauth.trace u:object_r:vendor_faceauth_prop:s0 exact bool
Ograniczenia właściwości dostawców
Partycje systemu i produktu nie mogą być zależne od dostawcy, dlatego nigdy nie zezwalaj na dostęp do jego właściwości z partycji system
, system-ext
ani product
.
Dodatek: zmiana nazw istniejących usług
Jeśli musisz wycofać usługę i przejść do nowej, użyj Sysprop jako interfejsów API, aby zmienić nazwę istniejących usług. Aby zachować zgodność wsteczną, podaj zarówno nazwę starszego typu, jak i nową nazwę właściwości. Starszą nazwę możesz ustawić w polu legacy_prop_name
w pliku .sysprop
. Wygenerowany interfejs API próbuje odczytać zasadę prop_name
, a jeśli prop_name
nie istnieje, używa metody legacy_prop_name
.
W poniższych krokach na przykład zmień nazwę z awesome_feature_foo_enabled
na 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 kwestiach:
Po pierwsze nie możesz zmienić typu sysprop. Nie możesz na przykład przekształcić rekwizytu
int
w właściwośćstring
. Możesz tylko zmienić nazwę.Po drugie, tylko interfejs API do odczytu przyjmuje starszą nazwę. Interfejs Write API nie wraca. Jeśli obiekt sysprop jest zapisem, nie możesz go zmienić.