Thêm thuộc tính hệ thống

Trang này cung cấp phương pháp chuẩn để thêm hoặc xác định thuộc tính hệ thống trong Android, cùng với hướng dẫn tái cấu trúc các thuộc tính hệ thống hiện có. Đảm bảo rằng bạn sử dụng các nguyên tắc khi tái cấu trúc, trừ khi bạn gặp vấn đề tương thích nghiêm trọng có quy định khác.

Bước 1: Xác định thuộc tính hệ thống

Khi bạn thêm thuộc tính hệ thống, hãy quyết định tên cho thuộc tính và liên kết nó với bối cảnh thuộc tính SELinux. Nếu không có bối cảnh hiện có phù hợp, hãy tạo một bối cảnh mới. Tên được sử dụng khi truy cập vào thuộc tính; bối cảnh thuộc tính được sử dụng để kiểm soát khả năng truy cập về mặt SELinux. Tên có thể là bất kỳ chuỗi nào, nhưng AOSP khuyên bạn nên tuân theo định dạng có cấu trúc để làm cho chúng rõ ràng.

Tên tài sản

Sử dụng định dạng này với cách viết hoa snake_case:

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

Sử dụng “” (bị bỏ qua), ro (đối với các thuộc tính chỉ được đặt một lần) hoặc persist (đối với các thuộc tính vẫn tồn tại qua các lần khởi động lại) cho prefix phần tử .

Hãy cẩn thận

Chỉ sử dụng ro khi bạn chắc chắn rằng bạn không cần prefix để có thể ghi được trong tương lai. ** Không chỉ định tiền tố ro .** Thay vào đó, hãy dựa vào sepolicy để đặt prefix ở chế độ chỉ đọc (nói cách khác, chỉ có thể ghi bằng init ).

Chỉ sử dụng persist khi bạn chắc chắn rằng giá trị phải được duy trì trong các lần khởi động lại và việc sử dụng thuộc tính hệ thống là lựa chọn duy nhất của bạn. (Chi tiết xem phần Chuẩn bị .)

Google xem xét nghiêm ngặt các thuộc tính hệ thống có thuộc tính ro hoặc persist .

group thuật ngữ được sử dụng để tổng hợp các thuộc tính liên quan. Nó được dự định là một tên hệ thống con tương tự như tên sử dụng cho audio hoặc telephony . Không sử dụng các thuật ngữ mơ hồ hoặc quá tải như sys , system , dev , default hoặc config .

Thực tế phổ biến là sử dụng tên loại miền của một quy trình có quyền truy cập đọc hoặc ghi độc quyền vào các thuộc tính hệ thống. Ví dụ: đối với các thuộc tính hệ thống mà quy trình vold có quyền truy cập ghi, người ta thường sử dụng vold (tên loại miền cho quy trình) làm tên nhóm.

Nếu cần, hãy thêm subgroup để phân loại thêm các thuộc tính, nhưng tránh các thuật ngữ mơ hồ hoặc quá tải để mô tả phần tử này. (Bạn cũng có thể có nhiều hơn một subgroup .)

Nhiều tên nhóm đã được xác định. Kiểm tra tệp system/sepolicy/private/property_contexts và sử dụng tên nhóm hiện có nếu có thể, thay vì tạo tên mới. Bảng sau đây cung cấp ví dụ về tên nhóm được sử dụng thường xuyên.

Lãnh địa Nhóm (và nhóm con)
liên quan đến bluetooth bluetooth
sysprops từ cmdline hạt nhân boot
sysprops xác định một bản dựng build
liên quan đến điện thoại telephony
liên quan đến âm thanh audio
đồ họa liên quan graphics
liên quan đến vold vold

Phần sau đây xác định cách sử dụng nametype trong ví dụ biểu thức chính quy trước đó.

[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]

  • name xác định thuộc tính hệ thống trong một nhóm.

  • type là phần tử tùy chọn giúp làm rõ loại hoặc mục đích của thuộc tính hệ thống. Ví dụ: thay vì đặt tên sysprop là audio.awesome_feature_enabled hoặc chỉ audio.awesome_feature , hãy đổi tên nó thành audio.awesome_feature.enabled để phản ánh loại thuộc tính hệ thống và mục đích.

