ویژگی های سیستم را اضافه کنید

این صفحه یک روش استاندارد برای اضافه کردن یا تعریف ویژگی‌های سیستم در اندروید، به همراه دستورالعمل‌هایی برای بازسازی ویژگی‌های سیستم موجود ارائه می‌دهد. هنگام بازسازی، مطمئن شوید که از دستورالعمل‌ها استفاده می‌کنید، مگر اینکه مشکل سازگاری شدیدی داشته باشید که خلاف آن را ایجاب کند.

مرحله ۱: تعریف ویژگی سیستم

وقتی یک ویژگی سیستمی اضافه می‌کنید، نامی برای آن ویژگی انتخاب کنید و آن را به یک زمینه ویژگی SELinux مرتبط کنید. اگر زمینه مناسبی وجود ندارد، یک زمینه جدید ایجاد کنید. نام هنگام دسترسی به ویژگی استفاده می‌شود؛ زمینه ویژگی برای کنترل دسترسی از نظر SELinux استفاده می‌شود. نام‌ها می‌توانند هر رشته‌ای باشند، اما AOSP توصیه می‌کند که برای واضح بودن آنها، از یک قالب ساختاریافته پیروی کنید.

نام ملک

از این قالب با پوشش snake_case استفاده کنید:

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

برای prefix عنصر، از "" (حذف شده)، ro (برای ویژگی‌هایی که فقط یک بار تنظیم می‌شوند) یا persist (برای ویژگی‌هایی که در طول راه‌اندازی مجدد سیستم باقی می‌مانند) استفاده کنید.

هشدارها

فقط زمانی ro استفاده کنید که مطمئن هستید برای قابل نوشتن بودن در آینده به prefix نیازی ندارید. ** پیشوند ro را مشخص نکنید.** در عوض، برای اینکه prefix فقط خواندنی شود (به عبارت دیگر، فقط توسط init قابل نوشتن باشد) به sepolicy تکیه کنید.

فقط زمانی persist استفاده کنید که مطمئن هستید مقدار باید در طول راه‌اندازی‌های مجدد ثابت بماند، و استفاده از ویژگی‌های سیستم تنها گزینه شماست.

گوگل ویژگی‌های سیستمی که دارای ویژگی‌های ro یا persist هستند را به شدت بررسی می‌کند.

اصطلاح group برای تجمیع ویژگی‌های مرتبط استفاده می‌شود. این اصطلاح قرار است نام یک زیرسیستم مشابه با audio یا telephony باشد. از اصطلاحات مبهم یا بیش از حد معمول مانند sys ، system ، dev ، default یا config استفاده نکنید .

معمولاً از نام نوع دامنه‌ی فرآیندی که دسترسی انحصاری خواندن یا نوشتن به ویژگی‌های سیستم را دارد، استفاده می‌شود. به عنوان مثال، برای ویژگی‌های سیستمی که فرآیند vold به آنها دسترسی نوشتن دارد، معمولاً از vold (نام نوع دامنه برای فرآیند) به عنوان نام گروه استفاده می‌شود.

در صورت نیاز، برای دسته‌بندی بیشتر ویژگی‌ها، subgroup اضافه کنید، اما از اصطلاحات مبهم یا بیش از حد برای توصیف این عنصر خودداری کنید. (همچنین می‌توانید بیش از یک subgroup داشته باشید.)

بسیاری از نام‌های گروه از قبل تعریف شده‌اند. فایل system/sepolicy/private/property_contexts را بررسی کنید و در صورت امکان، به جای ایجاد نام‌های جدید، از نام‌های گروه‌های موجود استفاده کنید. جدول زیر نمونه‌هایی از نام‌های گروه‌های پرکاربرد را ارائه می‌دهد.

دامنه گروه (و زیرگروه)
مربوط به بلوتوث bluetooth
sysprops از cmdline هسته boot
sysprops که یک build را شناسایی می‌کنند build
مربوط به تلفن telephony
مرتبط با صدا audio
مرتبط با گرافیک graphics
مرتبط با جلد vold

موارد زیر نحوه‌ی استفاده از name و type را در مثال regex قبلی تعریف می‌کند.

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

  • name یک ویژگی سیستم را در یک گروه مشخص می‌کند.

  • type یک عنصر اختیاری است که نوع یا هدف ویژگی سیستم را مشخص می‌کند. برای مثال، به جای نامگذاری یک sysprop به صورت audio.awesome_feature_enabled یا فقط audio.awesome_feature ، نام آن را به audio.awesome_feature.enabled تغییر دهید تا نوع و هدف ویژگی سیستم را منعکس کند.

هیچ قانون خاصی در مورد نوع داده وجود ندارد؛ اینها توصیه‌های استفاده هستند:

  • enabled : اگر نوع یک ویژگی سیستمی از نوع بولی باشد که برای روشن یا خاموش کردن یک ویژگی استفاده می‌شود، از این گزینه استفاده کنید.
  • config : اگر قصد روشن کردن این نکته است که ویژگی سیستم نشان‌دهنده‌ی حالت پویای سیستم نیست ؛ بلکه نشان‌دهنده‌ی یک مقدار از پیش پیکربندی‌شده (مثلاً یک چیز فقط خواندنی) است، از این دستور استفاده کنید.
  • List : اگر یک ویژگی سیستمی است که مقدار آن یک لیست است، از آن استفاده کنید.
  • Timeoutmillis : اگر یک ویژگی سیستمی برای مقدار timeout بر حسب میلی‌ثانیه باشد، از آن استفاده کنید.

