Trang này cung cấp một phương thức chuẩn để thêm hoặc xác định các thuộc tính hệ thống trong Android, cùng với các nguyên tắc để tái cấu trúc các thuộc tính hệ thống hiện có. Hãy đảm bảo rằng bạn sử dụng các nguyên tắc này khi tái cấu trúc, trừ phi bạn gặp phải vấn đề về khả năng tương thích nghiêm trọng.
Bước 1: Xác định thuộc tính hệ thống
Khi 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 ngữ cảnh thuộc tính SELinux. Nếu không có ngữ cảnh hiện có thích 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 hỗ trợ tiếp cận theo 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 một định dạng có cấu trúc để làm cho tên rõ ràng.
Tên thuộc tính
Sử dụng định dạng này với cách viết snake_case:
[{prefix}.]{group}[.{subgroup}]*.{name}[.{type}]
Sử dụng "" (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 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. ** 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ì sau khi 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.
Google nghiêm ngặt xem xé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 của một hệ thống con tương tự như cách sử dụng audio
hoặc telephony
. Đừng sử dụng các cụm từ không rõ ràng hoặc quá tải như sys
, system
, dev
, default
hoặc config
.
Thông thường, bạn nên sử dụng tên của loại miền của một quy trình có quyền đọc hoặc ghi riêng đố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, thường thì bạn sẽ sử 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ữ không rõ ràng 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ó khi có thể, thay vì tạo tên mới. Bảng sau đây cung cấp ví dụ về tên nhóm thường dùng.
Miền | Nhóm (và nhóm con) |
---|---|
liên quan đến bluetooth | bluetooth |
sysprops từ lệnh cmdline 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 |
liên quan đến đồ hoạ | 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ụ 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 ý định 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 nó thànhaudio.awesome_feature.enabled
để phản ánh loại và ý định của thuộc tính hệ thống.
Không có quy tắc cụ thể về loại phải là gì; sau đây là các đề xuất về cách sử dụng:
enabled
: Sử dụng nếu loại là 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 ý định 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; thuộc tính này thể hiện một giá trị được định cấu hình trước (ví dụ: một đối tượng chỉ có thể đọ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
Ngữ cảnh thuộc tính
Lược đồ ngữ cảnh thuộc tính SELinux mới cho phép độ chi tiết tốt hơn và tên mô tả hơn. Tương tự như tên thuộc tính, AOSP đề xuất định dạng sau:
{group}[_{subgroup}]*_prop
Các thuật ngữ được xác định 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 nhà cung cấp và do vendor_init
đặt, trong khi vold_status_prop
hoặc chỉ vold_prop
biểu thị các thuộc tính hiển thị trạng thái hiện tại của vold
.
Khi đặt tên ngữ cảnh thuộc tính, hãy chọn tên phản ánh cách sử dụng chung của các thuộc tính. Cụ thể, hãy tránh các loại cụm từ sau:
- Các thuật ngữ có vẻ quá chung chung và mơ hồ, chẳng hạn như
sys
,system
,default
. - Các thuật ngữ trực tiếp mã hoá 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
Loại thuộc tính có thể là một trong những loại sau đượ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 đã ký |
Số nguyên chưa ký | số nguyên 64 bit chưa ký |
Đôi | dấu phẩy động có độ chính xác kép |
Chuỗi | bất kỳ chuỗi UTF-8 hợp lệ nào |
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 |
Trong 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 này bằng cách chỉ định loại này là 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 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 vendor_init ghi |
system_public_prop |
Các thuộc tính được đọc và ghi bên ngoài /system |
Giới hạn quyền 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 sự cố ứng dụng và 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ó, tại sao?)
- Quy trình nào sẽ có quyền đọc đối với thuộc tính này?
- Quy trình nào sẽ có quyền 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 đây 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 các thuộc tính của 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 hỗ trợ tiếp cận 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 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 cho phép) bổ sung về những quy trình được phép (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 nằm trong 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 vào ngữ cảnh thuộc tính. Sử dụng các 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 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 khả năng hỗ trợ tiếp cận do macro xác định phạm vi. Ví dụ: giả sử 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 đọc và chỉ cần 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 đọ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 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 không bao giờ cho phép 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;
Lưu ý rằng {domain -coredomain}
ghi lại mọi quy trình của nhà cung cấp. Vì vậy, {domain -coredomain -vendor_init}
có nghĩa là "tất 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 áp dụng cho ngữ cảnh thuộc tính đượ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 hoặc một tiền tố cho các thuộc tính cần được liên kết vào ngữ cảnh.
Đây là cú pháp để liên kết một tài sản:
[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ể tuỳ ý chỉ định loại thuộc tính, có thể là một trong các 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, thì 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 các yêu cầu về độ ổn định
Độ ổn định là một khía cạnh khác của thuộc tính hệ thống và khác với khả năng hỗ trợ tiếp cận. Độ ổn định thể hiện việc một thuộc tính hệ thống có thể được thay đổi hay không (ví dụ: đổi tên hoặc thậm chí là xoá) 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, bạn có thể cập nhật hệ thống, nhà cung cấp và các phân vùng sản phẩm một cách độ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 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 thuộc tính này chỉ được sử 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 thuộc tính này, thậm chí xoá thuộc tính này.
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 định cấu hình khác nhau cho mỗi thiết bị)? Nếu có, phiên bản phải ổn định.
- Thuộc tính hệ thống do AOSP xác định này có được dùng để 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ì mã đó 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 hay trên một mô-đun Mainline và phần không thể cập nhật của nền tảng? Nếu có, phiên bản 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 vào thuộc tính hệ thống, như được giải thích trong Bước 6.
Bước 5: Thiết lập thuộc tính tại thời điểm tạo bản dựng
Đặt thuộc tính tại thời điểm tạo bằng các biến tệp makefile. Về mặt kỹ thuật, các giá trị này đượ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ó 2 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à một giá trị gán thông thường đảm bảo rằng {prop}
được đặt thành {value}
; chỉ có thể có một giá trị gán như vậy cho mỗi thuộc tính.
{prop}?={value}
là một giá trị gán không bắt buộc; {prop}
chỉ đặt thành {value}
nếu không có giá trị gán {prop}={value}
nào. Nếu có nhiều nhiệm vụ không bắt buộc, thì nhiệm vụ đầ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 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 thuộc tính trong thời gian chạy.
Tập lệnh khởi tạo
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 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 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
tương ứng để đọc hoặc ghi thuộc tính. Để biết thêm thông tin 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 đặt 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 API ổn định. Dưới đây là một mẫu tệp .sysprop
, mô-đun Android.bp
và mã C++, Java và Rust sử dụng các tệp và mô-đun đó.
# 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 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 trong 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à 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 thuận tiện nhất và tệp nhị phân lưu trữ 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 kiểu và hàm 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à các 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 họ, chứ không phải cho nền tảng. Vì các tệp này phụ thuộc vào phần cứng hoặc 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 thuộc tính nhà cung cấp và cho biết những thuộc tính nhà cung cấp nào phải luôn được sử dụng.
Không gian tên trên tên thuộc tính và 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 để ngăn chặn sự xung đột giữa các thuộc tính đó 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 dùng làm tiền tố, nhưng chỉ để tương thích.
Không sử dụng thuộc tính này cho các thuộc tính thông thường.
Tất 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ả 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 bảo khả năng 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 làm 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 thuộc tính 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 thuộc tính faceauth của nhà cung cấp trong coral.
Trong tệp BoardConfig.mk
(hoặc trong bất kỳ tệp BoardConfig.mk
nào có chứa), 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 của tài sản của nhà cung cấp
Vì phân vùng sản phẩm và hệ thống không thể phụ thuộc vào nhà cung cấp, nên đừng bao giờ cho phép truy cập vào các thuộc tính của nhà cung cấp từ phân vùng system
, system-ext
hoặc product
.
Phụ lục: Đổi tên các 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 dưới dạng API để đổi tên các thuộc tính hiện có. Điều này giúp 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ũ theo 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ều sau:
Trước tiên, bạn không thể thay đổi loại sysprop. Ví dụ: bạn không thể tạo thuộc tính
int
thành thuộc tínhstring
. Bạn chỉ có thể thay đổi tên.Thứ hai, chỉ API đọc mới quay lại tên cũ. API ghi sẽ không quay lại. Nếu sysprop là một thuộc tính có thể ghi, bạn không thể đổi tên thuộc tính đó.