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 name
và type
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ànhaudio.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:
group
và subgroup
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áchDanh 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_contexts
ở Bướ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.
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ép và khô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_prop
và get_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ụngstring
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ặcproduct.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}_PROPERTIES
và TARGET_{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
, libbase
và libcutils
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 libbase
và libcutils
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ànhstring
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ó.