Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

시스템 속성 추가

이 페이지에서는 Android에서 시스템 속성을 추가하거나 정의하는 표준 메서드와 기존 시스템 속성을 리팩터링하는 가이드라인을 제공합니다. 리팩터링할 때 가이드라인을 따르지 않아야 할 강력한 호환성 문제가 발생하지 않는 한 가이드라인을 사용해야 합니다.

배경

시스템 속성은 사용하기 쉽기 때문에 다양한 용도로 사용됩니다. 프로그래밍 언어의 전역 변수와 비슷하지만 공식화된 프로세스 요구사항 또는 작성 시 따라야 하는 이름 지정 규칙 세트는 없습니다. 따라서 시스템 속성을 이해하고 유지관리하기가 어려울 수 있습니다. 이 페이지에서는 시스템 속성을 정의하고 이러한 속성을 유지관리하고 속성에 추가하는 단계를 제공합니다.

준비: 대안 고려하기

시스템 속성이 실제로 원하는 속성인지 그리고 유일한 옵션인지 확인합니다. 시스템 속성은 특정한 이점을 제공하는 시스템 차원의 리소스입니다. 사용하기 쉬우며 비동적 속성의 성능 오버헤드가 비교적 낮습니다. 시스템 속성을 사용하면 시스템 속성이 여러 프로세스에서 공유되는 경우에도 프로세스 간 통신(IPC)을 사용할 필요가 없습니다. 그러나 전역 변수와 마찬가지로 오용 시 유해할 수도 있습니다. 시스템 속성을 잘못 사용하면 사용자가 앱에 액세스할 수 없게 되고 보안 취약점이 도입되는 문제로 이어집니다.

시스템 속성의 다양한 대안을 고려하여 그중에서 필요한 해결책을 제공할 수 있는 대안을 평가합니다.

공유 환경설정

앱에 로컬로 있는 영구 구성의 경우 시스템 속성 대신 Shared Preferences 인터페이스를 사용합니다.

하드웨어 추상화 계층(HAL)

구성을 하는 데 필요한 정보의 소스가 기기의 하드웨어 구성요소인 경우 HAL을 통해 이 구성요소에 관한 정보를 얻어야 합니다. 다른 프로세스에서 읽을 수 있게 시스템 속성을 작성하도록 HAL을 구성하지 않습니다(그 반대의 경우도 마찬가지). 그 대신 구성에 액세스할 새로운 HAL 메서드를 정의하세요. 즉, 시스템 속성을 HAL의 사이드 채널 통신 메커니즘으로 사용하면 안 됩니다.

이 사용 사례에서는 비용이 드는 옵션인 새 HAL이 필요 없습니다. 하드웨어 구성요소를 추상화할 기존 HAL이 있는 경우에만 이 방법을 활용하세요.

구성 파일

구성 데이터가 정적이지만 복잡한 경우(즉, 구조화된 경우) XML 또는 구성 데이터에 해당하는 다른 형식을 사용해 보세요. 파일 스키마가 안정적으로 유지되는지 확인합니다. XML 파일의 경우 xsd_config를 사용하여 스키마를 안정적으로 유지하고 자동 생성된 XML 파서를 활용할 수 있습니다.

바인더 서비스

시스템 속성은 하위 시스템의 동적 상태를 여러 프로세스와 공유하는 데 자주 사용됩니다. 이러한 상태는 바인더 서비스 내에서(예: 객체 필드로) 구현될 수 있으며 다른 프로세스는 서비스에 관한 바인더 호출을 사용하여 상태를 읽거나 수정할 수도 있습니다. 이러한 방식을 선호하는 이유는, 시스템 속성으로 만들고 이 속성에 직접적인 액세스 권한을 부여하려면 다음과 유사한 프로세스가 필요하기 때문입니다.

  1. 상태에 관해 상태 검사를 실행합니다.
  2. 상태에 관해 사후 처리를 실행하여 상태를 소비할 수 있도록 만듭니다.
  3. 세분화된 액세스 제어 기능을 실행합니다.
  4. 상태를 구조화된 채로 유지합니다.

상태를 시스템 속성으로 구현할 때 이 프로세스를 성공적으로 완료하는 것은 불가능하거나 가능하더라도 매우 어렵습니다. 따라서 상태 리더에게 이미 바인더 서비스 액세스 권한이 있는 경우 바인더 서비스 옵션을 사용합니다.

