หน้านี้มีวิธีการที่เชื่อถือได้ในการเพิ่มหรือกำหนดพร็อพเพอร์ตี้ของระบบ ใน Android พร้อมหลักเกณฑ์ในการปรับโครงสร้างพร็อพเพอร์ตี้ของระบบที่มีอยู่ ตรวจสอบว่าคุณใช้หลักเกณฑ์เมื่อทำการรีแฟกเตอร์ เว้นแต่จะมีปัญหาด้านความเข้ากันได้ที่ร้ายแรงซึ่งกำหนดไว้เป็นอย่างอื่น
ขั้นตอนที่ 1: กําหนดพร็อพเพอร์ตี้ของระบบ
เมื่อเพิ่มพร็อพเพอร์ตี้ของระบบ ให้ตั้งชื่อพร็อพเพอร์ตี้และเชื่อมโยง กับบริบทพร็อพเพอร์ตี้ SELinux หากไม่มีบริบทที่มีอยู่ซึ่งเหมาะสม ให้สร้างบริบทใหม่ ระบบจะใช้ชื่อเมื่อเข้าถึงพร็อพเพอร์ตี้ และใช้บริบทพร็อพเพอร์ตี้เพื่อควบคุมการเข้าถึงในแง่ของ SELinux ชื่อจะเป็นสตริงใดก็ได้ แต่ AOSP ขอแนะนำให้คุณใช้รูปแบบที่มีโครงสร้างเพื่อให้ชื่อมีความชัดเจน
ชื่อพร็อพเพอร์ตี้
ใช้รูปแบบนี้กับตัวพิมพ์เล็กและขีดล่าง
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
ใช้ "" (ละเว้น) ro
(สำหรับพร็อพเพอร์ตี้ที่ตั้งค่าเพียงครั้งเดียว) หรือ persist
(สำหรับพร็อพเพอร์ตี้ที่คงอยู่เมื่อรีบูต) สำหรับองค์ประกอบ prefix
ข้อควรระวัง
ใช้ ro
เฉพาะเมื่อคุณแน่ใจว่าไม่จำเป็นต้องให้ prefix
เขียนได้
ในอนาคต ** อย่าระบุคำนำหน้า ro
** แต่ให้ใช้ sepolicy เพื่อ
ทำให้ prefix
เป็นแบบอ่านอย่างเดียว (กล่าวคือ เขียนได้เฉพาะโดย init
)
ใช้ persist
เฉพาะเมื่อคุณมั่นใจว่าต้องคงค่าไว้ตลอดการรีบูต และการใช้พร็อพเพอร์ตี้ของระบบเป็นตัวเลือกเดียวของคุณ
Google ตรวจสอบพร็อพเพอร์ตี้ของระบบอย่างเข้มงวดซึ่งมีพร็อพเพอร์ตี้ ro
หรือ persist
คำว่า group
ใช้เพื่อรวบรวมพร็อพเพอร์ตี้ที่เกี่ยวข้อง โดยมีจุดประสงค์เพื่อเป็นชื่อระบบย่อยที่มีการใช้งานคล้ายกับ audio
หรือ telephony
อย่าใช้
คำที่คลุมเครือหรือใช้มากเกินไป เช่น sys
, system
, dev
, default
หรือ
config
โดยทั่วไปจะใช้ชื่อประเภทโดเมนของกระบวนการที่มีสิทธิ์อ่านหรือเขียนแบบพิเศษไปยังพร็อพเพอร์ตี้ของระบบ ตัวอย่างเช่น สำหรับพร็อพเพอร์ตี้ของระบบที่กระบวนการ vold
มีสิทธิ์เขียน
โดยทั่วไปจะใช้ vold
(ชื่อประเภทโดเมนสำหรับกระบวนการ) เป็นชื่อกลุ่ม
หากจำเป็น ให้เพิ่ม subgroup
เพื่อจัดหมวดหมู่พร็อพเพอร์ตี้เพิ่มเติม แต่อย่าใช้คำที่คลุมเครือหรือใช้คำมากเกินไปเพื่ออธิบายองค์ประกอบนี้ (คุณมีsubgroup
ได้มากกว่า 1 รายการ)
มีการกำหนดชื่อกลุ่มจำนวนมากแล้ว ตรวจสอบ
system/sepolicy/private/property_contexts
ไฟล์และใช้ชื่อกลุ่มที่มีอยู่
หากเป็นไปได้ แทนที่จะสร้างชื่อใหม่ ตารางต่อไปนี้แสดง
ตัวอย่างชื่อกลุ่มที่ใช้บ่อย
โดเมน | กลุ่ม (และกลุ่มย่อย) |
---|---|
เกี่ยวกับบลูทูธ | bluetooth |
sysprops จากบรรทัดคำสั่งของเคอร์เนล | boot |
sysprops ที่ระบุบิลด์ | 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
ควรใช้ชื่อในรูปแบบ 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
ในขั้นตอนที่ 3
ขั้นตอนที่ 2: กำหนดระดับการช่วยเหลือพิเศษที่จำเป็น
มีมาโครตัวช่วย 4 รายการที่กำหนดพร็อพเพอร์ตี้
ประเภทการช่วยเหลือพิเศษ | ความหมาย |
---|---|
system_internal_prop |
พร็อพเพอร์ตี้ที่ใช้ใน /system เท่านั้น |
system_restricted_prop |
พร็อพเพอร์ตี้ที่อ่านภายนอก /system แต่ไม่ได้เขียน |
system_vendor_config_prop |
พร็อพเพอร์ตี้ที่อ่านภายนอก /system และเขียนโดย vendor_init เท่านั้น |
system_public_prop |
พร็อพเพอร์ตี้ที่อ่านและเขียนภายนอก /system |
กำหนดขอบเขตการเข้าถึงพร็อพเพอร์ตี้ของระบบให้แคบที่สุด ในอดีต การเข้าถึงในวงกว้างส่งผลให้แอปใช้งานไม่ได้และมีช่องโหว่ด้านความปลอดภัย พิจารณาคำถามต่อไปนี้เมื่อกำหนดขอบเขต
- ต้องคงพร็อพเพอร์ตี้ของระบบนี้ไว้ไหม (หากใช่ เพราะเหตุใด)
- กระบวนการใดควรมีสิทธิ์เข้าถึงแบบอ่านในพร็อพเพอร์ตี้นี้
- กระบวนการใดควรมีสิทธิ์เข้าถึงแบบเขียนในพร็อพเพอร์ตี้นี้
ใช้คำถามก่อนหน้าและแผนผังการตัดสินใจต่อไปนี้เป็นเครื่องมือสำหรับ กำหนดขอบเขตการเข้าถึงที่เหมาะสม
รูปที่ 1 แผนผังการตัดสินใจเพื่อกำหนดขอบเขตการเข้าถึงพร็อพเพอร์ตี้ของระบบ
ขั้นตอนที่ 3: เพิ่มลงใน system/sepolicy
เมื่อเข้าถึง sysprop, SELinux จะควบคุมการเข้าถึงของกระบวนการ หลังจาก
พิจารณาว่าต้องมีระดับการช่วยเหลือพิเศษใด ให้กำหนดบริบทของพร็อพเพอร์ตี้
ใน system/sepolicy
พร้อมกับกฎ allow และ neverallow เพิ่มเติม
เกี่ยวกับสิ่งที่กระบวนการได้รับ (และไม่ได้รับ) อนุญาตให้อ่านหรือเขียน
ก่อนอื่น ให้กำหนดบริบทของพร็อพเพอร์ตี้ใน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)
ประการที่ 2 ให้สิทธิ์การอ่านและ (หรือ) การเขียนบริบทพร็อพเพอร์ตี้ ใช้มาโคร set_prop
และ get_prop
เพื่อให้สิทธิ์เข้าถึงในไฟล์ system/sepolicy/public/{domain}.te
หรือ system/sepolicy/private/{domain}.te
ใช้ private
เมื่อเป็นไปได้ public
เหมาะสมเฉพาะในกรณีที่มาโคร set_prop
หรือ get_prop
ส่งผลต่อโดเมนใดๆ นอกโดเมนหลัก
ตัวอย่างในไฟล์ system/sepolicy/private/audio.te
set_prop(audio, audio_foo_prop)
set_prop(audio, audio_bar_prop)
ตัวอย่างในไฟล์ system/sepolicy/public/domain.te
get_prop(domain, audio_bar_prop)
ประการที่สาม เพิ่มกฎ 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
หากกฎ neverallow เชื่อมโยงกับโดเมนที่เฉพาะเจาะจง สำหรับกฎ neverallow ที่กว้างขึ้น ให้ใช้
โดเมนทั่วไป เช่น โดเมนต่อไปนี้ในทุกที่ที่เหมาะสม
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
"
สุดท้าย ให้เชื่อมโยงพร็อพเพอร์ตี้ของระบบกับบริบทของพร็อพเพอร์ตี้ ซึ่งจะช่วยให้มั่นใจได้ว่าสิทธิ์เข้าถึงที่ได้รับและกฎ neverallow ที่ใช้กับบริบทของพร็อพเพอร์ตี้จะใช้กับพร็อพเพอร์ตี้จริง โดยเพิ่มรายการลงในไฟล์ 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
จะ
บังคับใช้เมื่อตั้งค่า 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
ขั้นตอนที่ 4: กำหนดข้อกำหนดด้านความเสถียร
ความเสถียรเป็นอีกแง่มุมหนึ่งของพร็อพเพอร์ตี้ระบบ และแตกต่างจาก การช่วยเหลือพิเศษ ความเสถียรคือการพิจารณาว่าพร็อพเพอร์ตี้ของระบบสามารถเปลี่ยนแปลงได้หรือไม่ (เช่น เปลี่ยนชื่อ หรือแม้แต่นำออก) ในอนาคต ซึ่งเป็นสิ่งสำคัญอย่างยิ่งเมื่อระบบปฏิบัติการ Android กลายเป็นแบบแยกส่วน Treble ช่วยให้สามารถอัปเดตพาร์ติชันระบบ ผู้ให้บริการ และผลิตภัณฑ์แยกกันได้ Mainline จะแยกส่วนบางส่วนของระบบปฏิบัติการเป็นโมดูลที่อัปเดตได้ (ใน APEX หรือ APK)
หากพร็อพเพอร์ตี้ของระบบใช้กับซอฟต์แวร์ที่อัปเดตได้ เช่น ในพาร์ติชันระบบและพาร์ติชันของผู้ให้บริการ พร็อพเพอร์ตี้นั้นต้องเสถียร แต่หากใช้เฉพาะภายใน เช่น โมดูล Mainline ที่เฉพาะเจาะจง คุณจะเปลี่ยนชื่อ ประเภท หรือบริบทของพร็อพเพอร์ตี้ และนำออกได้ด้วย
ถามคำถามต่อไปนี้เพื่อพิจารณาความเสถียรของพร็อพเพอร์ตี้ของระบบ
- คุณต้องการให้พาร์ทเนอร์กำหนดค่าพร็อพเพอร์ตี้ของระบบนี้ (หรือกำหนดค่า แตกต่างกันในแต่ละอุปกรณ์) หรือไม่ หากมี ต้องเป็นเวอร์ชันที่เสถียร
- คุณต้องการให้โค้ด (ไม่ใช่กระบวนการ) ที่อยู่ในพาร์ติชันที่ไม่ใช่ระบบ เช่น
vendor.img
หรือproduct.img
เขียนหรืออ่านพร็อพเพอร์ตี้ของระบบที่กำหนดโดย AOSP นี้หรือไม่ หากมี ต้องเป็นเวอร์ชันที่เสถียร - มีการเข้าถึงพร็อพเพอร์ตี้ของระบบนี้ในโมดูล Mainline หรือในโมดูล Mainline และส่วนที่อัปเดตไม่ได้ของแพลตฟอร์มหรือไม่ หากมี ต้องเป็นเวอร์ชันที่เสถียร
สำหรับพร็อพเพอร์ตี้ของระบบที่เสถียร ให้กำหนดแต่ละรายการอย่างเป็นทางการเป็น API และใช้ API เพื่อเข้าถึงพร็อพเพอร์ตี้ของระบบตามที่อธิบายไว้ใน ขั้นตอนที่ 6
ขั้นตอนที่ 5: ตั้งค่าพร็อพเพอร์ตี้ในเวลาบิลด์
ตั้งค่าพร็อพเพอร์ตี้ในเวลาบิลด์ด้วยตัวแปร Makefile ในทางเทคนิค ค่า
จะอยู่ใน {partition}/build.prop
จากนั้น init
อ่าน
{partition}/build.prop
เพื่อตั้งค่าพร็อพเพอร์ตี้ ตัวแปรดังกล่าวมี 2 ชุด ได้แก่ PRODUCT_{PARTITION}_PROPERTIES
และ TARGET_{PARTITION}_PROP
PRODUCT_{PARTITION}_PROPERTIES
มีรายการค่าพร็อพเพอร์ตี้ ไวยากรณ์
คือ {prop}={value}
หรือ {prop}?={value}
{prop}={value}
เป็นการกำหนดปกติซึ่งช่วยให้มั่นใจได้ว่า {prop}
จะตั้งค่าเป็น
{value}
โดยพร็อพเพอร์ตี้เดียวจะมีการกำหนดดังกล่าวได้เพียง 1 รายการ
{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
ขั้นตอนที่ 6: เข้าถึงพร็อพเพอร์ตี้ที่รันไทม์
อ่านและเขียนพร็อพเพอร์ตี้ได้ในรันไทม์
สคริปต์เริ่มต้น
ไฟล์สคริปต์เริ่มต้น (โดยปกติคือไฟล์ *.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}
คำสั่ง Shell getprop และ setprop
คุณใช้คำสั่งเชลล์ getprop
หรือ setprop
ตามลำดับเพื่ออ่านหรือเขียนพร็อพเพอร์ตี้ได้ ดูรายละเอียดเพิ่มเติมได้โดยเรียกใช้ getprop --help
หรือ
setprop --help
$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0
Sysprop เป็น API สำหรับ C++/Java/Rust
เมื่อใช้ sysprop เป็น API คุณจะกำหนดพร็อพเพอร์ตี้ของระบบและใช้ API ที่สร้างขึ้นโดยอัตโนมัติได้
ซึ่งเป็น API ที่เจาะจงและมีการพิมพ์ การตั้งค่า scope
ด้วย Public
ยังทำให้ API ที่สร้างขึ้นพร้อมใช้งานสำหรับโมดูลต่างๆ ข้ามขอบเขต และช่วยให้มั่นใจได้ถึงความเสถียรของ API ตัวอย่าง.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);
ดูข้อมูลเพิ่มเติมได้ที่ติดตั้งใช้งานพร็อพเพอร์ตี้ของระบบเป็น API
ฟังก์ชันและเมธอดพร็อพเพอร์ตี้ระดับต่ำของ C/C++, Java และ Rust
หากเป็นไปได้ ให้ใช้ Sysprop เป็น API แม้ว่าคุณจะใช้ฟังก์ชัน C/C++ หรือ Rust ระดับต่ำ หรือเมธอด Java ระดับต่ำได้ก็ตาม
libc
, libbase
และ libcutils
มีฟังก์ชันพร็อพเพอร์ตี้ของระบบ C++ libc
มี API พื้นฐาน ส่วนฟังก์ชัน libbase
และ libcutils
เป็น
Wrapper หากเป็นไปได้ ให้ใช้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
ภาคผนวก: เพิ่มพร็อพเพอร์ตี้เฉพาะผู้ให้บริการ
พาร์ทเนอร์ (รวมถึง Googler ที่ทำงานในบริบทของการพัฒนา Pixel) ต้องการกำหนดพร็อพเพอร์ตี้ของระบบที่เฉพาะเจาะจงกับฮาร์ดแวร์ (หรือเฉพาะเจาะจงกับอุปกรณ์)
พร็อพเพอร์ตี้เฉพาะของผู้ให้บริการคือพร็อพเพอร์ตี้ที่พาร์ทเนอร์เป็นเจ้าของซึ่งมีเฉพาะในฮาร์ดแวร์หรืออุปกรณ์ของพาร์ทเนอร์เอง ไม่ใช่ของแพลตฟอร์ม เนื่องจากฟีเจอร์เหล่านี้ขึ้นอยู่กับฮาร์ดแวร์หรืออุปกรณ์
จึงมีไว้สำหรับใช้ภายในพาร์ติชัน /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
ผู้ให้บริการมีหน้าที่ตั้งชื่อและดูแลพร็อพเพอร์ตี้ ดังนั้นให้ทำตามรูปแบบที่แนะนำในขั้นตอนที่ 2 นอกเหนือจากข้อกำหนดของเนมสเปซของผู้ให้บริการ
กฎ SEPolicy และ property_contexts เฉพาะผู้ให้บริการ
คุณกำหนดพร็อพเพอร์ตี้ของผู้ให้บริการได้โดยใช้มาโคร vendor_internal_prop
วางกฎเฉพาะของผู้ให้บริการที่คุณกำหนดไว้ในไดเรกทอรี BOARD_VENDOR_SEPOLICY_DIRS
ตัวอย่างเช่น สมมติว่าคุณกําลังกําหนดพร็อพเพอร์ตี้ faceauth ของผู้ให้บริการใน Coral
ในไฟล์ 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 เป็น API
เพื่อเปลี่ยนชื่อพร็อพเพอร์ตี้ที่มีอยู่ ซึ่งจะคงความเข้ากันได้แบบย้อนหลังโดย
ระบุทั้งชื่อเดิมและชื่อพร็อพเพอร์ตี้ใหม่ โดยคุณสามารถ
ตั้งชื่อเดิมได้โดยใช้ฟิลด์ legacy_prop_name
ในไฟล์ .sysprop
API ที่สร้างขึ้นจะพยายามอ่าน prop_name
และใช้ legacy_prop_name
หากไม่มี prop_name
ตัวอย่างเช่น ขั้นตอนต่อไปนี้จะเปลี่ยนชื่อ awesome_feature_foo_enabled
เป็น foo.awesome_feature.enabled
ในไฟล์ foo.sysprop
module: "android.sysprop.foo"
owner: Platform
prop {
api_name: "is_awesome_feature_enabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "foo.awesome_feature.enabled"
legacy_prop_name: "awesome_feature_foo_enabled"
}
ในโค้ด C++
// is_awesome_feature_enabled() reads "foo.awesome_feature.enabled".
// If it doesn't exist, reads "awesome_feature_foo_enabled" instead
using android::sysprop::foo;
bool enabled = foo::is_awesome_feature_enabled().value_or(false);
โปรดทราบข้อควรระวังต่อไปนี้
ประการแรก คุณเปลี่ยนประเภทของ Sysprop ไม่ได้ เช่น คุณเปลี่ยนพร็อพ
int
เป็นพร็อพstring
ไม่ได้ แต่เปลี่ยนชื่อได้ประการที่ 2 เฉพาะ API การอ่านเท่านั้นที่จะเปลี่ยนไปใช้ชื่อเดิม API การเขียนจะไม่ ย้อนกลับ หาก sysprop เป็นแบบเขียนได้ คุณจะเปลี่ยนชื่อไม่ได้