Trang này cung cấp một phương thức chính tắc để thêm hoặc xác định các thuộc tính hệ thống trong Android, kèm theo hướng dẫn về cách 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 tuân thủ các nguyên tắc khi tái cấu trúc, trừ phi bạn gặp phải vấn đề nghiêm trọng về khả năng tương thích khiến bạn không thể làm như vậy.
Bước 1: Xác định thuộc tính hệ thống
Khi bạn thêm một thuộc tính hệ thống, hãy quyết định tên cho thuộc tính đó và liên kết thuộc tính đó với một ngữ cảnh thuộc tính SELinux. Nếu không có ngữ cảnh hiện tại phù hợp, hãy tạo một ngữ cảnh mới. Tên này được dùng khi truy cập vào thuộc tính; ngữ cảnh thuộc tính được dùng để kiểm soát khả năng truy cập theo SELinux. Tên có thể là bất kỳ chuỗi nào, nhưng AOSP đề xuất bạn tuân theo một định dạng có cấu trúc để giúp tên rõ ràng.
Tên thuộc tính
Hãy dùng định dạng này với kiểu viết 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 sau khi khởi động lại) cho phần tử prefix
.
Chú ý
Chỉ sử dụng ro
khi bạn chắc chắn rằng bạn không cần prefix
có thể ghi trong tương lai. ** Đừng chỉ định tiền tố ro
. Thay vào đó, hãy dựa vào sepolicy để đặt prefix
ở chế độ chỉ có thể đọ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 quá trình khởi động lại và việc sử dụng các thuộc tính hệ thống là lựa chọn duy nhất của bạn.
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
.
Thuật ngữ group
được dùng để tổng hợp các thuộc tính có liên quan. Đây là tên hệ thống con có cách sử dụng tương tự như 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ông thường, bạn nên dùng tên của loại miền của một quy trình có quyền đọc hoặc ghi độc quyền đối với 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 ghi, bạn thường dùng vold
(tên của 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 dùng 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 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 nhóm mới. Bảng sau đây cung cấp ví dụ về các tên nhóm thường dùng.
Miền | Nhóm (và nhóm con) |
---|---|
có liên quan đến Bluetooth | bluetooth |
sysprops từ dòng lệnh kernel | boot |
sysprop xác định bản dựng | build
|
liên quan đến điện thoại | telephony |
liên quan đến âm thanh | audio |
đồ hoạ có liên quan | graphics |
vold liên quan | vold |
Sau đây xác định việc sử dụng name
và type
trong ví dụ về biểu thức chính quy trước đó.
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
name
xác định một thuộc tính hệ thống trong một nhóm.type
là một phần tử không bắt buộc, 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 cho một sysprop làaudio.awesome_feature_enabled
hoặc chỉaudio.awesome_feature
, hãy đổi tên thànhaudio.awesome_feature.enabled
để phản ánh loại và mục đích của thuộc tính hệ thống.
Không có quy tắc cụ thể nào về loại phải là gì; đây là các đề xuất sử dụng:
enabled
: Sử dụng nếu loại này là một thuộc tính hệ thống boolean 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 biểu thị trạng thái động của hệ thống; thuộc tính này biểu thị một giá trị được định cấu hình trước (ví dụ: một thứ chỉ có thể đọc).List
: Sử dụng nếu đó là một thuộc tính hệ thống có giá trị là một danh sách.Timeoutmillis
: Sử dụng nếu đó là một thuộc tính hệ thống cho giá trị thời gian chờ theo đơn vị mili giây.
Ví dụ:
persist.radio.multisim.config
drm.service.enabled
Bối cảnh của cơ sở lưu trú
Lược đồ ngữ cảnh thuộc tính SELinux mới cho phép có độ chi tiết cao hơn và tên mô tả hơn. Tương tự như định dạng được dùng cho tên thuộc tính, AOSP đề xuất định dạng sau:
{group}[_{subgroup}]*_prop
Các thuật ngữ này được định nghĩa như sau:
group
và subgroup
có cùng ý nghĩa như được xác định 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 của một nhà cung cấp và được vendor_init
đặt, 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 cho một bối cảnh thuộc tính, hãy chọn tên phản ánh việc sử dụng chung các thuộc tính. Đặc biệt, hãy tránh những loại từ sau:
- Những cụm từ có vẻ quá chung chung và mơ hồ, chẳng hạn như
sys
,system
,default
. - Các thuật ngữ mã hoá trực tiếp khả năng hỗ trợ tiếp cận: chẳng hạn như
exported
,apponly
,ro
,public
,private
.
Ưu tiên sử dụng tên như vold_config_prop
thay vì exported_vold_prop
hoặc vold_vendor_writable_prop
.
Loại
Một loại tài sản có thể là một trong những loại sau đây như được liệt kê trong bảng.
Loại | Định nghĩa |
---|---|
Boolean | true hoặc 1 cho đúng, false hoặc 0 cho sai |
Số nguyên | số nguyên 64 bit có dấu |
Số nguyên không dấu | số nguyên 64 bit chưa ký |
Đôi | dấu phẩy động có độ chính xác gấp đôi |
Chuỗi | mọi chuỗi UTF-8 hợp lệ |
enum | 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 trữ dưới dạng 1,2,3 |
Về nội bộ, tất cả các thuộc tính đều được lưu trữ dưới dạng chuỗi. Bạn có thể thực thi loại bằng cách chỉ định loại đó làm tệp property_contexts
. Để biết thêm thông tin, hãy xem property_contexts
trong Bước 3.
Bước 2: Xác định các cấp độ hỗ trợ tiếp cận bắt buộc
Có 4 macro trợ giúp xác định một thuộc tính.
Loại hỗ trợ tiếp cận | Ý nghĩa |
---|---|
system_internal_prop |
Các thuộc tính chỉ được dùng ở /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 ghi bằng 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 tình trạng ứng dụng bị lỗi và có lỗ hổng bảo mật. Hãy cân nhắc những 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 có thì tại sao?)
- Quy trình nào cần có quyền đọc đối với tài sản này?
- Quy trình nào cần có quyền ghi vào tài sản này?
Hãy sử dụng các câu hỏi trước đó và cây quyết định sau đây làm công cụ để xác định phạm vi truy cập phù hợp.
Hình 1. Cây quyết định để xác định phạm vi truy cập vào các thuộc tính hệ thống
Bước 3: Thêm vào system/sepolicy
Khi truy cập vào sysprop, SELinux sẽ kiểm soát khả năng truy cập của các quy trình. Sau khi bạn xác định cấp độ hỗ trợ tiếp cận cần thiết, hãy xác định các ngữ cảnh thuộc tính trong system/sepolicy
, cùng với các quy tắc allow (cho phép) và neverallow (không bao giờ cho phép) bổ sung về những gì các quy trình được (và không được) phép đọc hoặc ghi.
Trước tiên, hãy xác định ngữ 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 hỗ trợ tiếp cận cần thiết cho thuộc tính hệ thống của bạn. Đây là ví dụ về tệp system/sepolicy/public/property.te
:
system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)
Ví dụ về cách thêm vào tệp system/sepolicy/private/property.te
:
system_internal_prop(audio_baz_prop)
Thứ hai, cấp quyền đọc và (hoặc) ghi cho bối cảnh tài sản. 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 chính.
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, hãy thêm một số quy tắc neverallow để giảm thêm khả năng tiếp cận được xác định phạm vi theo macro. Ví dụ: giả sử bạn đã sử dụng system_restricted_prop
vì các quy trình của nhà cung cấp phải đọc các thuộc tính hệ thống của bạn. Nếu không phải tất cả các quy trình của nhà cung cấp đều cần quyền đọc và chỉ một số quy trình nhất định (chẳng hạn như vendor_init
) cần quyền này, hãy cấm các quy trình của nhà cung cấp không cần quyền đọc.
Sử dụng cú pháp sau để hạn chế quyền ghi và đọc:
Cách hạn chế quyền ghi:
neverallow [domain] [context]:property_service set;
Cách hạn chế quyền đọc:
neverallow [domain] [context]:file no_rw_file_perms;
Đặt các quy tắc neverallow trong tệp system/sepolicy/private/{domain}.te
nếu quy tắc neverallow được liên kết với một miền cụ thể. Đối với các quy tắc neverallow rộng hơn, hãy sử dụng các miền chung như sau khi 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
, hãy đặt nội dung sau:
neverallow {
domain -init -audio
} {audio_foo_prop audio_bar_prop}:property_service set;
Trong tệp system/sepolicy/private/property.te
, hãy đặt nội dung sau:
neverallow {
domain -coredomain -vendor_init
} audio_prop:file no_rw_file_perms;
Xin lưu ý rằng {domain -coredomain}
ghi lại tất cả cá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, hãy liên kết một thuộc tính hệ thống với ngữ 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 neverallow được áp dụng cho ngữ cảnh thuộc tính sẽ được áp dụng cho các thuộc tính thực tế. Để thực hiện việc này, hãy thêm một mục vào tệp property_contexts
, đây là tệp mô tả mối liên kết giữa các thuộc tính hệ thống và ngữ cảnh thuộc tính. Trong tệp này, bạn có thể chỉ định một thuộc tính duy nhất hoặc một tiền tố cho các thuộc tính sẽ được liên kết vào một ngữ cảnh.
Đây là cú pháp để liên kết 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ạ một tiền tố:
[property_name_prefix] u:object_r:[context_name]:s0 prefix [type]
Bạn có thể tuỳ ý chỉ định loại tài sản. Loại tài sản 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 các 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 mộ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. Để xem thêm ví dụ, hãy xem system/sepolicy/private/property_contexts
.
Bước 4: Xác định các yêu cầu về độ ổn định
Tính ổn định là một khía cạnh khác của các thuộc tính hệ thống và khác với khả năng tiếp cận. Tính ổn định là việc một thuộc tính hệ thống có thể thay đổi (ví dụ: đổi tên hoặc thậm chí xoá) trong tương lai hay không. Điều này đặc biệt quan trọng khi hệ điều hành Android trở thành hệ điều hành dạng 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ệ điều hành được mô-đun hoá dưới dạng 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 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 chỉ dùng trong một mô-đun Mainline cụ thể, chẳng hạn như, bạn có thể thay đổi tên, loại hoặc ngữ cảnh thuộc tính của mô-đun đó, thậm chí xoá mô-đun.
Hãy đặt những câu hỏi sau để xác định độ ổn định của một thuộc tính hệ thống:
- Đối tác có định cấu hình thuộc tính hệ thống này không (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.
- Liệu thuộc tính hệ thống do AOSP xác định này có đượ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 không phải hệ thống như
vendor.img
hoặcproduct.img
không? Nếu có, thì phải ổn định. - Bạn có truy cập vào thuộc tính hệ thống này trên các mô-đun Mainline hay trên một 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 chính thức xác định từng thuộc tính dưới dạng một API và sử dụng API để truy cập vào thuộc tính hệ thống, như giải thích trong Bước 6.
Bước 5: Đặt các thuộc tính tại thời điểm tạo
Đặt các thuộc tính tại thời gian xây dựng bằng các biến makefile. Về mặt kỹ thuật, các giá trị được tích hợp vào {partition}/build.prop
. Sau đó, init
sẽ đọc {partition}/build.prop
để thiết lập các thuộc tính. Có hai nhóm 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à một phép gán thông thường, đảm bảo rằng {prop}
được đặt thành {value}
; chỉ có thể có một phép gán như vậy cho mỗi thuộc tính.
{prop}?={value}
là một giá trị tuỳ chọn được chỉ định; {prop}
chỉ đặt thành {value}
nếu không có giá trị được chỉ định {prop}={value}
nào. Nếu có nhiều chỉ định không bắt buộc, thì chỉ định đầu tiên sẽ được áp dụ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 một 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 thông tin, hãy xem build/make/core/sysprop.mk
.
Bước 6: Truy cập vào các thuộc tính trong thời gian chạy
Bạn có thể đọc và ghi các thuộc tính trong thời gian chạy.
Tập lệnh khởi động
Các tệp tập lệnh khởi động (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 thao tác 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 lệnh 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}
Lệnh shell getprop và setprop
Bạn có thể dùng các lệnh shell getprop
hoặc setprop
để đọc hoặc ghi các thuộc tính tương ứng. Để 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 dưới dạng 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. Việc thiết lập scope
bằng Public
cũng giúp các API được tạo có sẵn cho các mô-đun trên các ranh giới và đảm bảo tính ổn định của API. Sau đây là ví dụ về tệp .sysprop
, mô-đun Android.bp
và mã C++, Java và Rust bằng cách sử dụng các tệp này.
# 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 phần Triển khai các thuộc tính hệ thống dưới dạng API.
Các phương thức và hàm 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ó 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 trình bao bọc. Nếu có thể, hãy sử dụng các hàm sysprop libbase
; đây là các hàm tiện lợi nhất và các tệp nhị phân máy chủ có thể sử dụng các hàm libbase
. Để biết thêm thông tin 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 hàm và loại thuộc tính hệ thống Rust.
Phụ lục: Thêm các 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ị).
Các thuộc tính dành riêng cho nhà cung cấp là những thuộc tính thuộc sở hữu của đối tác, chỉ có trên phần cứng hoặc thiết bị của riêng họ, chứ không phải trên nền tảng. Vì đây là phần cứng hoặc phụ thuộc vào thiết bị, nên chúng được 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 tách 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 bạn phải luôn sử dụng những thuộc tính nào của nhà cung cấp.
Không gian tên trên tên tài sản và bối cảnh
Tất cả cá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 để ngăn chặn xung đột giữa các thuộc tính đó và các 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.
Xin lưu ý rằng ro.hardware.
được phép dùng làm tiền tố, nhưng chỉ để tương thích.
Đừng sử dụng thuộc tính này cho các tài sản thông thường.
Tất cả các ví dụ sau đây đều sử dụng một trong các tiền tố được liệt kê ở trên:
vendor.display.primary_red
persist.vendor.faceauth.use_disk_cache
ro.odm.hardware.platform
Tất cả ngữ 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 nhằm mục đích tương thích. Sau đây là một số ví dụ:
vendor_radio_prop
.vendor_faceauth_prop
.vendor_usb_prop
.
Nhà cung cấp có trách nhiệm đặt tên và duy trì các thuộc tính, vì vậy, hãy tuân theo định dạng được đề xuất trong Bước 2, ngoài các yêu cầu về không gian tên của nhà cung cấp.
Các quy tắc SEPolicy và property_contexts dành riêng cho nhà cung cấp
Bạn có thể xác định các thuộc tính của nhà cung cấp bằng 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 một 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), hãy đặt nội dung sau:
BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy
Trong tệp device/google/coral-sepolicy/private/property.te
, hãy đặt nội dung sau:
vendor_internal_prop(vendor_faceauth_prop)
Trong tệp device/google/coral-sepolicy/private/property_contexts
, hãy đặt nội dung sau:
vendor.faceauth.trace u:object_r:vendor_faceauth_prop:s0 exact bool
Giới hạn đối với các thuộc tính của 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 vào 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 tài sản 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ó. Đ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 cũ bằng trường legacy_prop_name
trong tệp .sysprop
. API được tạo sẽ cố gắng đọ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 đây sẽ đổ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);
Xin lưu ý những điểm sau:
Trước tiên, bạn không thể thay đổi loại sysprop. Ví dụ: bạn không thể chuyển một prop
int
thành một propstring
. 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 dự phòng. Nếu sysprop là một sysprop có thể ghi, thì bạn không thể đổi tên sysprop đó.