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

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 tại thích hợp, hãy tạo một tài khoản 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 rõ tên.

Tên thuộc tính

Sử dụng định dạng này với kiểu 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ó thể đọc (nói cách khác, chỉ init mới có thể ghi).

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.

Từ khoá 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. Khô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, người dùng nên sử dụng tên loại miền của 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, 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 sử 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. Xem system/sepolicy/private/property_contexts tệp và sử dụng tên nhóm hiện có khi có thể, thay vì tạo quảng cáo 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 nametype 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, làm rõ loại hoặc ý định của thuộc tính hệ thống của chúng tôi. Ví dụ: thay vì đặt tên sysprop là audio.awesome_feature_enabled hoặc chỉ audio.awesome_feature, hãy đổi tên thành audio.awesome_feature.enabled để phản ánh loại thuộc tính hệ thống và ý định.

Không có quy tắc cụ thể nào về loại dữ liệu phải xuất hiện; đây là mức sử dụng đề xuất:

  • enabled: Sử dụng nếu kiểu này là một thuộc tính hệ thống boolean được dùng để biến 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ả rõ ràng 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:

groupsubgroup có cùng ý nghĩa như được định nghĩa cho trước biểu thức chính quy mẫu. 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:

  • Những cụm từ quá chung chung và không rõ ràng, chẳng hạn như sys, system, default.
  • Những cụm từ mã hoá trực tiếp chức 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 đến 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 giá trị true, false hoặc 0 cho kết quả 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ách
Danh sách số nguyên [1, 2, 3] được lưu trữ dưới dạng 1,2,3

Bên trong, 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 tệp này là một 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 Những thuộc tính chỉ được dùng trong /system
system_restricted_prop Những thuộc tính được đọc bên ngoài /system nhưng không được ghi
system_vendor_config_prop Những thuộc tính được đọc bên ngoài /system và chỉ do vendor_init viết
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 trong phạm vi hẹp nhất có thể. 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. Cân nhắc những câu hỏi sau đây 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.

Cây quyết định để xác định phạm vi truy cậ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 hệ thống/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 là nội bộ 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ủa thuộc tính hệ thống. Đâ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 ngữ cảnh thuộc tính. Sử dụng set_propget_prop để cấp quyền truy cập, trong system/sepolicy/public/{domain}.te hoặc system/sepolicy/private/{domain}.te tệp. 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 cốt 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 thiểu khả năng hỗ trợ tiếp cận được xác định phạm vi theo macro. Ví dụ: giả sử rằng bạn đã sử dụng system_restricted_prop vì nhà cung cấp phải đọc các thuộc tính hệ thống của bạn các quy trình. 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 yêu cầu bởi một nhóm quy trình nhất định (chẳng hạn như vendor_init), 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 bất cứ khi nào 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 như 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ả quy trình của nhà cung cấp. Loại đối thủ sau lượt đánh bóng {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 tài sản được áp dụng cho các tài sản 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ả mối liên kết giữa các hệ thống thuộc tính 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 tiền tố cho các thuộc tính đượ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:

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

Dưới đây là cú pháp để liên kết một tiền tố:

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

Bạn có thể chỉ định loại thuộc tính (không bắt buộc), thuộc tính này có thể là một trong các loại sau:

  • bool
  • int
  • uint
  • double
  • enum [list of possible values...]
  • string (Sử dụng string 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 có tiền tố xung đột, thì mục nhập chính xác đó sẽ được lấy quyền ư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à nó khác với khả năng hỗ trợ tiếp cận. Độ ổn định là về việc liệu một thuộc tính hệ thống có thể được thay đổi (ví dụ: đổi tên hoặc thậm chí xoá) trong tương lai hay không. Đây là đặ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 APEXes 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 mã này được sử dụng chỉ trong một mô-đun Mainline cụ thể, bạn có thể thay đổi tên của mô-đun đó, loại hoặc ngữ cảnh thuộc tính và thậm chí là loại bỏ ngữ cảnh đó.

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

  • Tài sản hệ thống này có phải do đối tác định cấu hình (hoặc định cấu hình) không khác nhau tuỳ theo thiết bị) không? Nếu có, thì mã đó 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ặc product.img không? Nếu có, phiên bản 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

Thiết lập các thuộc tính tại thời điểm xây dựng bằng các biến 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 đọc {partition}/build.prop để đặt thuộc tính. Có hai nhóm nội dung biến: 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à một chỉ định thông thường đảm bảo rằng {prop} được đặt thành {value}; bạn chỉ có thể chỉ định một thuộc tính như vậy cho mỗi thuộc tính.

{prop}?={value} là một bài tập không bắt buộc; {prop} chỉ được đặt thành {value} khi không có bất kỳ bài tập được chỉ định {prop}={value} nào. Nếu có nhiều bài tập không bắt buộc tồn tại, quảng cáo đầ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 tới {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

Các tệp tập lệnh khởi tạo (thường là tệp *.rc) có thể đọc một thuộc tính bằng ${prop} hoặc ${prop:-default}, có thể thiết lập một hành động sẽ 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ể viết 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}

các lệnh shell getprop và setprop

Bạn có thể sử dụng các lệnh shell getprop hoặc setprop tương ứng để đọc hoặc viết các thuộc tính. Để biết thêm thông tin, 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 dưới dạng 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 sẽ tạo API được cung cấp cho các mô-đun xuyên ranh giới và đảm bảo độ ổn định của API. 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 mặc dù 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 được cung cấp cho bạn.

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à 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 hàm thuộc tính hệ thống Rust và loại tài khoản.

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ị). Tài sản của nhà cung cấp là các tài sản thuộc sở hữu của đối tác và dành riêng cho phần cứng hoặc thiết bị riêng chứ không phải 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 của nền tảng và thuộc tính của nhà cung cấp tách hoàn toàn để ngăn không cho chúng xung đột. Phần sau đây mô tả cách xác định thuộc tính của nhà cung cấp và cho biết thuộc tính nào của nhà cung cấp 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ả các sản phẩm của nhà cung cấp phải bắt đầu bằng một trong các tiền tố sau đây để tránh xung đột giữa chúng và thuộc tính của 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.

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ả ngữ cảnh thuộc tính của nhà cung cấp phải bắt đầu bằng vendor_. Mục này cũng dành cho 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ì tài sản, vì vậy, hãy tuân theo định dạng được đề xuất trong Bước 2, ngoài việc 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à thuộc tính property_contexts dành riêng cho nhà cung cấp

Bạn có thể xác định 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 thuộc tính Faceauth của nhà cung cấp ở san hô.

Trong tệp BoardConfig.mk (hoặc trong bất kỳ BoardConfig.mk nào bao gồm), hãy đặt phương thức 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

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

Vì các 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 chưa bao giờ cho phép truy cập vào thuộc tính của nhà cung cấp từ system, system-ext hoặc product phân vùng.

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 tài sản và chuyển sang một tài sản mới, hãy sử dụng Sysprop làm API để đổi tên các tài sản hiện có. Việc 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. Chiến lược phát hành đĩa đơn 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ể biến một thuộc tính int thành một thuộc tính string. 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 lùi lại. Nếu sysprop là một thuộc tính có thể ghi, bạn không thể đổi tên nó.