Không có quy tắc cụ thể nào về loại phải là gì; đây là những khuyến nghị sử dụng:

  • enabled : Sử dụng nếu loại là thuộc tính hệ thống boolean được sử dụng để bật hoặc tắt một tính năng.
  • config : Sử dụng nếu mục đích là làm rõ rằng thuộc tính hệ thống không thể hiện trạng thái động của hệ thống; nó đại diện cho một giá trị được cấu hình sẵn (ví dụ: thứ chỉ đọc).
  • List : Sử dụng nếu đó là thuộc tính hệ thống có giá trị là danh sách.
  • Timeoutmillis : Sử dụng nếu đó là thuộc tính hệ thống cho giá trị thời gian chờ tính bằng đơn vị ms.

Ví dụ:

  • persist.radio.multisim.config
  • drm.service.enabled

Bối cảnh thuộc tính

Lược đồ ngữ cảnh thuộc tính SELinux mới cho phép có độ chi tiết tốt hơn và tên mô tả nhiều hơn. Tương tự như tên được sử dụng cho tên thuộc tính, AOSP đề xuất định dạng sau:

{group}[_{subgroup}]*_prop

Các điều khoản được định nghĩa như sau:

groupsubgroup có cùng ý nghĩa như được định nghĩa cho biểu thức chính quy mẫu trước đó. Ví dụ: vold_config_prop biểu thị các thuộc tính là cấu hình từ nhà cung cấp và được thiết lập bởi vendor_init , trong khi vold_status_prop hoặc chỉ vold_prop biểu thị các thuộc tính sẽ hiển thị trạng thái hiện tại của vold .

Khi đặt tên bối cảnh thuộc tính, hãy chọn tên phản ánh cách sử dụng chung của thuộc tính. Đặc biệt, hãy tránh các loại thuật ngữ sau:

  • Các thuật ngữ trông quá chung chung và mơ hồ, chẳng hạn như sys , system , default .
  • Các thuật ngữ mã hóa trực tiếp khả năng truy cập: chẳng hạn như exported , apponly , ro , public , private .

Thích cách sử dụng tên như vold_config_prop exported_vold_prop hoặc vold_vendor_writable_prop , v.v.

Kiểu

Loại thuộc tính có thể là một trong những loại sau như được liệt kê trong bảng.

Kiểu Sự định nghĩa
Boolean true hoặc 1 là đúng, false hoặc 0 là sai
số nguyên số nguyên 64 bit có dấu
Số nguyên không dấu số nguyên 64 bit không dấu
Gấp đôi dấu phẩy động có độ chính xác kép
Sợi dây bất kỳ chuỗi UTF-8 hợp lệ nào
liệt kê các giá trị có thể là bất kỳ chuỗi UTF-8 hợp lệ nào không có khoảng trắng
Danh sách trên Dấu phẩy ( , ) được dùng làm dấu phân cách
Danh sách số nguyên [1, 2, 3] được lưu dưới dạng 1,2,3

Trong nội bộ, tất cả các thuộc tính được lưu trữ dưới dạng chuỗi. Bạn có thể thực thi loại này bằng cách chỉ định nó dưới dạng tệp property_contexts . Để biết thêm thông tin, hãy xem property_contextsBước 3 .

Bước 2: Xác định mức độ tiếp cận cần thiết

Có bốn macro trợ giúp xác định một thuộc tính.

Loại trợ năng Nghĩa
system_internal_prop Các thuộc tính chỉ được sử dụng trong /system
system_restricted_prop Các thuộc tính được đọc bên ngoài /system nhưng không được ghi
system_vendor_config_prop Các thuộc tính được đọc bên ngoài /system và chỉ được viết bởi vendor_init
system_public_prop Các thuộc tính được đọc và ghi bên ngoài /system

Phạm vi truy cập vào các thuộc tính hệ thống càng hẹp càng tốt. Trước đây, quyền truy cập rộng rãi đã dẫn đến lỗi ứng dụng và lỗ hổng bảo mật. Hãy xem xét các câu hỏi sau khi xác định phạm vi:

  • Thuộc tính hệ thống này có cần được duy trì không? (nếu vậy thì tại sao?)
  • Quá trình nào nên có quyền truy cập đọc vào thuộc tính này?
  • Quá trình nào nên có quyền truy cập ghi vào thuộc tính này?

