הוספת מאפייני מערכת

בדף הזה מוצגת שיטה קנונית להוספה או להגדרה של מאפייני מערכת ב-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 ניתן לכתיבה, לא ניתן לשנות את שמו.