1단계: 시스템 속성 정의

시스템 속성을 추가할 때 속성의 이름을 결정하고 속성을 SELinux 속성 컨텍스트와 연결합니다. 적절한 기존 컨텍스트가 없으면 새 컨텍스트를 만듭니다. 속성 이름은 속성에 액세스할 때 사용되고, 속성 컨텍스트는 SELinux 측면의 접근성을 제어하는 데 사용됩니다. 이름은 임의의 문자열이 될 수 있지만 AOSP에서는 명확한 이름을 위해 구조화된 형식을 따르도록 권장합니다.

속성 이름

snap_case 대소문자 표기를 포함한 다음 형식을 사용합니다.

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

prefix 요소에 ""(비어 있음), ro(한 번만 설정된 속성), persist(재부팅 시 지속되는 속성) 중 하나를 사용합니다.

주의사항

향후에 prefix가 쓰기 가능할 필요가 없는 경우에만 ro를 사용합니다. ** ro 접두어를 지정하지 않습니다.** 대신 sepolicy를 사용하여 prefix를 읽기 전용으로 설정합니다(즉, init에 의해서만 쓰기 가능).

재부팅 시 값이 지속되어야 하고 시스템 속성을 사용하는 것이 유일한 옵션인 경우에만 persist를 사용합니다. 자세한 내용은 준비 섹션을 참고하세요.

Google에서는 ro 속성이나 persist 속성이 있는 시스템 속성을 엄격하게 검토합니다.

group이라는 용어는 관련 속성을 집계하는 데 사용됩니다. 비슷한 용도의 audio 또는 telephony와 비슷한 하위 시스템 이름이어야 합니다. sys, system, dev, default, config 등 모호하거나 오버로드된 용어를 사용하지 마세요.

시스템 속성에 독점적으로 읽기 또는 쓰기 액세스할 수 있는 프로세스의 도메인 유형 이름을 사용하는 것이 일반적입니다. 예를 들어 vold 프로세스가 쓰기 액세스 권한을 가진 시스템 속성의 경우 프로세스의 도메인 유형 이름인 vold를 그룹으로 사용하는 것이 일반적입니다.

필요한 경우 subgroup을 추가하여 속성을 추가로 분류하지만 이 요소를 설명하기 위해 모호하거나 오버로드된 용어를 사용하지는 마세요. subgroup이 두 개 이상 있을 수도 있습니다.

많은 그룹 이름이 이미 정의되어 있습니다. 가능한 경우 새로 만드는 대신 system/sepolicy/private/property_contexts 파일을 확인하고 기존 그룹을 사용합니다. 다음 표는 자주 사용되는 그룹 이름의 예를 보여 줍니다.

도메인 그룹(및 하위 그룹)
블루투스 관련 bluetooth
커널 cmdline의 sysprop boot
빌드를 식별하는 sysprop build
전화 기술 관련 telephony
오디오 관련 audio
그래픽 관련 graphics
vold 관련 vold

다음은 이전의 정규식 예제에서 nametype의 사용을 정의합니다.

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

  • name은 그룹 내의 시스템 속성을 식별합니다.

  • type은 시스템 속성의 유형이나 의도를 명확하게 나타내는 선택적 요소입니다. 예를 들어 sysprop의 이름을 audio.awesome_feature_enabled 또는 단순히 audio.awesome_feature로 지정하는 대신 시스템 속성 유형과 의도를 반영하도록 이름을 audio.awesome_feature.enabled로 바꿉니다.

어떤 유형이어야 하는지에 관한 구체적인 규칙은 없습니다. 사용 권장사항은 다음과 같습니다.

  • enabled: 유형이 기능을 사용 설정하거나 중지하는 데 사용되는 부울 시스템 속성인 경우 사용합니다.
  • config: 시스템 속성이 시스템의 동적 상태를 나타내지 않도록 명확히 하려는 의도인 경우 사용합니다. 사전 구성된 값(예: 읽기 전용 항목)을 나타냅니다.
  • List: 시스템 속성의 값이 목록인 경우 사용합니다.
  • Timeoutmillis: 밀리초 단위의 시간 제한 값인 시스템 속성인 경우 사용합니다.

예를 들면 다음과 같습니다.

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

속성 컨텍스트