Sử dụng các câu hỏi trước và cây quyết định sau làm công cụ để xác định phạm vi truy cập thích hợp.

Decision tree for determining the scope of access

Hình 1. Cây quyết định xác định phạm vi truy cập vào thuộc tính hệ thống

Bước 3: Thêm nó vào hệ thống/sepolicy

Khi truy cập sysprop, SELinux kiểm soát khả năng truy cập của các tiến trình. Sau khi bạn xác định mức độ truy cập được yêu cầu, hãy xác định bối cảnh thuộc tính trong system/sepolicy , cùng với các quy tắc cho phépkhông bao giờ cho phép bổ sung về những quy trình được (và không) được phép đọc hoặc ghi.

Đầu tiên, xác định bối cảnh thuộc tính trong tệp system/sepolicy/public/property.te . Nếu thuộc tính là nội bộ hệ thống, hãy xác định thuộc tính đó trong tệp system/sepolicy/private/property.te . Sử dụng một trong các macro system_[accessibility]_prop([context]) cung cấp khả năng truy cập cần thiết cho thuộc tính hệ thống của bạn. Đây là ví dụ cho tệp system/sepolicy/public/property.te :

system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)

Ví dụ để thêm vào tệp system/sepolicy/private/property.te :

system_internal_prop(audio_baz_prop)

Thứ hai, cấp quyền truy cập đọc và (hoặc) ghi vào ngữ cảnh thuộc tính. Sử dụng macro set_propget_prop để cấp quyền truy cập trong tệp system/sepolicy/public/{domain}.te hoặc system/sepolicy/private/{domain}.te . Sử dụng private bất cứ khi nào có thể; public chỉ phù hợp nếu macro set_prop hoặc get_prop ảnh hưởng đến bất kỳ miền nào bên ngoài miền lõi.

Ví dụ: trong tệp system/sepolicy/private/audio.te :

set_prop(audio, audio_foo_prop)
set_prop(audio, audio_bar_prop)

Ví dụ: trong tệp system/sepolicy/public/domain.te :

get_prop(domain, audio_bar_prop)

Thứ ba, thêm một số quy tắc không bao giờ cho phép để giảm hơn nữa khả năng truy cập trong phạm vi macro. Ví dụ: giả sử rằng bạn đã sử dụng system_restricted_prop vì các thuộc tính hệ thống của bạn phải được các quy trình của nhà cung cấp đọc. Nếu tất cả các quy trình của nhà cung cấp không yêu cầu quyền truy cập đọc và nó chỉ được yêu cầu bởi một nhóm quy trình nhất định (chẳng hạn như vendor_init ), hãy cấm các quy trình của nhà cung cấp không cần quyền truy cập đọc.

Sử dụng cú pháp sau để hạn chế quyền truy cập ghi và đọc:

Để hạn chế quyền truy cập ghi:

neverallow [domain] [context]:property_service set;

Để hạn chế quyền truy cập đọc:

neverallow [domain] [context]:file no_rw_file_perms;

Đặt các quy tắc không bao giờ cho phép trong tệp system/sepolicy/private/{domain}.te nếu quy tắc không bao giờ cho phép bị ràng buộc với một miền cụ thể. Đối với các quy tắc không bao giờ cho phép rộng hơn, hãy sử dụng các tên miền chung như sau nếu thích hợp:

  • system/sepolicy/private/property.te
  • system/sepolicy/private/coredomain.te
  • system/sepolicy/private/domain.te

Trong tệp system/sepolicy/private/audio.te , đặt thông tin sau:

neverallow {
    domain -init -audio
} {audio_foo_prop audio_bar_prop}:property_service set;

Trong tệp system/sepolicy/private/property.te , đặt như sau:

neverallow {
    domain -coredomain -vendor_init
} audio_prop:file no_rw_file_perms;

