أضف خصائص النظام

توفر هذه الصفحة طريقة أساسية لإضافة أو تعريف خصائص النظام في Android، مع إرشادات لإعادة هيكلة خصائص النظام الحالية. تأكد من استخدام الإرشادات عند إعادة البناء، ما لم تكن لديك مشكلة توافق قوية تتطلب خلاف ذلك.

الخطوة 1: تحديد خاصية النظام

عند إضافة خاصية نظام، حدد اسمًا للخاصية، واربطها بسياق خاصية SELinux. إذا لم يكن هناك سياق حالي مناسب، فقم بإنشاء سياق جديد. يتم استخدام الاسم عند الوصول إلى العقار؛ يتم استخدام سياق الخاصية للتحكم في إمكانية الوصول من حيث SELinux. يمكن أن تكون الأسماء أي سلسلة، لكن AOSP توصي باتباع تنسيق منظم لجعلها واضحة.

اسم الخاصية

استخدم هذا التنسيق مع غلاف الثعبان:

[{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
sysprops من cmdline kernel boot
sysprops التي تحدد البناء build
المتعلقة بالهاتف telephony
المتعلقة بالصوت audio
الرسومات ذات الصلة graphics
فولد ذات الصلة vold

يحدد ما يلي استخدام 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 لهما نفس المعنى كما هو محدد في نموذج regex السابق. على سبيل المثال، تشير 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 لخطأ
عدد صحيح وقعت عددا صحيحا 64 بت
عدد صحيح غير موقعة عدد صحيح 64 بت غير موقعة
مزدوج نقطة عائمة مزدوجة الدقة
خيط أي سلسلة UTF-8 صالحة
التعداد يمكن أن تكون القيم أي سلسلة 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

قم بنطاق الوصول إلى خصائص النظام بأكبر قدر ممكن. في الماضي، أدى الوصول الواسع النطاق إلى تعطل التطبيقات ونقاط الضعف الأمنية. ضع في اعتبارك الأسئلة التالية عند تحديد النطاق:

  • هل تحتاج خاصية النظام هذه إلى الاستمرار؟ (إذا كان الأمر كذلك لماذا؟)
  • ما هي العملية التي يجب أن يكون لها حق الوصول للقراءة إلى هذه الخاصية؟
  • ما هي العملية التي يجب أن يكون لها حق الوصول للكتابة إلى هذه الخاصية؟

استخدم الأسئلة السابقة وشجرة القرار التالية كأدوات لتحديد النطاق المناسب للوصول.

Decision tree for determining the scope of access

الشكل 1. شجرة القرار لتحديد نطاق الوصول إلى خصائص النظام

الخطوة 3: إضافته إلى النظام/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)

ثالثًا، أضف بعض قواعد عدم السماح أبدًا لتقليل إمكانية الوصول التي تم تحديد نطاقها بواسطة الماكرو. على سبيل المثال، افترض أنك استخدمت 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 مرتبطة بمجال معين. بالنسبة لقواعد 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 ."

وأخيرًا، قم بربط خاصية النظام بسياق الخاصية. وهذا يضمن أن الوصول الممنوح وقواعد عدم السماح المطبقة على سياقات الخاصية يتم تطبيقها على الخصائص الفعلية. للقيام بذلك، قم بإضافة إدخال إلى ملف 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 .

الخطوة الرابعة: تحديد متطلبات الاستقرار

الاستقرار هو جانب آخر من خصائص النظام، وهو يختلف عن إمكانية الوصول. يتعلق الاستقرار بإمكانية تغيير خاصية النظام (على سبيل المثال إعادة تسميتها أو حتى إزالتها) في المستقبل أم لا. وهذا مهم بشكل خاص حيث أصبح نظام التشغيل Android معياريًا. باستخدام Treble، يمكن تحديث أقسام النظام والبائعين والمنتج بشكل مستقل عن بعضها البعض. مع Mainline، يتم تقسيم بعض أجزاء نظام التشغيل إلى وحدات نمطية قابلة للتحديث (في APEXes أو ملفات APK).

إذا كانت خاصية النظام مخصصة للاستخدام عبر أجزاء من البرامج قابلة للتحديث، على سبيل المثال عبر أقسام النظام والموردين، فيجب أن تكون مستقرة. ومع ذلك، إذا تم استخدامه فقط، على سبيل المثال، ضمن وحدة Mainline محددة، فيمكنك تغيير اسمها أو نوعها أو سياقات خصائصها، بل وحتى إزالتها.

اطرح الأسئلة التالية لتحديد مدى استقرار خاصية النظام:

  • هل تم تصميم خاصية النظام هذه ليتم تكوينها بواسطة الشركاء (أو يتم تكوينها بشكل مختلف لكل جهاز)؟ إذا كانت الإجابة بنعم، فيجب أن تكون مستقرة.
  • هل المقصود من خاصية النظام المحددة بواسطة AOSP أن تتم كتابتها أو قراءتها من التعليمات البرمجية (وليست العملية) الموجودة في الأقسام غير التابعة للنظام مثل vendor.img أو product.img ؟ إذا كانت الإجابة بنعم، فيجب أن تكون مستقرة.
  • هل يمكن الوصول إلى خاصية النظام هذه عبر وحدات Mainline أو عبر وحدة Mainline والجزء غير القابل للتحديث من النظام الأساسي؟ إذا كانت الإجابة بنعم، فيجب أن تكون مستقرة.

بالنسبة لخصائص النظام المستقرة، قم بتعريف كل منها رسميًا كواجهة برمجة التطبيقات (API) واستخدم واجهة برمجة التطبيقات (API) للوصول إلى خاصية النظام، كما هو موضح في الخطوة 6 .

الخطوة 5: تحديد الخصائص في وقت الإنشاء

قم بتعيين الخصائص في وقت الإنشاء باستخدام متغيرات 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}

