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 podczas refaktoryzacji postępować zgodnie z wytycznymi, chyba że masz mocne że jest to problem ze zgodnością, który dyktuje inne warunki.
Krok 1. Zdefiniuj właściwość systemową
Po dodaniu właściwości 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ć dowolne ciągu znaków. Jednak AOSP zaleca stosowanie uporządkowanego formatu, który zapewnia 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ę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 funkcji ro
tylko wtedy, gdy masz pewność, że nie potrzebujesz prefix
do zapisu
w przyszłości. ** Nie określaj prefiksu ro
.** Zamiast tego używaj narzędzia sepolicy, aby
ustaw plik prefix
jako tylko do odczytu (innymi słowy, dostępny tylko do zapisu przez init
).
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ą ro
lub persist
.
usług.
Termin group
służy do agregowania powiązanych usług. 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
ma wyłączny dostęp do właściwości systemu z uprawnieniami do odczytu lub zapisu. Dla:
w przypadku właściwości systemowych, do których proces vold
ma uprawnienia do zapisu,
jest często używany jako vold
(nazwa typu domeny procesu) jako
nazwę grupy.
W razie potrzeby dodaj subgroup
, aby jeszcze bardziej kategoryzować usługi.
niejednoznacznych lub przeciążonych terminami opisującymi ten element. (Możesz też mieć więcej opcji
niż jeden subgroup
.)
Zdefiniowano wiele nazw grup. Zajrzyj do
system/sepolicy/private/property_contexts
plik i użyj istniejących nazw grup
w miarę możliwości, zamiast tworzyć nowe. W poniższej tabeli 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ższy kod definiuje użycie elementów name
i type
w poprzednim wyrażeniem regularnym
.
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
identyfikuje właściwość systemową w grupie.type
to opcjonalny element, który określa typ lub intencję funkcji właściwość systemową. Na przykład zamiast nazywać sysprop jakoaudio.awesome_feature_enabled
lub po prostuaudio.awesome_feature
, zmień nazwę naaudio.awesome_feature.enabled
, aby odzwierciedlić typ i intencję usługi 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ą z wartością logiczną i służy do zmieniania włączyć lub wyłączyć daną funkcję.config
: użyj, jeśli chcesz wyjaśnić, że właściwość systemowa nie reprezentuje dynamicznego stanu systemu. reprezentuje wstępnie skonfigurowaną wartość (na przykład 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. z 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 więcej funkcji. nazw opisowych. 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
usług, które są konfiguracjami dostawcy i mają być ustawiane przez
vendor_init
, podczas gdy vold_status_prop
lub tylko vold_prop
oznaczają właściwości
które ujawniają 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 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: np.
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 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
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 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.
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. Po
określić wymagany poziom ułatwień dostępu, zdefiniować kontekst właściwości
w atrybucie system/sepolicy
oraz dodatkowe reguły allow i neverallow.
o tym, co te procesy mogą (a czego nie) mogą odczytywać lub zapisywać.
Najpierw określ kontekst właściwości w tabeli system/sepolicy/public/property.te
.
. Jeśli właściwość jest ustawiona wewnętrznie, zdefiniuj ją w
system/sepolicy/private/property.te
. Użyj jednego z
Makra system_[accessibility]_prop([context])
, które dostarczają funkcji
w zakresie dostępu wymaganej przez właściwość systemową. 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 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. Użyj formatu: set_prop
i get_prop
, aby przyznać dostęp, w
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 np., że jako podstawę prawną do wykorzystania kodu
system_restricted_prop
, ponieważ właściwości systemowe muszą być odczytywane przez dostawcę
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ć 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;
Umieść reguły nigdy w pliku system/sepolicy/private/{domain}.te
, jeśli
reguła nigdy nie jest powiązana z określoną 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
property_contexts
– plik opisujący mapowanie systemu
właściwości i kontekstach 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 właściwości, którym może być jeden z :
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ż type
jest
wymuszane podczas konfigurowania ustawienia property
. Poniższy 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 między dokładnym wpisem a wpisem prefiksu dokładny wpis zajmuje
pierwszeństwo. 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ść określa, czy właściwość systemową można (np. zmieniono ich nazwę, a nawet usunięto) w przyszłości. To jest szczególnie ważne, ponieważ system operacyjny Android staje się modułowy. W wysokich tonach system podziały dostawcy i produktu mogą być aktualizowane niezależnie od siebie. Na 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 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
lubproduct.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ć stabilny.
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. Z technicznego punktu widzenia wartości
są wbudowane w {partition}/build.prop
. Następnie init
odczytuje
{partition}/build.prop
, aby ustawić właściwości. Istnieją 2 zestawy takich
zmienne: PRODUCT_{PARTITION}_PROPERTIES
i TARGET_{PARTITION}_PROP
.
PRODUCT_{PARTITION}_PROPERTIES
zawiera listę wartości właściwości. Składnia
jest {prop}={value}
lub {prop}?={value}
.
{prop}={value}
to normalne przypisanie, które gwarantuje, że {prop}
jest ustawiony na
{value}
; W przypadku danej usługi możliwy jest tylko jeden taki przydział.
Zadanie {prop}?={value}
jest opcjonalne. Pole {prop}
jest ustawiane na wartość {value}
tylko wtedy, gdy
Brak projektów {prop}={value}
. Jeśli jest wiele przypisań opcjonalnych
istnieje, wygrywa pierwszy 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 tutaj:
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 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ślonych wartości 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
Można użyć odpowiednio poleceń powłoki getprop
lub setprop
do odczytywania lub
zapisz właściwości. 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
Z pomocą sysprop jako interfejsu API możesz definiować właściwości systemu i korzystać z automatycznie wygenerowanego interfejsu API
konkretne i wpisane na klawiaturze. 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
jak ich używać.
# 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
Gdy to możliwe, używaj Sysprop jako interfejsu API, nawet jeśli używasz funkcji niskiego poziomu w C/C++ lub Rust lub niskiego poziomu w Javie.
libc
, libbase
i libcutils
udostępniają funkcje właściwości systemowych w 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
oferuje funkcje właściwości systemu Rust
i typów plików.
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 pod względem
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 można całkowicie podzielić na grupy, 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 usługi dostawcy muszą zaczynać się od jednego z tych prefiksów, aby zapobiegać kolizji między nimi a 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 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 także
zgodność. Przykłady:
vendor_radio_prop
.vendor_faceauth_prop
.vendor_usb_prop
.
Obowiązkiem dostawcy jest nazwanie i utrzymywanie usług, więc przestrzegaj sugerowane w kroku 2, oprócz wymagania dotyczące przestrzeni nazw dostawcy.
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ść parametr
konkretnego dostawcy, które określisz 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 obiekcie BoardConfig.mk
) umieść
:
BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy
W pliku device/google/coral-sepolicy/private/property.te
umieść makro
:
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ść do nowej, użyj Sysprop jako interfejsów API.
możesz zmienić nazwy istniejących 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ć prop_name
i używa legacy_prop_name
, jeśli
Zasób (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 kwestiach:
Po pierwsze nie możesz zmienić typu sysprop. Na przykład nie można rekwizyt
int
wstring
. Możesz tylko zmienić nazwę.Po drugie, tylko interfejs API do odczytu przyjmuje starszą nazwę. Interfejs Write API nie awaryjne. Jeśli obiekt sysprop jest zapisem, nie możesz go zmienić.