Lưu ý rằng {domain -coredomain} nắm bắt tất cả quy trình của nhà cung cấp. Vì vậy, {domain -coredomain -vendor_init} có nghĩa là "tất cả các quy trình của nhà cung cấp ngoại trừ vendor_init ."

Cuối cùng, liên kết thuộc tính hệ thống với bối cảnh thuộc tính. Điều này đảm bảo rằng quyền truy cập được cấp và các quy tắc không bao giờ cho phép áp dụng cho bối cảnh thuộc tính cũng được áp dụng cho thuộc tính thực tế. Để thực hiện việc này, hãy thêm một mục nhập vào tệp property_contexts , một tệp mô tả ánh xạ giữa các thuộc tính hệ thống và bối cảnh thuộc tính. Trong tệp này, bạn có thể chỉ định một thuộc tính hoặc tiền tố cho các thuộc tính được ánh xạ vào ngữ cảnh.

Đây là cú pháp để ánh xạ một thuộc tính duy nhất:

[property_name] u:object_r:[context_name]:s0 exact [type]

Đây là cú pháp để ánh xạ tiền tố:

[property_name_prefix] u:object_r:[context_name]:s0 prefix [type]

Bạn có thể tùy ý chỉ định loại thuộc tính, có thể là một trong những loại sau:

  • bool
  • int
  • uint
  • double
  • enum [list of possible values...]
  • string (Sử dụng string cho thuộc tính danh sách.)

Đảm bảo rằng mọi mục nhập đều có loại được chỉ định bất cứ khi nào có thể, vì type được thực thi khi đặt property . Ví dụ sau đây cho thấy cách viết ánh xạ:

# 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

Khi một mục nhập chính xác và một mục nhập tiền tố xung đột, mục nhập chính xác sẽ được ưu tiên. Để biết thêm ví dụ, hãy xem system/sepolicy/private/property_contexts .

Bước 4: Xác định yêu cầu về độ ổn định

Tính ổn định là một khía cạnh khác của thuộc tính hệ thống và nó khác với khả năng truy cập. Tính ổn định là về việc một thuộc tính hệ thống có thể được thay đổi hay không (ví dụ như được đổi tên hoặc thậm chí bị xóa) trong tương lai. Điều này đặc biệt quan trọng khi hệ điều hành Android trở thành mô-đun. Với Treble, các phân vùng hệ thống, nhà cung cấp và sản phẩm có thể được cập nhật độc lập với nhau. Với Mainline, một số phần của HĐH được mô-đun hóa thành các mô-đun có thể cập nhật (trong APEX hoặc APK).

Nếu một thuộc tính hệ thống được sử dụng trên các phần mềm có thể cập nhật, chẳng hạn như trên các phân vùng hệ thống và nhà cung cấp, thì thuộc tính đó phải ổn định. Tuy nhiên, nếu nó chỉ được sử dụng trong một mô-đun Mainline cụ thể, chẳng hạn, bạn có thể thay đổi tên, loại hoặc ngữ cảnh thuộc tính của nó và thậm chí xóa nó.

Đặt các câu hỏi sau để xác định tính ổn định của thuộc tính hệ thống:

  • Thuộc tính hệ thống này có phải do đối tác định cấu hình (hoặc được định cấu hình khác nhau cho mỗi thiết bị) không? Nếu được thì phải ổn định.
  • Thuộc tính hệ thống do AOSP xác định này có mục đích được ghi vào hoặc đọc từ mã (không phải quy trình) tồn tại trong các phân vùng phi hệ thống như vendor.img hoặc product.img ? Nếu được thì phải ổn định.
  • Thuộc tính hệ thống này có được truy cập trên các mô-đun Mainline hoặc trên mô-đun Mainline và phần không thể cập nhật của nền tảng không? Nếu được thì phải ổn định.

Đối với các thuộc tính hệ thống ổn định, hãy xác định chính thức từng thuộc tính là một API và sử dụng API để truy cập thuộc tính hệ thống, như được giải thích trong Bước 6 .

Bước 5: Đặt thuộc tính tại thời điểm xây dựng