مثال‌ها:

  • 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 برای درست، false یا 0 برای نادرست
عدد صحیح عدد صحیح ۶۴ بیتی علامت‌دار
عدد صحیح بدون علامت عدد صحیح ۶۴ بیتی بدون علامت
دو برابر ممیز شناور با دقت مضاعف
رشته هر رشته معتبر UTF-8
شمارشی مقادیر می‌توانند هر رشته معتبر UTF-8 بدون فاصله باشند.
فهرست موارد فوق از کاما ( , ) به عنوان جداکننده استفاده می‌شود.
لیست اعداد صحیح [1, 2, 3] به صورت 1,2,3 ذخیره می‌شود.

در داخل، تمام ویژگی‌ها به صورت رشته ذخیره می‌شوند. می‌توانید با مشخص کردن آن به عنوان یک فایل property_contexts ، نوع را اعمال کنید. برای اطلاعات بیشتر، به property_contexts در مرحله 3 مراجعه کنید.

مرحله ۲: تعیین سطوح دسترسی مورد نیاز

چهار ماکروی کمکی وجود دارد که یک ویژگی را تعریف می‌کنند.

نوع دسترسی معنی
system_internal_prop ویژگی‌هایی که فقط در /system ‎ استفاده می‌شوند
system_restricted_prop ویژگی‌هایی که خارج از /system ‎ خوانده می‌شوند، اما نوشته نمی‌شوند.
system_vendor_config_prop ویژگی‌هایی که خارج از /system ‎ خوانده می‌شوند و فقط توسط vendor_init نوشته می‌شوند
system_public_prop ویژگی‌هایی که خارج از /system خوانده و نوشته می‌شوند

دسترسی به ویژگی‌های سیستم را تا حد امکان محدود کنید. در گذشته، دسترسی گسترده منجر به خرابی برنامه و آسیب‌پذیری‌های امنیتی شده است. هنگام تعیین محدوده، سوالات زیر را در نظر بگیرید:

  • آیا این ویژگی سیستمی نیاز به ذخیره دائمی دارد؟ (اگر چنین است، چرا؟)
  • کدام فرآیند باید دسترسی خواندن به این ویژگی را داشته باشد؟
  • کدام فرآیند باید دسترسی نوشتن روی این ویژگی را داشته باشد؟

از سوالات قبلی و درخت تصمیم زیر به عنوان ابزاری برای تعیین محدوده مناسب دسترسی استفاده کنید.

Decision tree for determining the scope of access

شکل ۱. درخت تصمیم برای تعیین محدوده دسترسی به ویژگی‌های سیستم

مرحله ۳: اضافه کردن به system/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 به یک دامنه خاص محدود شده است، قوانین 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 مراجعه کنید.

مرحله ۴: تعیین الزامات پایداری

پایداری جنبه‌ی دیگری از ویژگی‌های سیستم است و با دسترسی‌پذیری متفاوت است. پایداری به این موضوع مربوط می‌شود که آیا یک ویژگی سیستم می‌تواند در آینده تغییر کند (مثلاً تغییر نام دهد یا حتی حذف شود). این امر به ویژه با ماژولار شدن سیستم عامل اندروید اهمیت دارد. با Treble، پارتیشن‌های سیستم، فروشنده و محصول می‌توانند مستقل از یکدیگر به‌روزرسانی شوند. با Mainline، برخی از بخش‌های سیستم عامل به عنوان ماژول‌های قابل به‌روزرسانی (در APEXها یا APKها) ماژولار می‌شوند.

اگر یک ویژگی سیستمی برای استفاده در قطعات نرم‌افزاری قابل به‌روزرسانی، مثلاً در پارتیشن‌های سیستم و فروشنده، باشد، باید پایدار باشد. با این حال، اگر فقط در مثلاً یک ماژول خاص Mainline استفاده می‌شود، می‌توانید نام، نوع یا زمینه‌های ویژگی آن را تغییر دهید و حتی آن را حذف کنید.

برای تعیین پایداری یک ویژگی سیستم، سوالات زیر را بپرسید:

  • آیا این ویژگی سیستم قرار است توسط شرکا پیکربندی شود (یا برای هر دستگاه به طور متفاوتی پیکربندی شود)؟ اگر بله، باید پایدار باشد.
  • آیا این ویژگی سیستمی تعریف‌شده توسط AOSP قرار است در کدی (نه فرآیندی) که در پارتیشن‌های غیرسیستمی مانند vendor.img یا product.img وجود دارد، نوشته یا از آن خوانده شود؟ اگر بله، باید پایدار باشد.
  • آیا این ویژگی سیستم از طریق ماژول‌های Mainline یا از طریق یک ماژول Mainline و بخش غیرقابل به‌روزرسانی پلتفرم قابل دسترسی است؟ اگر بله، باید پایدار باشد.