أوامر shell getprop وsetprop

يمكنك استخدام أوامر getprop أو setprop shell، على التوالي، لقراءة الخصائص أو كتابتها. لمزيد من التفاصيل، قم باستدعاء 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);

لمزيد من المعلومات، راجع تنفيذ خصائص النظام كواجهات برمجة التطبيقات (API) .

وظائف وأساليب الملكية ذات المستوى المنخفض C/C++ وJava وRust

عندما يكون ذلك ممكنًا، استخدم Sysprop كواجهة برمجة التطبيقات (API) على الرغم من توفر وظائف C/C++ أو Rust ذات المستوى المنخفض أو أساليب Java ذات المستوى المنخفض لك.

تقدم libc و libbase و libcutils وظائف خاصية نظام C++. يحتوي libc على واجهة برمجة التطبيقات الأساسية، في حين أن وظائف libbase و libcutils عبارة عن أغلفة. إذا كان ذلك ممكنًا، استخدم وظائف libbase sysprop؛ إنها الأكثر ملاءمة، ويمكن للثنائيات المضيفة استخدام وظائف libbase . لمزيد من التفاصيل، راجع sys/system_properties.h ( libcandroid-base/properties.h ( libbase )، و cutils/properties.h ( libcutils ).

توفر فئة android.os.SystemProperties أساليب خاصية نظام Java.

توفر وحدة rustutils::system_properties وظائف وأنواع خاصية نظام الصدأ.

الملحق: إضافة خصائص خاصة بالبائع

يرغب الشركاء (بما في ذلك موظفي 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 .

تقع على عاتق البائع مسؤولية تسمية الخصائص والحفاظ عليها، لذا اتبع التنسيق المقترح في الخطوة 2 ، بالإضافة إلى متطلبات مساحات أسماء البائع.

قواعد SEPolicy الخاصة بالبائع وسياقات الملكية

يمكن تعريف خصائص البائع بواسطة الماكرو vendor_internal_prop . ضع القواعد الخاصة بالبائع التي تحددها في دليل BOARD_VENDOR_SEPOLICY_DIRS . على سبيل المثال، لنفترض أنك تقوم بتعريف خاصية واجهة البائع في المرجان.

في ملف 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 كواجهات برمجة التطبيقات (API) لإعادة تسمية خصائصك الحالية. يحافظ هذا على التوافق مع الإصدارات السابقة عن طريق تحديد كل من الاسم القديم واسم الخاصية الجديد. على وجه التحديد، يمكنك تعيين الاسم القديم بواسطة الحقل legacy_prop_name في الملف .sysprop . تحاول واجهة برمجة التطبيقات التي تم إنشاؤها قراءة 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);

لاحظ التحذيرات التالية:

  • أولاً، لا يمكنك تغيير نوع sysprop. على سبيل المثال، لا يمكنك تحويل الخاصية int إلى دعامة string . يمكنك فقط تغيير الاسم.

  • ثانيًا، تعود واجهة برمجة التطبيقات للقراءة فقط إلى الاسم القديم. واجهة برمجة تطبيقات الكتابة لا تتراجع. إذا كان sysprop قابلاً للكتابة، فلا يمكنك إعادة تسميته.