Đặt thuộc tính tại thời điểm xây dựng với các biến makefile. Về mặt kỹ thuật, các giá trị được đưa vào {partition}/build.prop . Sau đó init đọc {partition}/build.prop để đặt thuộc tính. Có hai bộ biến như vậy: PRODUCT_{PARTITION}_PROPERTIESTARGET_{PARTITION}_PROP .

PRODUCT_{PARTITION}_PROPERTIES chứa danh sách các giá trị thuộc tính. Cú pháp là {prop}={value} hoặc {prop}?={value} .

{prop}={value} là phép gán bình thường nhằm đảm bảo rằng {prop} được đặt thành {value} ; chỉ có thể thực hiện một nhiệm vụ như vậy cho mỗi thuộc tính.

{prop}?={value} là một phép gán tùy chọn; {prop} chỉ đặt thành {value} nếu không có bất kỳ phép gán {prop}={value} nào. Nếu có nhiều bài tập tùy chọn, bài tập đầu tiên sẽ thắng.

# 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 chứa danh sách các tệp được phát trực tiếp đến {partition}/build.prop . Mỗi tệp chứa danh sách các cặp {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

Để biết thêm chi tiết, hãy xem build/make/core/sysprop.mk .

Bước 6: Truy cập các thuộc tính khi chạy

Tất nhiên, các thuộc tính có thể được đọc và ghi trong thời gian chạy.

Tập lệnh khởi tạo

Các tệp tập lệnh ban đầu (thường là tệp *.rc) có thể đọc một thuộc tính bằng ${prop} hoặc ${prop:-default} , có thể đặt một hành động chạy bất cứ khi nào một thuộc tính trở thành một giá trị cụ thể và có thể ghi các thuộc tính bằng cách sử dụng setprop yêu cầu.

# 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}

lệnh shell getprop và setprop

Bạn có thể sử dụng lệnh shell getprop hoặc setprop tương ứng để đọc hoặc ghi các thuộc tính. Để biết thêm chi tiết, hãy gọi getprop --help hoặc setprop --help .

$ adb shell getprop ro.vndk.version
$
$ adb shell setprop security.perf_harden 0

Sysprop làm API cho C++/Java/Rust

Với sysprop làm API, bạn có thể xác định các thuộc tính hệ thống và sử dụng API được tạo tự động cụ thể và được nhập. scope đặt với Public cũng giúp cung cấp các API được tạo cho các mô-đun xuyên ranh giới và đảm bảo tính ổn định của API. Đây là mẫu của tệp .sysprop , mô-đun Android.bp và mã C++, Java và Rust sử dụng chúng.

# 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);

Để biết thêm thông tin, hãy xem Triển khai các thuộc tính hệ thống dưới dạng API .

Các hàm và phương thức thuộc tính cấp thấp C/C++, Java và Rust

Khi có thể, hãy sử dụng Sysprop làm API ngay cả khi bạn có sẵn các hàm C/C++ hoặc Rust cấp thấp hoặc các phương thức Java cấp thấp.

libc , libbaselibcutils cung cấp các hàm thuộc tính hệ thống C++. libc có API cơ bản, trong khi các hàm libbaselibcutils là các hàm bao. Nếu có thể, hãy sử dụng các hàm sysprop libbase ; chúng thuận tiện nhất và các tệp nhị phân của máy chủ có thể sử dụng các hàm libbase . Để biết thêm chi tiết, hãy xem sys/system_properties.h ( libc ), android-base/properties.h ( libbase ) và cutils/properties.h ( libcutils ).

Lớp android.os.SystemProperties cung cấp các phương thức thuộc tính hệ thống Java.

Mô-đun rustutils::system_properties cung cấp các loại và chức năng thuộc tính hệ thống Rust.

Phụ lục: Thêm thuộc tính dành riêng cho nhà cung cấp

Các đối tác (bao gồm cả nhân viên Google làm việc trong bối cảnh phát triển Pixel) muốn xác định các thuộc tính hệ thống dành riêng cho phần cứng (hoặc dành riêng cho thiết bị). Thuộc tính dành riêng cho nhà cung cấp là thuộc tính thuộc sở hữu của đối tác dành riêng cho phần cứng hoặc thiết bị của riêng họ chứ không phải cho nền tảng. Vì đây là những phụ thuộc vào phần cứng hoặc thiết bị nên chúng được sử dụng trong các phân vùng /vendor hoặc /odm .