새로운 SELinux 속성 컨텍스트 체계에서는 고도로 세부 제어하고 더 구체적으로 설명하는 이름을 사용할 수 있습니다. 속성 이름에 사용되는 것과 마찬가지로 AOSP에서 권장되는 형식은 다음과 같습니다.

{group}[_{subgroup}]*_prop

용어는 다음과 같이 정의됩니다.

groupsubgroup은 이전의 샘플 정규식에 정의된 것과 동일한 의미를 가집니다. 예를 들어 vold_config_prop은 공급업체의 구성이며 vendor_init에서 설정할 수 있는 속성을 나타내고, vold_status_prop 또는 단순히 vold_propvold의 현재 상태를 노출합니다.

속성 컨텍스트 이름을 지정할 때는 속성의 일반적인 사용을 반영하는 이름을 선택합니다. 특히 다음과 같은 유형의 용어는 사용하지 마세요.

  • 너무 일반적이고 모호한 용어(예: sys, system, default)
  • 접근성을 직접 인코딩하는 용어(예: exported, apponly, ro, public, private)

exported_vold_prop 또는 vold_vendor_writable_prop 등의 이름보다 vold_config_prop 같은 이름을 사용합니다.

유형

속성 유형은 표에 나온 대로 다음 중 하나일 수 있습니다.

유형 정의
부울 true의 경우 true 또는 1, false의 경우 false 또는 0
정수 부호 있는 64비트 정수
Double 배정밀도 부동 소수점
문자열 유효한 UTF-8 문자열
enum 공백 없는 유효한 UTF-8 문자열은 어느 것이나 가능
위 목록 쉼표(,)가 구분 기호로 사용됨
정수 목록([1, 2, 3])이 1,2,3으로 저장됨

내부적으로 모든 속성은 문자열로 저장됩니다. 유형을 property_contexts 파일로 지정하여 적용할 수 있습니다. 자세한 내용은 3단계property_contexts를 참고하세요.

2단계: 필요한 접근성 수준 확인

속성을 정의하는 도우미 매크로 4개가 있습니다.

접근성 유형 의미
system_internal_prop /system에서만 사용되는 속성
system_restricted_prop /system 외부에서 읽지만 작성되지는 않는 속성
system_vendor_config_prop /system 외부에서 읽고 vendor_init에 의해서만 작성되는 속성
system_public_prop /system 외부에서 읽고 작성되는 속성

시스템 속성 액세스 권한을 최대한 좁힙니다. 이전에는 광범위한 액세스 권한으로 인해 앱 중단 및 보안 취약점이 발생했습니다. 범위를 지정할 때 다음 질문을 고려하세요.

  • 이 시스템 속성을 유지해야 하는가? 그렇다면 이유는 무엇인가?
  • 이 속성에 관한 읽기 액세스 권한이 있어야 하는 프로세스는 어느 것인가?
  • 이 속성에 관한 쓰기 액세스 권한이 있어야 하는 프로세스는 어느 것인가?

위 질문과 다음 결정 트리를 도구로 활용하여 적절한 액세스 범위를 결정하세요.

액세스 범위를 결정하기 위한 결정 트리

그림 1. 시스템 속성 액세스 범위를 결정하기 위한 결정 트리

3단계: 시스템/sepolicy에 추가

sysprop에 액세스할 때 SELinux는 프로세스의 접근성을 제어합니다. 필요한 접근성 수준을 결정한 후에는 system/sepolicy에서 속성 컨텍스트를 정의하고 프로세스가 어느 항목을 읽거나 쓸 수 있는지 규정하는 추가 allow 규칙과 neverallow 규칙을 정의합니다.

첫째, system/sepolicy/public/property.te 파일에서 속성 컨텍스트를 정의합니다. 시스템 내부 속성인 경우 system/sepolicy/private/property.te 파일에서 속성을 정의합니다. 시스템 속성에 필요한 접근성을 제공하는 system_[accessibility]_prop([context]) 매크로 중 하나를 사용합니다. 다음은 system/sepolicy/public/property.te 파일의 예입니다.

system_public_prop(audio_foo_prop)
system_vendor_config_prop(audio_bar_prop)

system/sepolicy/private/property.te 파일에 추가할 예제:

system_internal_prop(audio_baz_prop)

