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