Kể từ Project Treble, các thuộc tính nền tảng và thuộc tính nhà cung cấp đã được phân chia hoàn toàn để tránh xung đột. Phần sau đây mô tả cách xác định các thuộc tính của nhà cung cấp và cho biết các thuộc tính của nhà cung cấp nào phải luôn được sử dụng.

Không gian tên trên thuộc tính và tên ngữ cảnh

Tất cả thuộc tính của nhà cung cấp phải bắt đầu bằng một trong các tiền tố sau để tránh xung đột giữa chúng và thuộc tính của các phân vùng khác.

  • 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.

Lưu ý rằng ro.hardware. được phép làm tiền tố nhưng chỉ để tương thích. Đừng sử dụng nó cho các thuộc tính thông thường.

Các ví dụ sau đây đều sử dụng một trong các tiền tố được liệt kê trước đó:

  • vendor.display.primary_red
  • persist.vendor.faceauth.use_disk_cache
  • ro.odm.hardware.platform

Tất cả bối cảnh thuộc tính của nhà cung cấp phải bắt đầu bằng vendor_ . Điều này cũng là để tương thích. Sau đây là những ví dụ:

  • vendor_radio_prop .
  • vendor_faceauth_prop .
  • vendor_usb_prop .

Trách nhiệm của nhà cung cấp là đặt tên và duy trì các thuộc tính, vì vậy hãy làm theo định dạng được đề xuất ở Bước 2 , bên cạnh các yêu cầu về không gian tên của nhà cung cấp.

Các quy tắc và thuộc tính_contexts SEPolicy dành riêng cho nhà cung cấp

Thuộc tính nhà cung cấp có thể được xác định bởi macro vendor_internal_prop . Đặt các quy tắc dành riêng cho nhà cung cấp mà bạn xác định trong thư mục BOARD_VENDOR_SEPOLICY_DIRS . Ví dụ: giả sử bạn đang xác định thuộc tính faceauth của nhà cung cấp trong Coral.

Trong tệp BoardConfig.mk (hoặc trong bất kỳ BoardConfig.mk nào bao gồm), hãy đặt thông tin sau:

BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy

Trong tệp device/google/coral-sepolicy/private/property.te , hãy đặt thông tin sau:

vendor_internal_prop(vendor_faceauth_prop)

Trong tệp device/google/coral-sepolicy/private/property_contexts , hãy đặt thông tin sau:

vendor.faceauth.trace u:object_r:vendor_faceauth_prop:s0 exact bool

Hạn chế của tài sản nhà cung cấp

Vì các phân vùng hệ thống và sản phẩm không thể phụ thuộc vào nhà cung cấp, nên không bao giờ cho phép truy cập các thuộc tính của nhà cung cấp từ các phân vùng system , system-ext hoặc product .

Phụ lục: Đổi tên thuộc tính hiện có

Khi bạn phải ngừng sử dụng một thuộc tính và chuyển sang một thuộc tính mới, hãy sử dụng Sysprop làm API để đổi tên các thuộc tính hiện có của bạn. Điều này duy trì khả năng tương thích ngược bằng cách chỉ định cả tên cũ và tên thuộc tính mới. Cụ thể, bạn có thể đặt tên kế thừa theo trường legacy_prop_name trong tệp .sysprop . API được tạo sẽ cố đọc prop_name và sử dụng legacy_prop_name nếu prop_name không tồn tại.

Ví dụ: các bước sau đổi tên awesome_feature_foo_enabled thành foo.awesome_feature.enabled .

Trong tệp 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"
}

Trong mã 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);

Lưu ý những lưu ý sau:

  • Đầu tiên, bạn không thể thay đổi loại sysprop. Ví dụ: bạn không thể biến int prop thành string prop. Bạn chỉ có thể thay đổi tên.

  • Thứ hai, chỉ API đọc mới quay lại tên cũ. API ghi không quay trở lại. Nếu sysprop là một cái có thể ghi được, bạn không thể đổi tên nó.