둘째, 속성 컨텍스트에 관한 읽기 및 쓰기 액세스 권한을 부여합니다. system/sepolicy/public/{domain}.te 파일이나 system/sepolicy/private/{domain}.te 파일에서 set_propget_prop 매크로를 사용하여 액세스 권한을 부여합니다. 가능하면 항상 private을 사용합니다. publicset_prop 매크로나 get_prop 매크로가 코어 도메인 외부의 도메인에 영향을 미치는 경우에만 적합합니다.

system/sepolicy/private/audio.te 파일의 예:

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

system/sepolicy/public/domain.te 파일의 예:

get_prop(domain, audio_bar_prop)

셋째, 매크로에 의해 범위가 지정된 접근성을 더 줄이기 위해 몇 가지 neverallow 규칙을 추가합니다. 예를 들어 공급업체 프로세스에서 시스템 속성을 읽어야 하기 때문에 system_restricted_prop을 사용했다고 가정하겠습니다. 읽기 액세스가 모든 공급업체 프로세스에서 필요하지는 않고 특정 프로세스 모음(예: vendor_init)에서만 필요한 경우에는 읽기 액세스가 필요하지 않은 공급업체 프로세스를 금지합니다.

쓰기 및 읽기 액세스를 제한하는 다음 구문을 사용합니다.

쓰기 액세스 제한:

neverallow [domain] [context]:property_service set;

읽기 액세스 제한:

neverallow [domain] [context]:file no_rw_file_perms;

neverallow 규칙이 특정 도메인에 결합되는 경우 system/sepolicy/private/{domain}.te 파일에 neverallow 규칙을 배치합니다. 보다 광범위한 neverallow 규칙의 경우 적절하다면 어디서나 다음과 같이 일반 도메인을 사용합니다.

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

system/sepolicy/private/audio.te 파일에 다음을 배치합니다.

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

system/sepolicy/private/property.te 파일에 다음을 배치합니다.

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

{domain -coredomain}은 모든 공급업체 프로세스를 캡처합니다. 따라서 {domain -coredomain -vendor_init}vendor_init제외한 '모든 공급업체 프로세스'를 의미합니다.

마지막으로, 시스템 속성과 속성 컨텍스트를 연결합니다. 이렇게 하면 부여된 액세스 권한과 속성 컨텍스트에 적용되는 neverallow 규칙이 실제 속성에 적용됩니다. 이렇게 하려면 시스템 속성과 속성 컨텍스트 간의 매핑을 설명하는 파일인 property_contexts 파일에 항목을 추가합니다. 이 파일에서 단일 속성을 지정하거나 컨텍스트에 매핑할 속성의 접두어를 지정할 수 있습니다.

단일 속성을 매핑하는 구문은 다음과 같습니다.

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

접두어를 매핑하는 구문은 다음과 같습니다.

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

선택적으로 속성 유형을 지정할 수 있으며 이러한 유형은 다음 중 하나일 수 있습니다.

  • bool
  • int
  • double
  • enum [list of possible values...]
  • string(list 속성의 경우 string 사용)

property를 설정할 때 type이 적용되므로 가능하면 항상 모든 항목에 유형이 지정되어 있는지 확인합니다. 다음 예는 매핑을 작성하는 방법을 보여 줍니다.

# 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

정확한 입력과 접두어 입력이 충돌하는 경우 정확한 입력이 우선합니다. 더 많은 예는 system/sepolicy/private/property_contexts에서 참고하세요.

4단계: 안정성 요구사항 확인

안정성은 시스템 속성의 또 다른 측면으로서 접근성과 다릅니다. 안정성은 향후 시스템 속성을 변경할 수 있는지 여부(예: 이름 바꾸기 또는 삭제)와 관련 있습니다. Android OS가 모듈화될 때 특히 중요합니다. Treble에서는 시스템, 공급업체, 제품 파티션을 서로 독립적으로 업데이트할 수 있습니다. Mainline에서는 OS의 일부가 업데이트 가능한 모듈(APEX 또는 APK)로 모듈화됩니다.

예를 들어 시스템 및 공급업체 파티션 간에 업데이트 가능한 소프트웨어에서 시스템 속성을 사용하는 경우에는 반드시 안정적이어야 합니다. 하지만 예를 들어 특정 Mainline 모듈 내에서만 사용되는 경우에는 속성의 이름, 유형 또는 속성 컨텍스트를 변경할 수 있고 심지어 삭제할 수도 있습니다.

