בדף הזה מוצגת שיטה קנונית להוספה או להגדרה של מאפייני מערכת ב-Android, עם הנחיות לארגון הקוד מחדש של מאפייני המערכת הקיימים. הקפידו להשתמש בהנחיות כשאתם מבצעים את ארגון הקוד מחדש, אלא אם יש לכם בעיית תאימות חזקה שגורמת לבעיה אחרת.
שלב 1: מגדירים את מאפיין המערכת
כשאתם מוסיפים מאפיין מערכת, אתם צריכים לבחור שם לנכס ולשייך אותו להקשר של נכס SELinux. אם אין הקשר קיים מתאים, יוצרים הקשר חדש. משתמשים בשם הזה כשניגשים לנכס. ההקשר של המאפיין משמש לשליטה בנגישות במונחים של SELinux. השמות יכולים להיות כל מחרוזת, אבל AOSP ממליץ להשתמש בפורמט מובנה כדי שיהיה ברור.
שם המאפיין
צריך להשתמש בפורמט הזה עם אותיות רישיות [snake_case]:
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
השתמשו ב-"" (הושמט), ב-ro
(למאפיינים שמוגדרים פעם אחת בלבד) או ב-persist
(למאפיינים שנמשכים בכל ההפעלות מחדש) עבור הרכיב prefix
.
נקודות שצריך לשים לב אליהן:
כדאי להשתמש ב-ro
רק כשאתם בטוחים שלא תצטרכו להשתמש ב-prefix
כדי שיהיה אפשר לכתיבה בעתיד. ** אין לציין את הקידומת ro
.** במקום זאת, הסתמך על מדיניות כדי להגדיר את 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 |
syspros מ-kernel של cmdline | boot |
מערכות build שמזהים גרסת build | build
|
קשור לטלפוניה | telephony |
קשורים לאודיו | audio |
קשורים לגרפיקה | graphics |
קשור ל-vold | vold |
בהמשך מוגדר השימוש ב-name
וב-type
בדוגמה הקודמת של ביטוי רגולרי.
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
מזהה נכס מערכת בקבוצה.type
הוא רכיב אופציונלי שמבהיר את הסוג או הכוונה של מאפיין המערכת. לדוגמה, במקום לתת ל-syspro את השםaudio.awesome_feature_enabled
או רקaudio.awesome_feature
, צריך לשנות את השם ל-audio.awesome_feature.enabled
כדי לשקף את הסוג ואת Intent של המערכת.
אין כלל ספציפי לגבי הסוג צריך להיות, אלה המלצות לשימוש:
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
.
Type
סוג הנכס יכול להיות אחת מהאפשרויות הבאות, כפי שמפורט בטבלה.
Type | הגדרה |
---|---|
ערך בוליאני | true או 1 לציון True, false או 0 ל-False |
מספר שלם | מספר שלם חתום של 64 ביט |
מספר שלם לא חתום | מספר שלם לא חתום מסוג 64 ביט |
כפול | נקודה צפה בדיוק כפול |
מחרוזת | כל מחרוזת 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: הוספה למערכת/למדיניות
בעת גישה ל-syspro, SELinux שולט בנגישות של תהליכים. אחרי שקובעים את רמת הנגישות הנדרשת, מגדירים הקשרים בנכס בקטע system/sepolicy
, יחד עם כללי Allow ואף פעם נוספים לגבי קריאה או כתיבה של תהליכים.
קודם כול מגדירים את ההקשר של הנכס בקובץ 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)
שלישית, אפשר להוסיף כמה כללים אף פעם כדי לצמצם עוד יותר את הנגישות שתתפרס על ידי המאקרו. לדוגמה, נניח שהשתמשתם ב-system_restricted_prop
כי תהליכים של ספקים צריכים לקרוא את מאפייני המערכת. אם לא נדרשת גישת קריאה מכל התהליכים של הספקים, והיא נדרשת רק על ידי קבוצה מסוימת של תהליכים (כמו vendor_init
), צריך לאסור על תהליכי הספק שלא זקוקים להרשאת קריאה.
צריך להשתמש בתחביר הבא כדי להגביל גישת כתיבה וקריאה:
כדי להגביל את גישת הכתיבה:
neverallow [domain] [context]:property_service set;
כדי להגביל את גישת הקריאה:
neverallow [domain] [context]:file no_rw_file_perms;
אם הכלל אף פעם לא קשור לדומיין ספציפי, צריך לכלול כללים של אף פעם בקובץ system/sepolicy/private/{domain}.te
. ובכללים ללא הרשאה, כדאי להשתמש בדומיינים כלליים כמו במקרים הרלוונטיים:
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
."
לבסוף, משייכים נכס מערכת להקשר של הנכס. כך ניתן לוודא שהגישה שמוענקת והכללים של אף פעם שמוחלים על הקשרים של נכסים יחולו על הנכסים בפועל. כדי לעשות זאת, מוסיפים רשומה לקובץ 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 OS הופכת למודולרית. באמצעות טרבל אפשר לעדכן את מחיצות המערכת, הספק והמוצרים בנפרד. ב-Mainline, חלקים מסוימים של מערכת ההפעלה מודולריים כמודולים שניתנים לעדכון (ב-APEX או ב-APK).
אם מאפיין מערכת מיועד לשימוש בכל קטעי תוכנה ניתנים לעדכון, לדוגמה, במחיצות בין מערכות וספקים, הוא חייב להיות יציב. עם זאת, אם משתמשים בו רק בתוך, למשל, מודול ראשי ספציפי, אפשר לשנות את השם, הסוג או ההקשרי המאפיין שלו, ואפילו להסיר אותו.
כדי לקבוע את היציבות של נכס מערכת, צריך לשאול את השאלות הבאות:
- האם נכס המערכת הזה מיועד להגדרה על ידי שותפים (או להגדרה שונה לפי מכשיר)? אם כן, המכשיר צריך להיות יציב.
- האם מאפיין המערכת הזה, שמוגדר ל-AOSP, מיועד להיכתב בקוד (לא עיבוד) או לקרוא אותו במחיצות שלא נמצאות במחיצות של המערכת כמו
vendor.img
אוproduct.img
? אם כן, המכשיר צריך להיות יציב. - האם מתבצעת גישה לנכס המערכת הזה דרך מודולים של Minline או דרך מודול ראשי ושל החלק שלא ניתן לעדכון? אם כן, המכשיר צריך להיות יציב.
בשביל מאפייני המערכת היציבים, צריך להגדיר כל אחד מהם באופן רשמי כ-API ולהשתמש ב-API כדי לגשת למאפיין המערכת, כפי שמוסבר בשלב 6.
שלב 5: הגדרת נכסים בזמן ה-build
הגדרה של מאפיינים בזמן ה-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 (בדרך כלל קובצי *.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}
פקודות מעטפת מסוג getpromo ו-setpro
אפשר להשתמש בפקודות המעטפת getprop
או setprop
, בהתאמה, כדי לקרוא או לכתוב את המאפיינים. לפרטים נוספים, אפשר להפעיל את getprop --help
או setprop --help
.
$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0
Syspro כ-API עבור C++/Java/Rust
באמצעות syspro כ-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.
פונקציות ו-methods של נכסים ברמה נמוכה של C/C++ , Java ו-Rust
כשאפשר, כדאי להשתמש ב-Syspr כ-API, למרות שאפשר להשתמש בפונקציות C/C++ או Rust ברמה נמוכה, או בשיטות Java ברמה נמוכה.
libc
, libbase
ו-libcutils
מציעים פונקציות של מאפייני מערכת C++. ל-libc
יש את ה-API הבסיסי, והפונקציות libbase
ו-libcutils
הן רכיבי wrapper. אם זה אפשרי, צריך להשתמש בפונקציות ה-syspro של libbase
. הן הנוחות ביותר, והקבצים הבינאריים של המארח יכולים להשתמש בפונקציות libbase
. לפרטים נוספים: sys/system_properties.h
(libc
), android-base/properties.h
(libbase
) ו-cutils/properties.h
(libcutils
).
המחלקה android.os.SystemProperties
מציעה שיטות של מאפייני מערכת Java.
המודול rustutils::system_properties
כולל פונקציות וסוגים של מאפייני מערכת Rust.
נספח: הוספת נכסים ספציפיים לספק
שותפים (כולל גוגלרים שעובדים בהקשר של פיתוח 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, בנוסף לדרישות לגבי מרחבי השמות של הספקים.
כללים ו-property_contexts הספציפיים לספק
אפשר להגדיר את מאפייני הספק באמצעות פקודת המאקרו vendor_internal_prop
. שומרים בספרייה BOARD_VENDOR_SEPOLICY_DIRS
את הכללים הספציפיים לספק שהגדרתם.
לדוגמה, נניח שאתם מגדירים נכס Faceauth של ספק בצבע אלמוג.
בקובץ 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
.
נספח: שינוי השם של נכסים קיימים
כשצריך להוציא משימוש נכס ולעבור לנכס חדש, אפשר להשתמש ב-Sysפרו כממשקי API כדי לשנות את השם של הנכסים הקיימים. כך אפשר לשמור על תאימות לאחור על ידי ציון השם הקודם וגם שם הנכס החדש. באופן ספציפי, אפשר להגדיר את השם מהדור הקודם באמצעות השדה 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);
שימו לב לאזהרות הבאות:
ראשית, לא ניתן לשנות את סוג ה-syspro. לדוגמה, אי אפשר להפוך מאפיין
int
לאובייקטstring
, אלא רק לשנות את השם שלו.שנית, רק ה-API של Read Along חוזר לשם הקודם. ה-API לכתיבה לא נעלם. אם ה-syspro ניתן לכתיבה, לא ניתן לשנות את שמו.