برای ویژگی‌های سیستم پایدار، هر کدام را رسماً به عنوان یک API تعریف کنید و از API برای دسترسی به ویژگی سیستم، همانطور که در مرحله 6 توضیح داده شده است، استفاده کنید.

مرحله ۵: تنظیم ویژگی‌ها در زمان ساخت

ویژگی‌ها را در زمان ساخت با متغیرهای 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 مراجعه کنید.

مرحله ۶: دسترسی به ویژگی‌ها در زمان اجرا

ویژگی‌ها را می‌توان در زمان اجرا خواند و نوشت.

اسکریپت‌های اولیه

فایل‌های اسکریپت 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}

دستورات پوسته getprop و setprop

شما می‌توانید به ترتیب از دستورات getprop یا setprop shell برای خواندن یا نوشتن ویژگی‌ها استفاده کنید. برای جزئیات بیشتر، getprop --help یا setprop --help را فراخوانی کنید.

$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0

Sysprop به عنوان API برای 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++، جاوا و Rust

در صورت امکان، حتی اگر توابع سطح پایین C/C++ یا Rust یا متدهای سطح پایین جاوا در دسترس شما هستند، از Sysprop به عنوان API استفاده کنید.

libc ، libbase و libcutils توابع ویژگی سیستم C++ را ارائه می‌دهند. libc دارای API زیربنایی است، در حالی که توابع libbase و libcutils پوشش‌دهنده هستند. در صورت امکان، از توابع sysprop libbase استفاده کنید. آنها راحت‌ترین هستند و فایل‌های باینری میزبان می‌توانند از توابع libbase استفاده کنند. برای جزئیات بیشتر، به sys/system_properties.h ( libcandroid-base/properties.h ( libbase ) و cutils/properties.h ( libcutils ) مراجعه کنید.

کلاس android.os.SystemProperties متدهای مربوط به ویژگی‌های سیستمی جاوا را ارائه می‌دهد.

ماژول rustutils::system_properties توابع و انواع ویژگی‌های سیستم Rust را ارائه می‌دهد.

پیوست: افزودن ویژگی‌های مختص فروشنده

شرکا (از جمله گوگلی‌هایی که در زمینه توسعه پیکسل کار می‌کنند) می‌خواهند ویژگی‌های سیستم مختص سخت‌افزار (یا مختص دستگاه) را تعریف کنند. ویژگی‌های مختص فروشنده، ویژگی‌هایی متعلق به شریک هستند که منحصر به سخت‌افزار یا دستگاه خودشان هستند، نه مختص پلتفرم. از آنجایی که این ویژگی‌ها وابسته به سخت‌افزار یا دستگاه هستند، قرار است در پارتیشن‌های /vendor یا /odm استفاده شوند.

از زمان پروژه 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 .

مسئولیت نامگذاری و نگهداری ویژگی‌ها بر عهده فروشنده است، بنابراین علاوه بر الزامات فضاهای نام فروشنده، از قالب پیشنهادی در مرحله ۲ نیز پیروی کنید.

قوانین و property_contexts مربوط به SEPolicy فروشنده

ویژگی‌های فروشنده را می‌توان با استفاده از ماکرو vendor_internal_prop تعریف کرد. قوانین مختص فروشنده را که تعریف می‌کنید در دایرکتوری BOARD_VENDOR_SEPOLICY_DIRS قرار دهید. برای مثال، فرض کنید که در حال تعریف یک ویژگی faceauth فروشنده در نرم‌افزار 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 و product نمی‌توانند به vendor وابسته باشند، هرگز اجازه ندهید که از پارتیشن‌های system ، system-ext یا product به ویژگی‌های vendor دسترسی پیدا شود.

پیوست: تغییر نام ویژگی‌های موجود

وقتی مجبورید یک ویژگی را منسوخ کنید و به یک ویژگی جدید بروید، از Sysprop به عنوان API برای تغییر نام ویژگی‌های موجود خود استفاده کنید. این کار با مشخص کردن نام قدیمی و نام ویژگی جدید، سازگاری با نسخه‌های قبلی را حفظ می‌کند. به طور خاص، می‌توانید نام قدیمی را با فیلد legacy_prop_name در فایل .sysprop تنظیم کنید. API تولید شده سعی می‌کند prop_name بخواند و اگر prop_name وجود نداشته باشد، legacy_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);

به هشدارهای زیر توجه کنید:

  • اول اینکه، شما نمی‌توانید نوع sysprop را تغییر دهید. برای مثال، نمی‌توانید یک int prop را به string prop تبدیل کنید. فقط می‌توانید نام آن را تغییر دهید.

  • دوم، فقط API مربوط به خواندن به نام قدیمی برمی‌گردد. API مربوط به نوشتن به این نام برنمی‌گردد. اگر sysprop قابل نوشتن باشد، نمی‌توانید نام آن را تغییر دهید.