다음 질문을 통해 시스템 속성의 안정성을 결정하세요.

  • 이 시스템 속성은 파트너가 구성하거나 기기별로 다르게 구성되도록 만들어졌는가? '예'인 경우 속성은 안정적이어야 합니다.
  • 이 AOSP 정의 시스템 속성은 vendor.img 또는 product.img 같은 비시스템 파티션에 있는 코드(프로세스 아님)에 쓰거나 이러한 코드에서 읽도록 만들어졌는가? '예'인 경우 속성은 안정적이어야 합니다.
  • 다수의 Mainline 모듈에서 이 시스템 속성에 액세스하거나 Mainline 모듈과 업데이트 불가능한 플랫폼 부분에서 이 시스템 속성에 액세스하는가? '예'인 경우 속성은 안정적이어야 합니다.

안정적인 시스템 속성의 경우 6단계의 설명대로 각 속성을 API로 공식적으로 정의하고 이 API를 사용하여 시스템 속성에 액세스합니다.

5단계: 빌드 시간에 속성 설정

makefile 변수를 사용하여 빌드 시간에 속성을 설정합니다. 기본적으로, 값은 {partition}/build.prop에 통합됩니다. 그런 다음 init{partition}/build.prop을 읽어 속성을 설정합니다. 변수 유형으로는 PRODUCT_{PARTITION}_PROPERTIESTARGET_{PARTITION}_PROP이 있습니다.

PRODUCT_{PARTITION}_PROPERTIES에는 속성 값 목록이 포함됩니다. 구문은 {prop}={value} 또는 {prop}?={value}입니다.

{prop}={value}{prop}{value}로 설정되었는지 확인하는 정규 할당입니다. 속성당 이러한 할당 하나만 지정할 수 있습니다.

{prop}?={value}는 선택적 할당입니다. {prop}={value} 할당이 없는 경우에만 {prop}{value}로 설정됩니다. 선택적 할당이 여러 개 있는 경우 첫 번째 할당이 우선합니다.

# 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에는 {partition}/build.prop에 직접 출력되는 파일 목록이 포함됩니다. 각 파일에는 {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

자세한 내용은 build/make/core/sysprop.mk를 참고하세요.

6단계: 런타임에 속성 액세스

물론 런타임에 속성을 읽고 쓸 수 있습니다.

Init 스크립트

init 스크립트 파일(일반적으로 *.rc 파일)은 ${prop} 또는 ${prop:-default}에서 속성을 읽고, 속성이 특정 값이 될 때마다 실행되는 작업을 설정하고, 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}

getprop 및 setprop 셸 명령어

getprop 또는 setprop 셸 명령어를 각각 사용하여 속성을 읽거나 쓸 수 있습니다. 자세한 내용을 확인하려면 getprop --help 또는 setprop --help를 호출하세요.

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

C++/자바에 sysprop을 API로 사용

sysprop을 API로 사용하면 시스템 속성을 정의하고 구체적이고 유형화된 자동 생성 API를 사용할 수 있습니다. 또한 Public으로 scope을 설정하면 생성된 API를 여러 모듈에서 경계를 넘어 사용할 수 있게 되고 API 안정성을 보장할 수 있습니다. 다음은 .sysprop 파일 샘플, Android.bp 모듈, 이 파일과 모듈을 사용하는 C++ 코드와 자바 코드입니다.

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

// Both java and cc module can link against sysprop_library
java_library {
    static_libs: ["AudioProps"],
    …
}

cc_binary {
    static_libs: ["AudioProps"],
    …
}

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

자세한 내용은 시스템 속성을 API로 구현을 참고하세요.

C/C++ 및 자바 하위 수준 속성 함수 및 메서드

하위 수준 C/C++ 함수나 하위 수준 자바 메서드를 사용할 수 있더라도 sysprop을 API로 사용합니다. 가능하면 항상 sysprop을 사용하는 것이 좋습니다.

libc, libbase, libcutils는 C++ 시스템 속성 함수를 제공합니다. libc에는 기본 API가 있고, libbaselibcutils 함수는 래퍼입니다. 가능한 경우 libbase sysprop 함수를 사용합니다. 가장 편리한 방법이며, 호스트 바이너리는 libbase 함수를 사용할 수 있습니다. 자세한 내용은 sys/system_properties.h(libc), android-base/properties.h(libbase), cutils/properties.h(libcutils)를 참고하세요.

