افزودن دارایی‌های سیستم

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

مرحله ۱: تعریف کردن دارایی سیستم

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

نام دارایی

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

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

برای عنصر prefix، از «» (حذف‌شده)، ro (برای دارایی‌هایی که فقط یک‌بار تنظیم می‌شوند)، یا persist (برای دارایی‌هایی که پس‌از بازراه‌اندازی حفظ می‌شوند) استفاده کنید.

ملاحظات

فقط زمانی از 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
sysprops از خط فرمان هسته boot
sysprops که نسخه ساخت را شناسایی می‌کند build
مرتبط با تلفن telephony
مرتبط با صوت audio
مرتبط با گرافیک graphics
مربوط به vold vold

در مثال regex قبلی، از name و type به این صورت استفاده شده است.

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

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

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

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

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

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

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

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

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

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

درخت تصمیم برای تعیین محدوده دسترسی

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

مرحله ۳: افزودن به سیستم/sepolicy

هنگام دسترسی به sysprop،‏ SELinux دسترس‌پذیری فرایندها را کنترل می‌کند. پس‌از تعیین سطح دسترسی‌پذیری موردنیاز، زمینه‌های ویژگی را در system/sepolicy، به‌همراه قوانین مجاز و غیرمجاز اضافی درباره اینکه فرایندها مجاز به خواندن یا نوشتن چه چیزهایی هستند (و نیستند) تعریف کنید.

ابتدا، بافت دارایی را در فایل 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 برای دارایی‌های فهرست استفاده کنید.)

مطمئن شوید که هر ورودی درصورت امکان نوع تعیین‌شده خود را داشته باشد، زیرا هنگام تنظیم property، type اعمال می‌شود مثال زیر نحوه نوشتن نگاشت را نشان می‌دهد:

# 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 مراجعه کنید.

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

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

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

برای تعیین پایداری دارایی سیستم، سؤالات زیر را بپرسید:

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

برای دارایی‌های سیستم پایدار، هریک را به‌طور رسمی به‌عنوان «میانای برنامه‌سازی کاربردی» تعریف کنید و از «میانای برنامه‌سازی کاربردی» برای دسترسی به دارایی سیستم استفاده کنید، همان‌طور که در مرحله ۶ توضیح داده شده است.

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

ویژگی‌ها را در زمان ساخت با متغیرهای 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 برای خواندن یا نوشتن ویژگی‌ها استفاده کنید. برای جزئیات بیشتر، getprop --help یا setprop --help را فراخوانی کنید.

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

‫Sysprop به‌عنوان میانای برنامه‌سازی کاربردی برای C++/Java/Rust

با sysprop به‌عنوان API، می‌توانید ویژگی‌های سیستم را تعریف کنید و از API تولیدشده خودکار که عینی و تایپ‌شده است استفاده کنید. تنظیم scope با Public همچنین باعث می‌شود میاناهای برنامه‌سازی کاربردی تولیدشده برای ماژول‌ها در سراسر مرزها دردسترس باشند و پایداری میانای برنامه‌سازی کاربردی را تضمین می‌کند. در اینجا نمونه‌ای از فایل .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);

برای اطلاعات بیشتر، پیاده‌سازی دارایی‌های سیستم به‌عنوان میاناهای برنامه‌سازی کاربردی را ببینید.

توابع و روش‌های سطح پایین ویژگی C/C++‎،‏ Java، و Rust

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

‫libc،‏ libbase، و libcutils توابع دارایی سیستم C++ را ارائه می‌دهند. libcمیانای برنامه‌سازی کاربردی زیربنایی را دارد، درحالی‌که تابع‌های libbase و libcutils پوشش هستند. اگر امکان‌پذیر است، از توابع sysprop libbase استفاده کنید؛ این توابع راحت‌ترین هستند و باینری‌های میزبان می‌توانند از توابع 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 استفاده شوند.

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

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

قوانین SEPolicy مختص فروشنده و property_contexts

ویژگی‌های فروشنده را می‌توان با 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، system-ext، یا product به دارایی‌های فروشنده دسترسی پیدا شود.

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

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

  • دوم، فقط «میانای برنامه کاربردی خواندن» به نام قدیمی برمی‌گردد. میانای برنامه‌سازی کاربردی نوشتن بازگشت ندارد. اگر sysprop نوشتنی باشد، نمی‌توانید نام آن را تغییر دهید.