सिस्टम की प्रॉपर्टी जोड़ें

इस पेज पर, Android में सिस्टम प्रॉपर्टी जोड़ने या तय करने का कैननिकल तरीका बताया गया है. साथ ही, मौजूदा सिस्टम प्रॉपर्टी को फिर से बनाने के दिशा-निर्देश भी दिए गए हैं. पक्का करें कि आप प्रतिक्रिया देते समय दिशा-निर्देशों का पालन करें, जब तक कि आपके पास साथ काम करने से जुड़ी कोई समस्या है.

पहला चरण: सिस्टम की प्रॉपर्टी तय करना

सिस्टम प्रॉपर्टी जोड़ते समय, प्रॉपर्टी का नाम तय करें और असोसिएट करें उसे 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
कर्नेल cmdline से sysprops boot
सिप्रॉप जो किसी बिल्ड की पहचान करते हैं build
टेलीफ़ोनी से जुड़ी telephony
ऑडियो के बारे में जानकारी audio
ग्राफ़िक से जुड़े graphics
वोल्ड से जुड़े vold

नीचे, पिछले रेगुलर एक्सप्रेशन के उदाहरण में name और type के इस्तेमाल के बारे में बताया गया है.

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

  • name किसी ग्रुप में सिस्टम प्रॉपर्टी की पहचान करता है.

  • type एक वैकल्पिक एलिमेंट है. इससे यह पता चलता है कि सिस्टम प्रॉपर्टी. उदाहरण के लिए, किसी सिस्टम को यह नाम देने के बजाय 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
पूर्णांक साइन किया हुआ 64-बिट पूर्णांक
साइन नहीं किया गया पूर्णांक साइन न किया गया 64-बिट वाला पूर्णांक
डबल डबल-प्रीसिज़न फ़्लोटिंग पॉइंट
स्ट्रिंग कोई भी मान्य UTF-8 स्ट्रिंग
enum वैल्यू, बिना खाली सफ़ेद जगह के कोई भी मान्य 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 के बाहर पढ़ा और लिखा जाता है

सिस्टम प्रॉपर्टी के ऐक्सेस को ज़्यादा से ज़्यादा सीमित रखें. पहले, सीमित ऐक्सेस की वजह से, ऐप्लिकेशन में गड़बड़ी हुई है और सुरक्षा से जुड़े जोखिम पैदा हो गए हैं. इन बातों पर ध्यान दें सीमा तय करते समय ये सवाल:

  • क्या इस सिस्टम प्रॉपर्टी को बनाए रखने की ज़रूरत है? (अगर हां, तो क्यों?)
  • किस प्रोसेस के पास इस प्रॉपर्टी को पढ़ने का ऐक्सेस होना चाहिए?
  • किस प्रोसेस के पास इस प्रॉपर्टी में लिखने का ऐक्सेस होना चाहिए?

ऐक्सेस के सही दायरे का पता लगाने के लिए, ऊपर दिए गए सवालों और नीचे दिए गए डिसीज़न ट्री का इस्तेमाल करें.

ऐक्सेस के दायरे का पता लगाने के लिए डिसीज़न ट्री

पहला डायग्राम. सिस्टम प्रॉपर्टी के ऐक्सेस का दायरा तय करने के लिए डिसिज़न ट्री

तीसरा चरण: 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)

तीसरा, कुछ ऐसे नियम जोड़ें जिनकी मदद से, का दायरा मैक्रो के आधार पर तय किया जाता है. उदाहरण के लिए, मान लें कि आपने 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 का इस्तेमाल करें.)

पक्का करें कि हर एंट्री का टाइप तय हो. ऐसा इसलिए, क्योंकि 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 OS मॉड्यूलर हो गया है. ट्रेबल की मदद से, वेंडर और प्रॉडक्ट के सेगमेंट, एक-दूसरे से अलग अपडेट किए जा सकते हैं. Mainline में, ओएस के कुछ हिस्सों को अपडेट किए जा सकने वाले मॉड्यूल (APEX या APK में) के तौर पर मॉड्यूलर किया गया है.

अगर कोई सिस्टम प्रॉपर्टी, अपडेट किए जा सकने वाले सॉफ़्टवेयर के सभी हिस्सों में इस्तेमाल के लिए है, तो उदाहरण के लिए, सिस्टम और वेंडर के सभी सेगमेंट में, यह स्थिर होनी चाहिए. हालांकि, अगर इसका इस्तेमाल किया जाता है, तो उदाहरण के लिए, किसी मेनलाइन मॉड्यूल में, उसका नाम बदला जा सकता है, टाइप, या प्रॉपर्टी कॉन्टेक्स्ट शामिल किए जा सकते हैं और यहां तक कि उन्हें हटाया भी जा सकता है.

सिस्टम प्रॉपर्टी की स्थिरता तय करने के लिए, नीचे दिए गए सवाल पूछें:

  • क्या इस सिस्टम प्रॉपर्टी को पार्टनर कॉन्फ़िगर करते हैं या हर डिवाइस के लिए अलग-अलग कॉन्फ़िगर करते हैं? अगर हां, तो यह स्थिर होना चाहिए.
  • क्या AOSP की तय की गई इस सिस्टम प्रॉपर्टी का मकसद, vendor.img या product.img जैसे नॉन-सिस्टम पार्टीशन में मौजूद कोड (प्रोसेस नहीं) में लिखना या उससे पढ़ना है? अगर हां, तो यह स्थिर होना चाहिए.
  • क्या इस सिस्टम प्रॉपर्टी को मेनलाइन मॉड्यूल या मेनलाइन पर ऐक्सेस किया जाता है और YouTube के ऐसे हिस्से जो अपडेट नहीं हो सकते? अगर हां, तो यह स्थिर होना चाहिए.