android.os.SystemProperties 클래스는 자바 시스템 속성 메서드를 제공합니다.

부록: 공급업체별 속성 추가

파트너(Pixel 개발과 관련된 Google 직원 포함)는 하드웨어별 또는 기기별 시스템 속성을 정의하려고 합니다. 공급업체별 속성은 플랫폼이 아닌 자체 하드웨어나 기기에 고유한 파트너 소유 속성입니다. 이러한 속성은 하드웨어나 기기에 따라 다르므로 /vendor 또는 /odm 파티션 내에서 사용해야 합니다.

프로젝트 Treble 이후로는 플랫폼 속성과 공급업체 속성이 완전히 분할되어 충돌이 발생하지 않습니다. 아래에서는 공급업체 속성을 정의하는 방법과 어떤 공급업체 속성을 항상 사용해야 하는지 설명합니다.

속성 및 컨텍스트 이름의 네임스페이스

모든 공급업체 속성은 다른 파티션의 속성과의 충돌을 방지하기 위해 다음 접두어 중 하나로 시작해야 합니다.

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

ro.hardware.는 접두어로 사용할 수 있지만 호환성을 위해서만 허용됩니다. 일반 속성에 사용하지 마세요.

다음 예에서는 모두 위에 나열된 접두어 중 하나를 사용합니다.

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

모든 공급업체 속성 컨텍스트는 vendor_로 시작해야 합니다. 호환성을 위한 것이기도 합니다. 예를 들어 다음과 같습니다.

  • vendor_radio_prop.
  • vendor_faceauth_prop.
  • vendor_usb_prop.

속성을 유지관리하고 속성 이름을 지정하는 것은 공급업체의 책임입니다. 따라서 공급업체 네임스페이스 요구사항 외에도 2단계에서 권장하는 형식을 따라야 합니다.

공급업체별 SEPolicy 규칙 및 property_contexts

플랫폼 속성과 마찬가지로 공급업체 속성은 다음 매크로 중 하나로 정의할 수 있습니다.

접근성 유형 의미
vendor_internal_prop /vendor에서만 사용되는 속성
vendor_restricted_prop /vendor 외부에서 읽지만 작성되지는 않는 속성
vendor_public_prop /vendor 외부에서 읽고 작성되는 속성

정의한 공급업체별 규칙을 BOARD_VENDOR_SEPOLICY_DIRS 디렉터리에 넣습니다. 예를 들어 Coral에서 공급업체 faceauth 속성을 정의한다고 가정합니다.

BoardConfig.mk 파일(또는 모든 BoardConfig.mk Include)에 다음을 배치합니다.

BOARD_VENDOR_SEPOLICY_DIRS := device/google/coral-sepolicy

device/google/coral-sepolicy/private/property.te 파일에 다음을 배치합니다.

vendor_internal_prop(vendor_faceauth_prop)

device/google/coral-sepolicy/private/property_contexts 파일에 다음을 배치합니다.

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

공급업체 속성의 제한사항

시스템 및 제품 파티션은 공급업체에 종속될 수 없으므로 system, system-ext 또는 product 파티션에서 공급업체 속성에 액세스할 수 없도록 해야 합니다.

부록: 기존 속성 이름 바꾸기

속성을 지원 중단하고 새로운 속성으로 이전해야 하는 경우 sysprop을 API로 사용하여 기존 속성의 이름을 바꿉니다. 이렇게 하면 기존 이름과 새 속성 이름을 모두 지정하여 이전 버전과의 호환성이 유지됩니다. 특히 .sysprop 파일의 legacy_prop_name 필드를 사용하여 기존 이름을 설정할 수 있습니다. 생성된 API는 prop_name을 읽으려고 시도하며 prop_name이 없으면 legacy_prop_name을 사용합니다.

예를 들어 다음 단계에서는 awesome_feature_foo_enabled에서 foo.awesome_feature.enabled로 이름을 바꿉니다.

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

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

다음과 같은 주의사항을 참고하세요.

  • 첫째, sysprop의 유형을 변경할 수 없습니다. 예를 들어 int prop을 string prop으로 만들 수 없습니다. 이름만 변경할 수 있습니다.

  • 둘째, 읽기 API만 기존 이름으로 대체됩니다. 쓰기 API는 대체되지 않습니다. sysprop이 쓰기 가능한 prop인 경우에는 이름을 바꿀 수 없습니다.