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

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

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

सिस्टम प्रॉपर्टी जोड़ते समय, प्रॉपर्टी का नाम तय करें और उसे SELinux प्रॉपर्टी कॉन्टेक्स्ट से जोड़ें. अगर कोई सही मौजूदा कॉन्टेक्स्ट नहीं है, तो नया कॉन्टेक्स्ट बनाएं. प्रॉपर्टी को ऐक्सेस करते समय नाम का इस्तेमाल किया जाता है. प्रॉपर्टी के कॉन्टेक्स्ट का इस्तेमाल, SELinux के हिसाब से ऐक्सेस कंट्रोल करने के लिए किया जाता है. नामों के लिए कोई भी स्ट्रिंग इस्तेमाल की जा सकती है. हालांकि, AOSP का सुझाव है कि नामों को साफ़ तौर पर दिखाने के लिए, स्ट्रक्चर्ड फ़ॉर्मैट का इस्तेमाल करें.

प्रॉपर्टी नाम

snake_case केसिंग के साथ इस फ़ॉर्मैट का इस्तेमाल करें:

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

एलिमेंट prefix के लिए, "" (छोड़ दिया गया), ro (सिर्फ़ एक बार सेट की गई प्रॉपर्टी के लिए) या persist (रीबूट के बाद भी बनी रहने वाली प्रॉपर्टी के लिए) में से किसी एक का इस्तेमाल करें.

सीमाएं

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 से जुड़े 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 प्रॉपर्टी के लिए नई कॉन्टेक्स्ट स्कीम, ज़्यादा जानकारी और बेहतर नामों की सुविधा देती है. प्रॉपर्टी के नामों के लिए इस्तेमाल किए जाने वाले तरीके की तरह, एओएसपी इस फ़ॉर्मैट का सुझाव देता है:

{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 फ़ाइल में तय करें. अपनी सिस्टम प्रॉपर्टी के लिए ज़रूरी ऐक्सेसibilitability की सुविधा देने वाले 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)

दूसरा, प्रॉपर्टी कॉन्टेक्स्ट को पढ़ने और (या) लिखने का ऐक्सेस दें. system/sepolicy/public/{domain}.te या system/sepolicy/private/{domain}.te फ़ाइल में, ऐक्सेस देने के लिए set_prop और get_prop मैक्रो का इस्तेमाल करें. जब भी हो सके, 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 मॉड्यूलर हो गया है. ट्रेबल की मदद से, सिस्टम, वेंडर, और प्रॉडक्ट विभाजनों को एक-दूसरे से अलग अपडेट किया जा सकता है. मेनलाइन में, ओएस के कुछ हिस्सों को अपडेट किए जा सकने वाले मॉड्यूल (APEXes या APKs में) के तौर पर मॉड्यूल किया जाता है.

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

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

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

स्थिर सिस्टम प्रॉपर्टी के लिए, हर प्रॉपर्टी को एपीआई के तौर पर आधिकारिक तौर पर तय करें. साथ ही, छठे चरण में बताए गए तरीके के मुताबिक, सिस्टम प्रॉपर्टी को ऐक्सेस करने के लिए एपीआई का इस्तेमाल करें.

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

बिल्ड टाइम के दौरान, 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 या 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 sysprop फ़ंक्शन का इस्तेमाल करें. ये सबसे आसान होते हैं और होस्ट बाइनरी, libbase फ़ंक्शन का इस्तेमाल कर सकती हैं. ज़्यादा जानकारी के लिए, sys/system_properties.h (libc), android-base/properties.h (libbase), और cutils/properties.h (libcutils) देखें.

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

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

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

पार्टनर (इसमें Pixel के डेवलपमेंट के लिए काम करने वाले Googlers भी शामिल हैं) को, हार्डवेयर (या डिवाइस) के हिसाब से सिस्टम प्रॉपर्टी तय करनी हैं. वेंडर-स्पेसिफ़िक प्रॉपर्टी, पार्टनर के मालिकाना हक वाली प्रॉपर्टी होती हैं. ये प्रॉपर्टी, प्लैटफ़ॉर्म के लिए नहीं, बल्कि उनके हार्डवेयर या डिवाइस के लिए खास होती हैं. ये हार्डवेयर या डिवाइस पर निर्भर होते हैं. इसलिए, इन्हें /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.

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

वेंडर के हिसाब से SEPolicy के नियम और property_contexts

वेंडर प्रॉपर्टी को vendor_internal_prop मैक्रो से तय किया जा सकता है. वे वेंडर-खास नियम डालें जिन्हें आपने BOARD_VENDOR_SEPOLICY_DIRS डायरेक्ट्री में तय किया है. उदाहरण के लिए, मान लें कि आपको coral में वेंडर की 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 को पढ़ने की कोशिश करता है. अगर 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 का टाइप नहीं बदला जा सकता. उदाहरण के लिए, string प्रॉप में int प्रॉप नहीं बनाया जा सकता. इसमें सिर्फ़ नाम बदला जा सकता है.

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