หน้านี้มีวิธี Canonical สำหรับการเพิ่มหรือกำหนดพร็อพเพอร์ตี้ของระบบ ใน Android ด้วยหลักเกณฑ์ในการเปลี่ยนโครงสร้างภายในพร็อพเพอร์ตี้ของระบบที่มีอยู่ ตรวจสอบให้แน่ใจว่าคุณใช้หลักเกณฑ์เมื่อคุณเปลี่ยนโครงสร้างภายในโค้ด ยกเว้นในกรณีที่คุณมี ปัญหาความเข้ากันได้ที่เป็นตัวกำหนดเนื้อหาอื่นๆ
ขั้นตอนที่ 1: กำหนดพร็อพเพอร์ตี้ของระบบ
เมื่อเพิ่มพร็อพเพอร์ตี้ของระบบ ให้ตั้งชื่อพร็อพเพอร์ตี้แล้วเชื่อมโยง พร้อมบริบทพร็อพเพอร์ตี้ SELinux หากไม่มีบริบทที่เหมาะสม สร้างใหม่ ชื่อจะใช้เมื่อเข้าถึงพร็อพเพอร์ตี้ ที่พัก จะมีการใช้บริบทเพื่อควบคุมการช่วยเหลือพิเศษใน SELinux ชื่อสามารถเป็นอะไรก็ได้ แต่ AOSP แนะนำให้คุณทำตามรูปแบบที่มีโครงสร้างเพื่อให้เห็นภาพชัดเจน
ชื่อพร็อพเพอร์ตี้
ใช้รูปแบบนี้ร่วมกับตัวพิมพ์เล็ก/ใหญ่ snake_case:
[{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
เพื่อจัดหมวดหมู่ที่พักเพิ่มเติม แต่ให้หลีกเลี่ยง
คำกำกวมหรือมากเกินไปที่จะอธิบายองค์ประกอบนี้ (คุณยังสามารถ
มากกว่า 1 subgroup
)
ชื่อกลุ่มหลายชื่อได้รับการกำหนดแล้ว ตรวจสอบ
system/sepolicy/private/property_contexts
ไฟล์และใช้ชื่อกลุ่มที่มีอยู่
หากเป็นไปได้ แทนที่จะสร้างวิดีโอใหม่ ตารางต่อไปนี้แสดง
ตัวอย่างชื่อกลุ่มที่ใช้บ่อย
โดเมน | กลุ่ม (และกลุ่มย่อย) |
---|---|
เกี่ยวกับบลูทูธ | bluetooth |
sysprops จากเคอร์เนล cmdline | boot |
sysprops ที่ระบุบิลด์ | build
|
เกี่ยวกับโทรศัพท์ | telephony |
เกี่ยวกับเสียง | audio |
เกี่ยวกับกราฟิก | graphics |
เกี่ยวข้องกับ vold | vold |
ต่อไปนี้จะกำหนดการใช้ name
และ type
ในนิพจน์ทั่วไปก่อนหน้า
ตัวอย่าง
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
ระบุพร็อพเพอร์ตี้ของระบบภายในกลุ่มtype
เป็นองค์ประกอบที่ไม่บังคับซึ่งชี้แจงประเภทหรือ Intent ของ พร็อพเพอร์ตี้ของระบบ ตัวอย่างเช่น แทนที่จะตั้งชื่อ sysprop เป็นaudio.awesome_feature_enabled
หรือเพียงaudio.awesome_feature
เปลี่ยนชื่อเป็นaudio.awesome_feature.enabled
เพื่อแสดงประเภทพร็อพเพอร์ตี้ของระบบและ Intent
โดยไม่มีกฎเฉพาะเกี่ยวกับประเภท นี่คือการใช้งาน คำแนะนำ:
enabled
: ใช้ในกรณีที่ประเภทเป็นพร็อพเพอร์ตี้ระบบบูลีนที่ใช้เปลี่ยน เปิดหรือปิดฟีเจอร์config
: ใช้ในกรณีที่ Intent เป็นการชี้แจงพร็อพเพอร์ตี้ของระบบ ไม่แสดงถึงสถานะแบบไดนามิกของระบบ ก็แสดงถึง ค่าที่กำหนดค่าไว้ล่วงหน้า (เช่น แบบอ่านอย่างเดียว)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: เพิ่มลงในระบบ/นโยบาย
เมื่อเข้าถึง 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)
ขั้นที่สอง ให้สิทธิ์อ่านและ (หรือ) เขียนบริบทของพร็อพเพอร์ตี้ ใช้ 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)
ข้อ 3 เพิ่มกฎ ไม่อนุญาตบางอย่างเพื่อลดการเข้าถึงได้ง่าย
ที่กำหนดขอบเขตโดยมาโคร ตัวอย่างเช่น สมมติว่าคุณเคยใช้
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
หาก
กฎ notallow จะถูกเชื่อมโยงกับโดเมนที่ระบุ สำหรับกฎ 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
"
สุดท้าย ให้เชื่อมโยงพร็อพเพอร์ตี้ของระบบกับบริบทของพร็อพเพอร์ตี้ วิธีนี้ช่วยให้มั่นใจว่า
สิทธิ์ที่ได้รับอนุญาตและกฎ "ไม่อนุญาต" ที่ใช้
บริบทพร็อพเพอร์ตี้จะใช้กับพร็อพเพอร์ตี้จริง ในการดำเนินการนี้ ให้เพิ่มรายการลงใน
ไฟล์ 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 ผู้ให้บริการ และพาร์ติชันผลิตภัณฑ์สามารถอัปเดตแยกกันได้ ด้วย เมนไลน์ บางส่วนของระบบปฏิบัติการได้รับการปรับปรุงเป็นโมดูลที่อัปเดตข้อมูลได้ (ใน APEXes หรือ APK)
เช่น หากพร็อพเพอร์ตี้ของระบบมีไว้สำหรับใช้ในซอฟต์แวร์ส่วนต่างๆ ที่อัปเดตได้ เช่น ข้ามพาร์ติชันของระบบและผู้ให้บริการ ตัวแปรนี้ต้องมีความเสถียร แต่หากใช้ ภายในเท่านั้น เช่น โมดูลเมนไลน์ที่เฉพาะเจาะจง คุณสามารถเปลี่ยนชื่อโมดูลได้ ประเภท หรือบริบทของพร็อพเพอร์ตี้ และแม้แต่ลบออก
ถามคำถามต่อไปนี้เพื่อระบุความเสถียรของพร็อพเพอร์ตี้ระบบ
- พร็อพเพอร์ตี้ของระบบนี้มีไว้เพื่อกำหนดค่าโดยพาร์ทเนอร์ (หรือกำหนดค่าไว้หรือไม่) แตกต่างกันในแต่ละอุปกรณ์) หากใช่ ไฟล์ต้องเสถียร
- พร็อพเพอร์ตี้ของระบบที่กำหนดโดย AOSP นี้ต้องการเขียนหรืออ่านจาก
โค้ด (ไม่ใช่กระบวนการ) ที่มีอยู่ในพาร์ติชันที่ไม่ใช่ระบบ เช่น
vendor.img
หรือproduct.img
ใช่ไหม หากใช่ ไฟล์ต้องเสถียร - เข้าถึงพร็อพเพอร์ตี้ของระบบนี้จากโมดูลเมนไลน์หรือข้ามเมนไลน์ และส่วนที่ไม่สามารถอัปเดตได้ของแพลตฟอร์ม หากใช่ ไฟล์ต้องเสถียร
สำหรับพร็อพเพอร์ตี้ของระบบที่เสถียร ให้กำหนดแต่ละรายการเป็น 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 รายการใช้การมอบหมายดังกล่าวได้เพียง 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: เข้าถึงพร็อพเพอร์ตี้ขณะรันไทม์
อ่านและเขียนพร็อพเพอร์ตี้ขณะรันไทม์ได้
สคริปต์เริ่มต้น
ไฟล์สคริปต์ 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}
คำสั่ง Shell getprop และ setprop
คุณใช้คำสั่ง Shell 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 ที่สร้างขึ้นโดยอัตโนมัติได้
ที่เป็นรูปธรรมและพิมพ์ไป การตั้งค่า 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 หากเป็นไปได้ ให้ใช้ฟังก์ชัน sysprop ของ libbase
พวกเขาคือ
ซึ่งสะดวกที่สุด และไบนารีของโฮสต์สามารถใช้ฟังก์ชัน 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 ของผู้ให้บริการในปะการัง
ในไฟล์ 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 การอ่านเท่านั้นที่กลับไปใช้ชื่อเดิม Write API ไม่ สำรอง หาก sysprop เป็น เขียนได้ คุณจะเปลี่ยนชื่อไม่ได้