เพิ่มคุณสมบัติของระบบ

หน้านี้แสดงวิธีการตามรูปแบบบัญญัติสำหรับการเพิ่มหรือกำหนดคุณสมบัติของระบบใน 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

กำหนดขอบเขตการเข้าถึงคุณสมบัติของระบบให้แคบที่สุด ในอดีต การเข้าถึงแบบกว้างๆ ส่งผลให้แอปเสียหายและมีช่องโหว่ด้านความปลอดภัย พิจารณาคำถามต่อไปนี้เมื่อกำหนดขอบเขต:

  • คุณสมบัติของระบบนี้จำเป็นต้องคงอยู่หรือไม่? (ถ้าเป็นเช่นนั้นทำไม?)
  • กระบวนการใดควรมีสิทธิ์เข้าถึงแบบอ่านในคุณสมบัตินี้
  • กระบวนการใดควรมีสิทธิ์เขียนในคุณสมบัตินี้

ใช้คำถามก่อนหน้าและแผนผังการตัดสินใจต่อไปนี้เป็นเครื่องมือในการกำหนดขอบเขตที่เหมาะสมสำหรับการเข้าถึง

Decision tree for determining the scope of access

รูปที่ 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 เป็นไฟล์ที่เขียนได้ คุณจะไม่สามารถเปลี่ยนชื่อได้