เพิ่มพร็อพเพอร์ตี้ของระบบ

หน้านี้มีวิธี 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 เป็น เขียนได้ คุณจะเปลี่ยนชื่อไม่ได้