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

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

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

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

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

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

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

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

सीमाएं

ro का इस्तेमाल सिर्फ़ तब करें, जब आप पक्का कर लें कि आने वाले समय में prefix को लिखने की ज़रूरत नहीं है. ** ro प्रीफ़िक्स की वैल्यू न डालें.** इसके बजाय, prefix को रीड-ओनली बनाने के लिए, sepolicy पर भरोसा करें (दूसरे शब्दों में, सिर्फ़ init उसे लिखा जा सकता है).

persist का इस्तेमाल सिर्फ़ तब करें, जब आप यह पक्का कर लें कि वैल्यू, फिर से चालू करने के दौरान बनी रहनी चाहिए. साथ ही, आपके पास सिस्टम प्रॉपर्टी का इस्तेमाल करने का विकल्प भी है.

Google, सिस्टम की उन प्रॉपर्टी की सख्ती से समीक्षा करता है जिनमें ro या persist प्रॉपर्टी होती है.

group शब्द का इस्तेमाल, मिलती-जुलती प्रॉपर्टी को इकट्ठा करने के लिए किया जाता है. यह एक ऐसा सबसिस्टम नाम है जो audio या telephony से मिलता-जुलता है. sys, system, dev, default या config जैसे संदिग्ध या ओवरलोड (बहुत ज़्यादा) शब्दों का इस्तेमाल न करें.

आम तौर पर, उस प्रोसेस के डोमेन टाइप का नाम इस्तेमाल किया जाता है जिसमें सिस्टम की प्रॉपर्टी के लिए, पढ़ने या लिखने का खास ऐक्सेस होता है. उदाहरण के लिए, जिन सिस्टम प्रॉपर्टी में vold प्रोसेस को लिखने का ऐक्सेस है उनके लिए ग्रुप के नाम के तौर पर vold (प्रोसेस के लिए डोमेन टाइप का नाम) का इस्तेमाल करना आम तौर पर इस्तेमाल किया जाता है.

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

कई ग्रुप के नाम पहले ही तय किए जा चुके हैं. system/sepolicy/private/property_contexts फ़ाइल देखें और जहां भी हो सके, ग्रुप के मौजूदा नाम इस्तेमाल करें. इसके लिए, नए नाम न बनाएं. नीचे दी गई टेबल में, अक्सर इस्तेमाल होने वाले ग्रुप नामों के उदाहरण दिए गए हैं.

डोमेन ग्रुप (और सबग्रुप)
ब्लूटूथ से जुड़ी जानकारी bluetooth
कर्नेल cmdline से sysप्रॉप boot
सिप्रॉप जो किसी बिल्ड की पहचान करते हैं build
टेलीफ़ोनी से जुड़ी telephony
ऑडियो के बारे में जानकारी audio
ग्राफ़िक से जुड़े graphics
Vod से जुड़े सवाल 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 प्रॉपर्टी कॉन्टेक्स्ट स्कीम, जानकारी के स्तर को बारीकी से और ज़्यादा जानकारी देने वाले नाम देने की अनुमति देती है. प्रॉपर्टी के नामों के लिए इस्तेमाल किए जाने वाले तरीके की तरह, एओएसपी इस फ़ॉर्मैट का सुझाव देता है:

{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 के बाहर पढ़ा और लिखा जाता है

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

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

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

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

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

तीसरा चरण: सिस्टम/विज्ञापन नीति में जोड़ें

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)

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

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

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

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

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

बिल्ड टाइम के दौरान, Makefile वैरिएबल की मदद से प्रॉपर्टी सेट करें. तकनीकी तौर पर, ये वैल्यू {partition}/build.prop में बनाई जाती हैं. इसके बाद, प्रॉपर्टी सेट करने के लिए init, {partition}/build.prop को पढ़ता है. ऐसे वैरिएबल के दो सेट होते हैं: PRODUCT_{PARTITION}_PROPERTIES और TARGET_{PARTITION}_PROP.

PRODUCT_{PARTITION}_PROPERTIES में प्रॉपर्टी की वैल्यू की एक सूची शामिल है. सिंटैक्स {prop}={value} या {prop}?={value} है.

{prop}={value} एक सामान्य असाइनमेंट है, जो पक्का करता है कि {prop} को {value} पर सेट किया गया है. हर प्रॉपर्टी के लिए ऐसा सिर्फ़ एक असाइनमेंट हो सकता है.

{prop}?={value} एक वैकल्पिक असाइनमेंट है; {prop} को {value} पर सिर्फ़ तब सेट किया जाता है, जब कोई {prop}={value} असाइनमेंट न हो. अगर कई वैकल्पिक असाइनमेंट मौजूद हैं, तो पहला वाला जीत जाएगा.

# sets persist.traced.enable to 1 with system/build.prop
PRODUCT_SYSTEM_PROPERTIES += persist.traced.enable=1

# sets ro.zygote to zygote32 with system/build.prop
# but only when there are no other assignments to ro.zygote
# optional are useful when giving a default value to a property
PRODUCT_SYSTEM_PROPERTIES += ro.zygote?=zygote32

# sets ro.config.low_ram to true with vendor/build.prop
PRODUCT_VENDOR_PROPERTIES += ro.config.low_ram=true

TARGET_{PARTITION}_PROP में फ़ाइलों की एक सूची होती है, जो सीधे {partition}/build.prop में पहुंचती है. हर फ़ाइल में {prop}={value} पेयर की सूची है.

# example.prop

ro.cp_system_other_odex=0
ro.adb.secure=0
ro.control_privapp_permissions=disable

# emits example.prop to system/build.prop
TARGET_SYSTEM_PROP += example.prop

ज़्यादा जानकारी के लिए, build/make/core/sysprop.mk देखें.

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

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

Init स्क्रिप्ट

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 मॉड्यूल में, Rust सिस्टम प्रॉपर्टी के फ़ंक्शन और टाइप की जानकारी मिलती है.

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

पार्टनर (इनमें 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.

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

वेंडर के लिए 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 को पढ़ने की कोशिश करता है और 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);

इन चेतावनियों पर ध्यान दें:

  • पहला, सिस्टम का टाइप नहीं बदला जा सकता. उदाहरण के लिए, string प्रॉप में int प्रॉप नहीं बनाया जा सकता. इसमें सिर्फ़ नाम बदला जा सकता है.

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