स्थिर सिस्टम प्रॉपर्टी के लिए, हर एक को औपचारिक रूप से एपीआई के तौर पर परिभाषित करें और एपीआई का इस्तेमाल करें का इस्तेमाल करें, जैसा कि यहां बताया गया है छठा चरण.

पांचवां चरण: बिल्ड के समय प्रॉपर्टी सेट करना

बिल्ड टाइम के दौरान, createfile वैरिएबल की मदद से प्रॉपर्टी सेट करें. तकनीकी तौर पर, वैल्यू {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 --help शुरू करें या setprop --help.

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

C++/Java/Rust के लिए, एपीआई के तौर पर Sysprop

sysprop को एपीआई के तौर पर इस्तेमाल करके, सिस्टम प्रॉपर्टी तय की जा सकती हैं. साथ ही, अपने-आप जनरेट होने वाले एपीआई का इस्तेमाल किया जा सकता है. ये एपीआई, सटीक और टाइप किए गए होते हैं. 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 को एपीआई के तौर पर इस्तेमाल करें. भले ही, आपके पास लो-लेवल C/C++ या Rust फ़ंक्शन या लो-लेवल Java तरीके उपलब्ध हों.

libc, libbase, और libcutils में C++ सिस्टम प्रॉपर्टी फ़ंक्शन उपलब्ध हैं. libc अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है में एपीआई मौजूद है, जबकि libbase और libcutils फ़ंक्शन रैपर. अगर हो सके, तो libbase सिस्प्रोप फ़ंक्शन का इस्तेमाल करें; वे हैं सबसे आसान है और होस्ट बाइनरी, libbase फ़ंक्शन का इस्तेमाल कर सकती हैं. ज़्यादा के लिए जानकारी, sys/system_properties.h (libc), android-base/properties.h देखें (libbase), और cutils/properties.h (libcutils).

android.os.SystemProperties क्लास, Java सिस्टम प्रॉपर्टी के मेथड उपलब्ध कराती है.

rustutils::system_properties मॉड्यूल में, रस्ट सिस्टम प्रॉपर्टी फ़ंक्शन की सुविधा मिलती है और प्रकार.

परिशिष्ट: वेंडर के हिसाब से प्रॉपर्टी जोड़ना

पार्टनर (इनमें Pixel को डेवलप करने से जुड़े काम करने वाले Googler भी शामिल हैं) का इस्तेमाल करें. वेंडर की प्रॉपर्टी, पार्टनर के मालिकाना हक वाली ऐसी प्रॉपर्टी होती हैं जो उनके खुद के हार्डवेयर या डिवाइस का, प्लैटफ़ॉर्म के लिए नहीं. ये हार्डवेयर या डिवाइस हैं निर्भर करता है कि उन्हें /vendor या /odm सेगमेंट में इस्तेमाल किया जाना है.

प्रोजेक्ट ट्रेबल के बाद से ही, प्लैटफ़ॉर्म और वेंडर प्रॉपर्टी इन्हें अलग-अलग हिस्सों में बांटें. यहां वेंडर प्रॉपर्टी तय करने का तरीका बताया गया है. साथ ही, यह भी बताया गया है कि किन वेंडर प्रॉपर्टी का इस्तेमाल हमेशा किया जाना चाहिए.

प्रॉपर्टी और कॉन्टेक्स्ट के नामों के लिए नेमस्पेस

सभी वेंडर प्रॉपर्टी को इनमें से किसी एक प्रीफ़िक्स से शुरू होना चाहिए, ताकि वे और अन्य सेगमेंट की प्रॉपर्टी के बीच टकराव होता है.

  • 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 के नियम और 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 विभाजन.

परिशिष्ट: मौजूदा प्रॉपर्टी का नाम बदलना

जब आपको किसी प्रॉपर्टी को बंद करके नई प्रॉपर्टी पर जाना हो, तो अपनी मौजूदा प्रॉपर्टी का नाम बदलने के लिए, Sysprop को एपीआई के तौर पर इस्तेमाल करें. यह पुराने सिस्टम के साथ काम करने की सुविधा को बनाए रखता है. इसके लिए, यह लेगसी नाम और नई प्रॉपर्टी, दोनों का नाम बताता है. खास तौर पर, आपके पास ये काम करने की सुविधा होती है .sysprop फ़ाइल में, legacy_prop_name फ़ील्ड के हिसाब से लेगसी नाम सेट करें. कॉन्टेंट बनाने जनरेट किया गया एपीआई, 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 का टाइप नहीं बदला जा सकता. उदाहरण के लिए, आप नहीं कर सकते string प्रॉप में int प्रॉप. सिर्फ़ नाम बदला जा सकता है.

  • दूसरा, सिर्फ़ रीड एपीआई ही लेगसी नाम पर वापस जाता है. लिखने के लिए इस्तेमाल होने वाला एपीआई, वैकल्पिक तरीका इस्तेमाल नहीं करता. अगर sysprop को लिखा जा सकता है, तो उसका नाम नहीं बदला जा सकता.