בדף הזה מוסבר על שיטה קנונית להוספה או להגדרה של מאפייני מערכת ב-Android, ומופיעות הנחיות לשינוי מבנה של מאפייני מערכת קיימים. חשוב לפעול לפי ההנחיות כשמבצעים רפקטורינג, אלא אם יש בעיית תאימות חמורה שמחייבת אחרת.
שלב 1: הגדרת מאפיין המערכת
כשמוסיפים מאפיין מערכת, צריך לבחור שם למאפיין ולשייך אותו להקשר של מאפיין SELinux. אם אין הקשר מתאים, צריך ליצור הקשר חדש. השם משמש כשניגשים למאפיין, וההקשר של המאפיין משמש לשליטה בנגישות מבחינת SELinux. השמות יכולים להיות כל מחרוזת, אבל ב-AOSP מומלץ להשתמש בפורמט מובנה כדי שהם יהיו ברורים.
שם הנכס
צריך להשתמש בפורמט הזה עם אותיות קטנות וקו תחתון בין המילים (snake_case):
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
משתמשים באחת מהאפשרויות הבאות: "" (השמטה), ro
(למאפיינים שמוגדרים רק פעם אחת) או persist
(למאפיינים שנשמרים גם אחרי הפעלה מחדש) עבור הרכיב prefix
.
נקודות שחשוב לדעת
משתמשים ב-ro
רק כשבטוחים שלא יהיה צורך בעתיד ש-prefix
יהיה ניתן לכתיבה. ** אל מציינים את הקידומת ro
. במקום זאת, מסתמכים על sepolicy כדי להפוך את prefix
לקריאה בלבד (כלומר, אפשר לכתוב רק באמצעות init
).
משתמשים ב-persist
רק כשבטוחים שהערך צריך להישמר גם אחרי הפעלה מחדש, ושהשימוש במאפייני המערכת הוא האפשרות היחידה.
Google בודקת בקפדנות את מאפייני המערכת שיש להם מאפיינים ro
או persist
.
המונח group
משמש לצבירה של נכסים קשורים. הכוונה היא שזה יהיה שם של מערכת משנה, בדומה לשימוש ב-audio
או ב-telephony
. לא להשתמש
במונחים מעורפלים או עמוסים מדי כמו sys
, system
, dev
, default
או config
.
נהוג להשתמש בשם של סוג הדומיין של תהליך שיש לו גישת קריאה או כתיבה בלעדית למאפייני המערכת. לדוגמה, במאפייני המערכת שלתהליך vold
יש הרשאת כתיבה אליהם, נהוג להשתמש ב-vold
(שם סוג הדומיין של התהליך) כשם הקבוצה.
אם צריך, מוסיפים subgroup
כדי לסווג עוד יותר את הנכסים, אבל חשוב להימנע משימוש במונחים דו-משמעיים או עמוסים מדי לתיאור הרכיב הזה. (אפשר גם להוסיף יותר מsubgroup
אחד.)
הרבה שמות של קבוצות כבר הוגדרו. בודקים את הקובץ system/sepolicy/private/property_contexts
ומשתמשים בשמות קבוצות קיימים כשאפשר, במקום ליצור שמות חדשים. בטבלה הבאה מופיעות דוגמאות לשמות קבוצות נפוצים.
דומיין | קבוצה (וקבוצת משנה) |
---|---|
קשור ל-Bluetooth | bluetooth |
sysprops from kernel cmdline | boot |
מאפייני מערכת שמזהים גרסת build | build
|
קשור לטלפוניה | telephony |
אודיו קשור | audio |
תוכן שקשור לגרפיקה | graphics |
vold related | vold |
ההסבר הבא מתייחס לשימוש ב-name
וב-type
בדוגמה הקודמת לביטוי רגולרי.
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
מציין מאפיין מערכת בתוך קבוצה.
type
הוא רכיב אופציונלי שמבהיר את הסוג או הכוונה של מאפיין המערכת. לדוגמה, במקום לתת למאפיין מערכת שם כמוaudio.awesome_feature_enabled
או רקaudio.awesome_feature
, כדאי לשנות את השם שלו ל-audio.awesome_feature.enabled
כדי לשקף את סוג מאפיין המערכת והכוונה שלו.
אין כלל ספציפי לגבי הסוג, אבל אלה המלצות לשימוש:
-
enabled
: משתמשים בו אם הסוג הוא מאפיין מערכת בוליאני שמשמש להפעלה או להשבתה של תכונה. -
config
: משתמשים בו אם רוצים להבהיר שמאפיין המערכת לא מייצג מצב דינמי של המערכת, אלא ערך שהוגדר מראש (לדוגמה, דבר שניתן לקריאה בלבד). -
List
: משתמשים אם מדובר במאפיין מערכת שהערך שלו הוא רשימה. Timeoutmillis
: משתמשים בו אם מדובר במאפיין מערכת של ערך פסק זמן ביחידות של אלפיות השנייה.
לדוגמה:
persist.radio.multisim.config
drm.service.enabled
הקשר של הנכס
הסכימה החדשה של הקשר המאפיינים של SELinux מאפשרת גרנולריות מדויקת יותר ושמות תיאוריים יותר. בדומה למה שמשמש לשמות של נכסים, ב-AOSP מומלץ להשתמש בפורמט הבא:
{group}[_{subgroup}]*_prop
המונחים מוגדרים כך:
ל-group
ול-subgroup
יש אותה משמעות כמו זו שהוגדרה עבור הביטוי הרגולרי לדוגמה הקודם. לדוגמה, vold_config_prop
מציין מאפיינים שהם הגדרות מספק, והם מיועדים להגדרה על ידי vendor_init
, בעוד ש-vold_status_prop
או רק vold_prop
מציינים מאפיינים שמיועדים לחשיפת הסטטוס הנוכחי של vold
.
כשנותנים שם להקשר של נכס, כדאי לבחור שמות שמשקפים את השימוש הכללי במאפיינים. בפרט, צריך להימנע מסוגי המונחים הבאים:
- מונחים שנראים כלליים מדי ומעורפלים, כמו
sys
,system
,default
. - מונחים שמקודדים ישירות את הנגישות: כמו
exported
, apponly
,ro
, public
, private
.
עדיף להשתמש בשמות כמו vold_config_prop
במקום exported_vold_prop
או vold_vendor_writable_prop
.
סוג
סוג הנכס יכול להיות אחד מהסוגים שמפורטים בטבלה.
סוג | הגדרה |
---|---|
בוליאני | true או 1 לערך True, false או 0 לערך False |
מספר שלם | מספר שלם ב-64 ביט עם סימן |
מספר שלם לא מסומן | מספר שלם לא מסומן ב-64 ביט |
כפול | נקודה צפה (floating-point) בדיוק כפול |
מחרוזת | כל מחרוזת תקינה בקידוד UTF-8 |
enum | הערכים יכולים להיות כל מחרוזת תקינה בקידוד UTF-8 ללא רווחים לבנים |
רשימה של האפשרויות שלמעלה | משתמשים בפסיק (, ) כמפרידרשימת המספרים השלמים [1, 2, 3] מאוחסנת כ-1,2,3 |
באופן פנימי, כל המאפיינים מאוחסנים כמחרוזות. אפשר לאכוף את הסוג על ידי ציון שלו כקובץ property_contexts
. מידע נוסף זמין במאמר property_contexts
בקטע שלב 3.
שלב 2: קובעים את רמות הנגישות הנדרשות
יש ארבעה פקודות מאקרו של עזרה שמגדירות מאפיין.
סוג הנגישות | משמעות |
---|---|
system_internal_prop |
מאפיינים שמשמשים רק ב-/system |
system_restricted_prop |
מאפיינים שנקראים מחוץ ל-/system , אבל לא נכתבים |
system_vendor_config_prop |
מאפיינים שנקראים מחוץ ל-/system ונכתבים רק על ידי vendor_init |
system_public_prop |
מאפיינים שנקראים ונכתבים מחוץ ל-/system |
צריך לצמצם את היקף הגישה למאפייני המערכת ככל האפשר. בעבר, גישה רחבה מדי הובילה לשגיאות באפליקציות ולנקודות חולשה באבטחה. כדאי לשקול את השאלות הבאות כשמגדירים את ההיקף:
- האם צריך לשמור את מאפיין המערכת הזה? (אם כן, למה?)
- לאיזה תהליך צריכה להיות גישת קריאה לנכס הזה?
- לאיזה תהליך צריכה להיות הרשאת כתיבה לנכס הזה?
אפשר להשתמש בשאלות שלמעלה ובתרשים הבא של עץ ההחלטות כדי לקבוע את היקף הגישה המתאים.
איור 1. עץ החלטות לקביעת היקף הגישה למאפייני המערכת
שלב 3: מוסיפים למערכת או ל-sepolicy
כשניגשים ל-sysprop, SELinux שולט בנגישות של תהליכים. אחרי שקובעים את רמת הנגישות הנדרשת, מגדירים את הקשרים של הנכסים בקטע system/sepolicy
, יחד עם כללי allow ו-neverallow נוספים לגבי מה התהליכים יכולים (ולא יכולים) לקרוא או לכתוב.
קודם כול, מגדירים את הקשר של המאפיין בקובץ system/sepolicy/public/property.te
. אם המאפיין הוא פנימי למערכת, מגדירים אותו בקובץ system/sepolicy/private/property.te
. משתמשים באחד מפקודות המאקרו system_[accessibility]_prop([context])
שמספקות את הנגישות הנדרשת למאפיין המערכת. דוגמה לקובץ system/sepolicy/public/property.te
:
system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)
דוגמה לתוכן שמוסיפים לקובץ system/sepolicy/private/property.te
:
system_internal_prop(audio_baz_prop)
בשלב השני, מעניקים גישת קריאה ו (או) כתיבה להקשר של הנכס. משתמשים בפקודות מאקרו set_prop
ו-get_prop
כדי להעניק גישה, בקובץ system/sepolicy/public/{domain}.te
או בקובץ system/sepolicy/private/{domain}.te
. מומלץ להשתמש ב-private
כשאפשר. public
מתאים רק אם פקודת המאקרו set_prop
או get_prop
משפיעה על דומיינים מחוץ לדומיין הליבה.
דוגמה בקובץ system/sepolicy/private/audio.te
:
set_prop(audio, audio_foo_prop)
set_prop(audio, audio_bar_prop)
דוגמה בקובץ system/sepolicy/public/domain.te
:
get_prop(domain, audio_bar_prop)
בשלב השלישי, מוסיפים כמה כללי neverallow כדי להפחית עוד יותר את הנגישות שמוגדרת על ידי המאקרו. לדוגמה, נניח שהשתמשתם ב-system_restricted_prop
כי תהליכי הספק צריכים לקרוא את מאפייני המערכת. אם גישת הקריאה לא נדרשת לכל התהליכים של הספק, אלא רק לקבוצה מסוימת של תהליכים (כמו vendor_init
), צריך לאסור את התהליכים של הספק שלא נדרשת להם גישת קריאה.
כדי להגביל את הגישה לקריאה ולכתיבה, משתמשים בתחביר הבא:
כדי להגביל את גישת הכתיבה:
neverallow [domain] [context]:property_service set;
כדי להגביל את גישת הקריאה:
neverallow [domain] [context]:file no_rw_file_perms;
אם כלל neverallow קשור לדומיין ספציפי, צריך להציב אותו בקובץ system/sepolicy/private/{domain}.te
. כדי להשתמש בכללי neverallow רחבים יותר, צריך להשתמש בדומיינים כלליים כמו אלה בכל מקום שמתאים:
system/sepolicy/private/property.te
system/sepolicy/private/coredomain.te
system/sepolicy/private/domain.te
בקובץ system/sepolicy/private/audio.te
, מוסיפים את השורות הבאות:
neverallow {
domain -init -audio
} {audio_foo_prop audio_bar_prop}:property_service set;
בקובץ system/sepolicy/private/property.te
, מוסיפים את השורות הבאות:
neverallow {
domain -coredomain -vendor_init
} audio_prop:file no_rw_file_perms;
הערה: {domain -coredomain}
מתעד את כל התהליכים של הספק. לכן
{domain -coredomain -vendor_init}
פירושו "כל התהליכים של הספק למעט
vendor_init
".
לבסוף, משייכים נכס מערכת להקשר של הנכס. כך מוודאים שהגישה שניתנת וכללי neverallow שמוחלים על הקשרים של הנכסים יחולו על נכסים בפועל. כדי לעשות זאת, מוסיפים רשומה לקובץ property_contexts
, קובץ שמתאר מיפוי בין מאפייני המערכת לבין הקשרים של המאפיינים. בקובץ הזה אפשר לציין נכס יחיד או קידומת של נכסים למיפוי בהקשר מסוים.
זה התחביר למיפוי של נכס יחיד:
[property_name] u:object_r:[context_name]:s0 exact [type]
זהו התחביר למיפוי קידומת:
[property_name_prefix] u:object_r:[context_name]:s0 prefix [type]
אפשר גם לציין את סוג הנכס, שיכול להיות אחד מהסוגים הבאים:
bool
int
uint
double
enum [list of possible values...]
-
string
(משתמשים ב-string
בשביל מאפייני רשימה).
חשוב לוודא שלכל רשומה יש את הסוג המיועד שלה, כי type
נאכף כשמגדירים את property
. בדוגמה הבאה אפשר לראות איך כותבים מיפוי:
# 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
אם יש התנגשות בין רשומה מדויקת לרשומה עם קידומת, הרשומה המדויקת מקבלת עדיפות. דוגמאות נוספות זמינות במאמר system/sepolicy/private/property_contexts
.
שלב 4: קובעים את דרישות היציבות
יציבות היא היבט נוסף של מאפייני המערכת, והיא שונה מנגישות. יציבות היא היכולת של מאפיין מערכת להשתנות (לדוגמה, לשנות את השם או אפילו להסיר אותו) בעתיד. זה חשוב במיוחד כי מערכת ההפעלה Android הופכת למודולרית. עם Treble, אפשר לעדכן את מחיצות המערכת, הספק והמוצר באופן עצמאי. ב-Mainline, חלקים מסוימים במערכת ההפעלה מודולריים כמודולים שאפשר לעדכן (ב-APEX או ב-APK).
אם מאפיין מערכת מיועד לשימוש בחלקים של תוכנה שאפשר לעדכן, למשל במחיצות של המערכת והספק, הוא צריך להיות יציב. עם זאת, אם הוא משמש רק בתוך מודול ספציפי של Mainline, למשל, אפשר לשנות את השם, הסוג או ההקשרים של המאפיין, ואפילו להסיר אותו.
כדי לקבוע את היציבות של מאפיין מערכת, כדאי לשאול את השאלות הבאות:
- האם מאפיין המערכת הזה מיועד להגדרה על ידי שותפים (או להגדרה שונה לכל מכשיר)? אם כן, היא צריכה להיות יציבה.
- האם מאפיין המערכת הזה שמוגדר ב-AOSP מיועד לכתיבה או לקריאה מקוד (לא מתהליך) שקיים במחיצות שאינן מערכתיות, כמו
vendor.img
אוproduct.img
? אם כן, היא צריכה להיות יציבה. - האם יש גישה לנכס המערכת הזה במודולים של Mainline או במודול Mainline ובחלק של הפלטפורמה שלא ניתן לעדכן? אם כן, היא צריכה להיות יציבה.
כדי להשתמש במאפייני המערכת היציבים, צריך להגדיר כל אחד מהם כ-API ולהשתמש ב-API כדי לגשת למאפיין המערכת, כמו שמוסבר בשלב 6.
שלב 5: הגדרת מאפיינים בזמן הבנייה
הגדרת מאפיינים בזמן ה-build באמצעות משתני makefile. מבחינה טכנית, הערכים מוטמעים ב-{partition}/build.prop
. לאחר מכן, init
כדי להגדיר את המאפיינים.{partition}/build.prop
יש שני סטים של משתנים כאלה: PRODUCT_{PARTITION}_PROPERTIES
ו-TARGET_{PARTITION}_PROP
.
PRODUCT_{PARTITION}_PROPERTIES
מכיל רשימה של ערכי מאפיינים. התחביר הוא {prop}={value}
או {prop}?={value}
.
{prop}={value}
היא מטלה רגילה שמוודאת שהערך של {prop}
הוא {value}
. אפשר להגדיר רק מטלה אחת כזו לכל נכס.
{prop}?={value}
היא מטלה אופציונלית; הערך {prop}
מוגדר ל-{value}
רק אם אין מטלות {prop}={value}
. אם יש כמה הקצאות אופציונליות, ההקצאה הראשונה היא זו שתקבע.
# 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
מכיל רשימת קבצים, שמועברת ישירות אל {partition}/build.prop
. כל קובץ מכיל רשימה של זוגות {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
פרטים נוספים זמינים במאמר build/make/core/sysprop.mk
.
שלב 6: גישה למאפיינים בזמן ריצה
אפשר לקרוא ולכתוב מאפיינים בזמן הריצה.
סקריפטים של init
קבצים של סקריפט init (בדרך כלל קבצים מסוג *.rc) יכולים לקרוא מאפיין באמצעות ${prop}
או ${prop:-default}
, להגדיר פעולה שמופעלת בכל פעם שמאפיין מקבל ערך ספציפי, ולכתוב את המאפיינים באמצעות הפקודה 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}
פקודות Shell getprop ו-setprop
אפשר להשתמש בפקודות getprop
או setprop
של מעטפת הפקודות כדי לקרוא או לכתוב את המאפיינים. לפרטים נוספים, אפשר להפעיל את getprop --help
או את setprop --help
.
$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0
Sysprop as API for C++/Java/Rust
עם sysprop כ-API, אפשר להגדיר מאפייני מערכת ולהשתמש ב-API שנוצר אוטומטית, שהוא קונקרטי ומוקלד. הגדרת scope
עם Public
גם מאפשרת למודולים לגשת לממשקי API שנוצרו מעבר לגבולות, ומבטיחה יציבות של ממשקי ה-API. דוגמה לקובץ .sysprop
, למודול Android.bp
ולקוד C++, Java ו-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);
מידע נוסף זמין במאמר הטמעה של מאפייני מערכת כממשקי API.
פונקציות ושיטות של נכסים ברמה נמוכה בשפות C/C++, Java ו-Rust
כשאפשר, מומלץ להשתמש ב-Sysprop כ-API, גם אם יש לכם גישה לפונקציות C/C++ או Rust ברמה נמוכה או לשיטות Java ברמה נמוכה.
libc
, libbase
ו-libcutils
מציעים פונקציות של מאפייני מערכת C++. libc
היא פונקציית ה-API הבסיסית, והפונקציות libbase
ו-libcutils
הן פונקציות wrapper. אם אפשר, כדאי להשתמש בפונקציות libbase
sysprop כי הן הכי נוחות, וקובצי הפעלה של מארחים יכולים להשתמש בפונקציות libbase
. פרטים נוספים זמינים במאמרים sys/system_properties.h
(libc
), android-base/properties.h
(libbase
) וcutils/properties.h
(libcutils
).
במחלקת android.os.SystemProperties
יש שיטות של מאפייני מערכת Java.
מודול rustutils::system_properties
מציע פונקציות וסוגים של מאפייני מערכת Rust.
נספח: הוספת מאפיינים ספציפיים לספק
שותפים (כולל עובדי Google שעובדים בהקשר של פיתוח Pixel) רוצים להגדיר מאפייני מערכת ספציפיים לחומרה (או ספציפיים למכשיר).
מאפיינים ספציפיים לספק הם מאפיינים בבעלות השותף שייחודיים לחומרה או למכשיר שלו, ולא לפלטפורמה. מכיוון שהם תלויים בחומרה או במכשיר, הם מיועדים לשימוש במחיצות /vendor
או /odm
.
מאז Project Treble, מאפייני הפלטפורמה ומאפייני הספק פוצלו לחלוטין כדי למנוע התנגשויות ביניהם. בהמשך מוסבר איך מגדירים מאפייני ספק, ומפורטים מאפייני הספק שתמיד צריך להשתמש בהם.
מרחב שמות בשמות של נכסים והקשרים
כל מאפייני הספק צריכים להתחיל באחד מהקידומות הבאות כדי למנוע התנגשות בינם לבין המאפיינים של מחיצות אחרות.
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.
שימו לב, אפשר להשתמש ב-ro.hardware.
כקידומת, אבל רק לצורך תאימות.
אל תשתמשו בו בנכסים רגילים.
כל הדוגמאות הבאות משתמשות באחת מהקידומות שצוינו למעלה:
vendor.display.primary_red
persist.vendor.faceauth.use_disk_cache
ro.odm.hardware.platform
כל ההקשרים של מאפייני הספק חייבים להתחיל ב-vendor_
. הסיבה לכך היא גם תאימות. הנה כמה דוגמאות:
vendor_radio_prop
.vendor_faceauth_prop
.vendor_usb_prop
.
הספק אחראי לתת שמות למאפיינים ולתחזק אותם, ולכן צריך לפעול לפי הפורמט שמוצע בשלב 2, בנוסף לדרישות של מרחבי השמות של הספק.
כללי SEPolicy ספציפיים לספק ו-property_contexts
אפשר להגדיר מאפייני ספק באמצעות מאקרו vendor_internal_prop
. את הכללים הספציפיים לספק שאתם מגדירים, צריך לשמור בספרייה BOARD_VENDOR_SEPOLICY_DIRS
.
לדוגמה, נניח שאתם מגדירים מאפיין של אימות פנים של ספק ב-coral.
בקובץ BoardConfig.mk
(או בכל קובץ BoardConfig.mk
שכלול בו), מזינים את השורה הבאה:
BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy
בקובץ device/google/coral-sepolicy/private/property.te
, מוסיפים את השורות הבאות:
vendor_internal_prop(vendor_faceauth_prop)
בקובץ device/google/coral-sepolicy/private/property_contexts
, מוסיפים את השורות הבאות:
vendor.faceauth.trace u:object_r:vendor_faceauth_prop:s0 exact bool
המגבלות של מאפייני ספקים
מכיוון שמחיצות המערכת והמוצר לא יכולות להיות תלויות בספק, אסור לאפשר גישה למאפייני הספק מהמחיצות system
, system-ext
או product
.
נספח: שינוי השם של נכסים קיימים
אם אתם חייבים להוציא נכס משימוש ולעבור לנכס חדש, אתם יכולים להשתמש ב-Sysprop as APIs כדי לשנות את השם של הנכסים הקיימים. כדי לשמור על תאימות לאחור, צריך לציין גם את השם הקודם וגם את השם החדש של הנכס. בפרט, אפשר להגדיר את השם הקודם באמצעות השדה legacy_prop_name
בקובץ .sysprop
. ה-API שנוצר מנסה לקרוא את prop_name
, ומשתמש ב-legacy_prop_name
אם prop_name
לא קיים.
לדוגמה, השלבים הבאים משנים את השם awesome_feature_foo_enabled
ל-foo.awesome_feature.enabled
.
בקובץ 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"
}
בקוד 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);
חשוב לשים לב להערות הבאות:
קודם כל, אי אפשר לשנות את הסוג של מאפיין המערכת. לדוגמה, אי אפשר להפוך מאפיין
int
למאפייןstring
. אפשר רק לשנות את השם.שנית, רק ה-API לקריאה חוזר לשם הקודם. ה-API לכתיבה לא מבצע חזרה. אם מאפיין המערכת ניתן לכתיבה, אי אפשר לשנות את השם שלו.