सिस्टम प्रॉपर्टी जोड़ना

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

नाम के इस्तेमाल के लिए, exported_vold_prop को exported_vold_prop या vold_vendor_writable_prop से ज़्यादा प्राथमिकता दें.vold_config_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 के बाहर पढ़ा और लिखा जाता है

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

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

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

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

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

तीसरा चरण: सिस्टम/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)

दूसरा, प्रॉपर्टी के कॉन्टेक्स्ट के लिए पढ़ने और (या) लिखने का ऐक्सेस दें. 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)

तीसरा, कुछ neverallow नियम जोड़ें, ताकि मैक्रो के दायरे में आने वाली ऐक्सेसिबिलिटी को और कम किया जा सके. उदाहरण के लिए, मान लें कि आपने 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 फ़ाइल में रखें. ज़्यादा बड़े स्तर पर कभी अनुमति न दें वाले नियमों के लिए, इन जैसे सामान्य डोमेन का इस्तेमाल करें:

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

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

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

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

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

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

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

छठा चरण: रनटाइम के दौरान प्रॉपर्टी ऐक्सेस करना

प्रॉपर्टी को रनटाइम के दौरान पढ़ा और लिखा जा सकता है.

स्क्रिप्ट शुरू करना

इनिट स्क्रिप्ट फ़ाइलें (आम तौर पर *.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 को एपीआई के तौर पर इस्तेमाल करके, सिस्टम प्रॉपर्टी तय की जा सकती हैं. साथ ही, अपने-आप जनरेट होने वाले एपीआई का इस्तेमाल किया जा सकता है. ये एपीआई, टाइप किए गए और खास होते हैं. Public के साथ scope सेट करने से, जनरेट किए गए एपीआई, सीमाओं के पार मौजूद मॉड्यूल के लिए भी उपलब्ध होते हैं. साथ ही, इससे एपीआई के स्टेबल होने की पुष्टि होती है. यहां .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 के डेवलपमेंट के लिए काम करने वाले Googler भी शामिल हैं) को हार्डवेयर के हिसाब से (या डिवाइस के हिसाब से) सिस्टम प्रॉपर्टी तय करनी होती हैं. वेंडर के हिसाब से तय की गई प्रॉपर्टी, पार्टनर के मालिकाना हक वाली प्रॉपर्टी होती हैं. ये प्रॉपर्टी, पार्टनर के हार्डवेयर या डिवाइस के लिए यूनीक होती हैं, न कि प्लैटफ़ॉर्म के लिए. ये हार्डवेयर या डिवाइस पर निर्भर करते हैं. इसलिए, इनका इस्तेमाल /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 डायरेक्ट्री में रखें. उदाहरण के लिए, मान लें कि आपको कोरल में वेंडर की 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 as APIs का इस्तेमाल करें. इससे पुराने सिस्टम के साथ काम करने की सुविधा बनी रहती है. इसके लिए, पुराने नाम और नई प्रॉपर्टी, दोनों के नाम दिए जाते हैं. खास तौर पर, .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 का टाइप नहीं बदला जा सकता. उदाहरण के लिए, int प्रॉपर्टी को string प्रॉपर्टी में नहीं बदला जा सकता. सिर्फ़ नाम बदला जा सकता है.

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