หน้านี้แสดงวิธีการตามรูปแบบบัญญัติสำหรับการเพิ่มหรือกำหนดคุณสมบัติของระบบใน 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
เพื่อจัดหมวดหมู่คุณสมบัติเพิ่มเติม แต่หลีกเลี่ยงคำที่คลุมเครือหรือมากเกินไปในการอธิบายองค์ประกอบนี้ (คุณสามารถมี subgroup
ได้มากกว่าหนึ่งกลุ่ม)
มีการกำหนดชื่อกลุ่มหลายชื่อแล้ว ตรวจสอบไฟล์ system/sepolicy/private/property_contexts
และใช้ชื่อกลุ่มที่มีอยู่หากเป็นไปได้ แทนที่จะสร้างชื่อใหม่ ตารางต่อไปนี้แสดงตัวอย่างชื่อกลุ่มที่ใช้บ่อย
โดเมน | กลุ่ม (และกลุ่มย่อย) |
---|---|
ที่เกี่ยวข้องกับบลูทูธ | bluetooth |
sysprops จากเคอร์เนล cmdline | boot |
sysprops ที่ระบุบิลด์ | build |
ที่เกี่ยวข้องกับโทรศัพท์ | telephony |
ที่เกี่ยวข้องกับเสียง | audio |
ที่เกี่ยวข้องกับกราฟิก | graphics |
เกี่ยวข้องกับโวลด์ | vold |
ข้อมูลต่อไปนี้จะกำหนดการใช้ name
และ type
ใน ตัวอย่าง regex ก่อนหน้า
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
ระบุคุณสมบัติของระบบภายในกลุ่มtype
เป็นองค์ประกอบเสริมที่ให้ความกระจ่างประเภทหรือจุดประสงค์ของคุณสมบัติระบบ ตัวอย่างเช่น แทนที่จะตั้งชื่อ sysprop เป็นaudio.awesome_feature_enabled
หรือเพียงaudio.awesome_feature
ให้เปลี่ยนชื่อเป็นaudio.awesome_feature.enabled
เพื่อให้สะท้อนถึงประเภทคุณสมบัติของระบบและจุดประสงค์
ไม่มีกฎเฉพาะเจาะจงว่าต้องเป็นประเภทใด นี่คือคำแนะนำการใช้งาน:
-
enabled
: ใช้หากประเภทเป็นคุณสมบัติระบบบูลีนที่ใช้ในการเปิดหรือปิดคุณสมบัติ -
config
: ใช้ถ้าจุดประสงค์คือการชี้แจงว่าคุณสมบัติของระบบ ไม่ได้ แสดงถึงสถานะไดนามิกของระบบ มันแสดงถึงค่าที่กำหนดไว้ล่วงหน้า (เช่น สิ่งที่อ่านอย่างเดียว) -
List
: ใช้หากเป็นคุณสมบัติของระบบที่มีค่าเป็นรายการ -
Timeoutmillis
: ใช้หากเป็นคุณสมบัติของระบบสำหรับค่าการหมดเวลาในหน่วยของ ms
ตัวอย่าง:
-
persist.radio.multisim.config
-
drm.service.enabled
บริบทของทรัพย์สิน
รูปแบบบริบทคุณสมบัติ SELinux ใหม่ช่วยให้มีรายละเอียดปลีกย่อยและชื่อที่สื่อความหมายมากขึ้น คล้ายกับสิ่งที่ใช้สำหรับชื่อคุณสมบัติ AOSP แนะนำรูปแบบต่อไปนี้:
{group}[_{subgroup}]*_prop
ข้อกำหนดมีการกำหนดดังต่อไปนี้:
group
และ subgroup
มีความหมายเดียวกันกับที่กำหนดไว้สำหรับ regex ตัวอย่าง ก่อนหน้า ตัวอย่างเช่น 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 ที่ถูกต้องใดๆ |
แจกแจง | ค่าอาจเป็นสตริง UTF-8 ที่ถูกต้องใดๆ ก็ได้โดยไม่มีช่องว่าง |
รายการข้างต้น | เครื่องหมายจุลภาค ( , ) ใช้เป็นตัวคั่นรายการจำนวนเต็ม [1, 2, 3] จะถูกจัดเก็บเป็น 1,2,3 |
ภายใน คุณสมบัติทั้งหมดจะถูกจัดเก็บเป็นสตริง คุณสามารถบังคับใช้ประเภทได้โดยระบุเป็นไฟล์ property_contexts
สำหรับข้อมูลเพิ่มเติม โปรดดู property_contexts
ใน ขั้นตอนที่ 3
ขั้นตอนที่ 2: การกำหนดระดับการเข้าถึงที่จำเป็น
มีแมโครตัวช่วยสี่ตัวที่กำหนดคุณสมบัติ
ประเภทการเข้าถึง | ความหมาย |
---|---|
system_internal_prop | คุณสมบัติที่ใช้ใน /system เท่านั้น |
system_restricted_prop | คุณสมบัติที่อ่านภายนอก /system แต่ไม่ได้เขียน |
system_vendor_config_prop | คุณสมบัติที่อ่านภายนอก /system และเขียนโดย vendor_init เท่านั้น |
system_public_prop | คุณสมบัติที่อ่านและเขียนภายนอก /system |
กำหนดขอบเขตการเข้าถึงคุณสมบัติของระบบให้แคบที่สุด ในอดีต การเข้าถึงแบบกว้างๆ ส่งผลให้แอปเสียหายและมีช่องโหว่ด้านความปลอดภัย พิจารณาคำถามต่อไปนี้เมื่อกำหนดขอบเขต:
- คุณสมบัติของระบบนี้จำเป็นต้องคงอยู่หรือไม่? (ถ้าเป็นเช่นนั้นทำไม?)
- กระบวนการใดควรมีสิทธิ์เข้าถึงแบบอ่านในคุณสมบัตินี้
- กระบวนการใดควรมีสิทธิ์เขียนในคุณสมบัตินี้
ใช้คำถามก่อนหน้าและแผนผังการตัดสินใจต่อไปนี้เป็นเครื่องมือในการกำหนดขอบเขตที่เหมาะสมสำหรับการเข้าถึง
รูปที่ 1 แผนผังการตัดสินใจสำหรับกำหนดขอบเขตการเข้าถึงคุณสมบัติของระบบ
ขั้นตอนที่ 3: เพิ่มลงในระบบ/sepolicy
เมื่อเข้าถึง sysprop SELinux จะควบคุมการเข้าถึงกระบวนการต่างๆ หลังจากที่คุณกำหนดระดับของการเข้าถึงที่ต้องการแล้ว ให้กำหนดบริบทของคุณสมบัติภายใต้ system/sepolicy
พร้อมด้วยกฎ การอนุญาต และ 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)
ประการที่สาม เพิ่มกฎ 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 บางส่วนของ OS จะถูกทำให้เป็นโมดูลเป็นโมดูลที่อัปเดตได้ (ใน APEX หรือ APK)
หากคุณสมบัติของระบบมีไว้สำหรับใช้กับซอฟต์แวร์ที่สามารถอัพเดตได้ เช่น ข้ามพาร์ติชันระบบและผู้จำหน่าย คุณสมบัตินั้นจะต้องเสถียร อย่างไรก็ตาม หากใช้เฉพาะภายในโมดูล Mainline ที่เฉพาะเจาะจง คุณสามารถเปลี่ยนชื่อ ประเภท หรือบริบทคุณสมบัติ และแม้แต่ลบออกได้
ถามคำถามต่อไปนี้เพื่อพิจารณาความเสถียรของคุณสมบัติระบบ:
- คุณสมบัติระบบนี้มีจุดมุ่งหมายให้กำหนดค่าโดยพันธมิตร (หรือกำหนดค่าแตกต่างกันตามอุปกรณ์) หรือไม่ ถ้าใช่มันก็ต้องมั่นคง
- คุณสมบัติระบบที่กำหนด AOSP นี้มีวัตถุประสงค์เพื่อเขียนหรืออ่านจากโค้ด (ไม่ใช่ประมวลผล) ที่มีอยู่ในพาร์ติชันที่ไม่ใช่ระบบเช่น
vendor.img
หรือproduct.img
หรือไม่ ถ้าใช่มันก็ต้องมั่นคง - คุณสมบัติของระบบนี้มีการเข้าถึงผ่านโมดูล Mainline หรือผ่านโมดูล Mainline และส่วนที่ไม่สามารถอัปเดตได้ของแพลตฟอร์มหรือไม่ ถ้าใช่มันก็ต้องมั่นคง
สำหรับคุณสมบัติของระบบที่เสถียร ให้กำหนดแต่ละรายการอย่างเป็นทางการว่าเป็น API และใช้ API เพื่อเข้าถึงคุณสมบัติของระบบ ตามที่อธิบายไว้ใน ขั้นตอนที่ 6
ขั้นตอนที่ 5: การตั้งค่าคุณสมบัติ ณ เวลาสร้าง
ตั้งค่าคุณสมบัติ ณ เวลาสร้างด้วยตัวแปร 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
ขั้นตอนที่ 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}
คำสั่งเชลล์ 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 ที่สร้างขึ้นอัตโนมัติซึ่งเป็นรูปธรรมและพิมพ์ได้ การตั้ง 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
นำเสนอฟังก์ชันและประเภทของคุณสมบัติระบบสนิม
ภาคผนวก: การเพิ่มคุณสมบัติเฉพาะของผู้ขาย
พันธมิตร (รวมถึง 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
ตัวอย่างเช่น สมมติว่าคุณกำลังกำหนดคุณสมบัติการตรวจสอบผู้ขายในปะการัง
ในไฟล์ 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
prop ให้เป็นstring
prop ได้ คุณสามารถเปลี่ยนชื่อได้เท่านั้นประการที่สอง เฉพาะ API การอ่านเท่านั้นที่จะกลับไปใช้ชื่อเดิม API การเขียนจะไม่ถอยกลับ หาก sysprop เป็นไฟล์ที่เขียนได้ คุณจะไม่สามารถเปลี่ยนชื่อได้