Android 공유 시스템 이미지

이 페이지에서는 Android 기기 OEM에서 제품 라인 전체에 걸쳐 자체 공유 시스템 이미지(SSI)를 보유하는 데 사용할 수 있는 여러 메커니즘을 소개합니다. AOSP에서 빌드한 일반 시스템 이미지(GSI)에 OEM 소유 SSI를 기반으로 하는 절차도 제안합니다.

배경

프로젝트 Treble에서 모놀리식 Android는 하드웨어 관련 부분(공급업체 구현)과 일반 OS 부분(Android OS 프레임워크)의 두 가지 부분으로 분할되었습니다. 각 소프트웨어는 별도의 파티션에 설치됩니다. 하드웨어 관련 소프트웨어의 경우 공급업체 파티션에, 일반 OS 소프트웨어의 경우 시스템 파티션에 설치됩니다. 공급업체 인터페이스(VINTF)라는 버전이 지정된 인터페이스는 두 파티션에서 정의되고 적용됩니다. 이 파티션 시스템을 사용하면 공급업체 파티션을 수정하지 않고도 시스템 파티션을 수정할 수 있고 반대의 경우도 마찬가지입니다.

동기

AOSP에서 출시된 프레임워크 코드는 Treble 아키텍처를 준수하고 이전 공급업체 구현과 호환성을 유지했습니다. 예를 들어 Android 10 AOSP 소스에서 빌드된 일반 시스템 이미지는 Android 8 이상에서 실행되는 Treble 준수 기기에서 실행될 수 있습니다. 소비자 기기에 제공되는 Android 버전은 SoC 공급업체 및 OEM에서 수정합니다(Android 버전 수명 참고). 프레임워크에 적용된 이러한 변경사항과 확장 프로그램은 이전 버전과의 호환성 유지를 위해 작성된 것이 아니므로 OS 업그레이드의 비용과 복잡성이 증가했습니다. 기기별 변경사항과 수정사항으로 인해 Android OS 버전 업그레이드의 비용과 복잡성은 한층 더 증가합니다.

Android 11 전에는 파트너가 Android OS 프레임워크의 모듈식 확장을 빌드할 수 있는 확실한 아키텍처가 없었습니다. 이 문서에서는 SoC 공급업체 및 OEM에서 SSI를 만들기 위해 수행할 수 있는 단계를 설명합니다. 이는 여러 기기에서 재사용하고 공급업체 구현과의 하위 호환성을 유지하며 Android OS 업그레이드의 복잡성과 비용을 크게 절감하기 위해 Android OS 프레임워크 소스에서 빌드된 하나의 이미지를 의미합니다. SSI를 만드는 데 필요한 구체적인 단계는 GSI 기반 SSI를 만들기 위한 권장 단계 섹션을 참고하세요. 4단계를 모두 거치지 않아도 됩니다. 선택하는 단계(예: 1단계만 선택)는 구현 내용에 따라 다릅니다.

SSI 개요

SSI를 사용하면 제품 관련 소프트웨어 구성요소와 OEM 확장 프로그램이 새 /product 파티션에 배치됩니다. /product 파티션의 구성요소는 명확하고 안정적인 인터페이스를 사용하여 /system 파티션의 구성요소와 상호작용합니다. OEM은 SSI 하나를 빌드하는 것과 여러 기기 SKU에서 사용하기 위해 소수의 SSI를 보유하는 것 중에 선택할 수 있습니다. 새 버전의 Android OS가 출시되면 OEM에서는 최신 Android 버전으로 SSI를 업데이트하는 데 한 번만 투자합니다. SSI를 재사용하여 /product 파티션을 업데이트하지 않고 여러 기기를 업데이트할 수 있습니다.

OEM 및 SoC 공급업체는 OEM에서 필요로 하는 모든 맞춤 기능과 수정사항이 포함된 SSI를 빌드합니다. 이 페이지에서 제공하는 메커니즘 및 권장사항은 OEM이 다음과 같은 주요 목표를 달성하는 데 사용하도록 하기 위한 것입니다.

  • SSI를 여러 기기 SKU에서 재사용합니다.
  • 더 쉽게 OS를 업그레이드할 수 있도록 모듈식 확장 프로그램으로 Android 시스템을 업데이트합니다.

제품 관련 구성요소를 제품 파티션으로 분리하는 핵심 개념은 SoC 관련 구성요소를 공급업체 파티션으로 분리하는 Treble 개념과 비슷합니다. VINTF와 유사한 제품 인터페이스를 통해 SSI와 제품 파티션 간에 통신할 수 있습니다. SSI와 관련하여 '구성요소'라는 용어는 기본적으로 파티션이 되는 이미지에 설치되는 모든 리소스, 바이너리, 텍스트, 라이브러리 등을 설명합니다.

SSI 주변의 파티션

그림 1에서는 SSI 주변의 파티션과 인터페이스의 파티션 및 정책에서 버전이 지정된 인터페이스를 보여 줍니다. 이 섹션에서는 각 파티션과 인터페이스를 자세히 설명합니다.

SSI 주변의 파티션과 인터페이스 블록 다이어그램

그림 1. SSI 주변의 파티션과 인터페이스

이미지와 파티션

이 섹션의 정보는 이미지파티션이라는 용어를 구분합니다.

  • 이미지는 독립적으로 업데이트할 수 있는 소프트웨어의 개념입니다.
  • 파티션은 독립적으로 업데이트할 수 있는 물리적 저장소 위치입니다.

그림 1의 섹션은 다음과 같이 정의됩니다.

  • SSI: SSI는 OEM에 공통된 이미지로, 여러 기기에 있을 수 있습니다. 하드웨어 관련 구성요소 또는 제품 관련 구성요소는 없습니다. 특정 SSI의 모든 항목은 정의상 SSI를 사용하는 모든 기기 간에 공유됩니다. SSI는 그림 1과 같이 단일 /system 이미지 또는 /system/system_ext 파티션으로 구성됩니다.

    • /system 파티션에는 AOSP 기반 구성요소가 포함된 반면, /system_ext에는 구현된 경우 AOSP 구성요소와 긴밀하게 결합되어 있는 OEM 및 SoC 공급업체 확장 프로그램과 구성요소가 포함되어 있습니다. 예를 들어 OEM의 자체 앱에 맞춤 API를 제공하는 OEM 자바 프레임워크 라이브러리는 /system 파티션보다 /system_ext에 더 적합합니다. /system/system_ext 파티션의 콘텐츠는 OEM에서 수정한 Android 소스에서 빌드됩니다.

    • /system_ext 파티션은 선택사항이지만 AOSP 기반 구성요소와 긴밀하게 결합된 맞춤 기능 및 확장 프로그램에 사용하면 도움이 됩니다. 이러한 구별을 통해 변경해야 할 사항을 확인하고 일정 기간에 걸쳐 그러한 구성요소를 /system_ext 파티션에서 /product 파티션으로 이동할 수 있습니다.

  • 제품: Android OS에 대한 OEM 맞춤설정 및 확장 프로그램을 나타내는 제품 관련 또는 기기 관련 구성요소 모음입니다. SoC 관련 구성요소를 /vendor 파티션에 배치합니다. SoC 공급업체는 SoC의 영향을 받지 않는 구성요소와 같이 적절한 구성요소에 /product 파티션을 사용할 수도 있습니다. 예를 들어 SoC 공급업체가 SoC의 영향을 받지 않는 구성요소를 OEM 고객에게 제공하는 경우(제품과 함께 제공되는 선택사항) SoC 공급업체는 제품 이미지에 이 구성요소를 배치할 수 있습니다. 구성요소의 위치는 소유권이 아닌 목적에 의해 결정됩니다.

  • 공급업체: SoC 관련 구성요소 모음입니다.

  • ODM: SoC에서 제공하지 않는 보드 관련 구성요소 모음입니다. 일반적으로 SoC 공급업체는 공급업체 이미지를 소유하는 반면 기기 제조업체는 ODM 이미지를 소유합니다. 별도의 /odm 파티션이 없으면 SoC 공급업체와 ODM 이미지가 모두 /vendor 파티션에서 함께 병합됩니다.

이미지 간 인터페이스

공급업체 및 제품 이미지의 두 가지 기본 인터페이스는 SSI 주변에 있습니다.

  • 공급업체 인터페이스(VINTF): VINTF는 공급업체 및 ODM 이미지에 있는 구성요소의 인터페이스입니다. 제품 및 시스템 이미지의 구성요소는 이 인터페이스를 통해 공급업체 및 ODM 이미지와만 상호작용할 수 있습니다. 예를 들어 공급업체 이미지는 시스템 이미지의 비공개 부분에 의존할 수 없으며 반대의 경우도 마찬가지입니다. 이는 원래 프로젝트 Treble에 정의되어 있습니다. 프로젝트 Treble에서는 시스템과 공급업체 파티션으로 이미지를 분할했습니다. 인터페이스는 다음 메커니즘을 사용하여 설명됩니다.

    • HIDL(패스 스루 HAL은 systemsystem_ext 모듈에서만 사용할 수 있음)
    • 안정적 AIDL
    • 구성
      • System properties API
      • Config File Schema API
    • VNDK
    • Android SDK API
    • 자바 SDK 라이브러리
  • 제품 인터페이스: 제품 인터페이스는 SSI와 제품 이미지 간의 인터페이스입니다. 안정적인 인터페이스를 정의하면 SSI의 시스템 구성요소에서 제품 구성요소가 분리됩니다. 제품 인터페이스에는 VINTF와 동일한 안정적인 인터페이스가 필요합니다. 그러나 VNDK 및 Android SDK API만 Android 11 이상으로 출시되는 기기에 적용됩니다.

Android 11에서 SSI 사용 설정

이 섹션에서는 Android 11에서 SSI를 지원하는 새로운 기능을 사용하는 방법을 설명합니다.

/system_ext 파티션

/system_ext 파티션은 Android 11에서 선택적 파티션으로 도입되었습니다. /system 파티션의 AOSP 정의 구성요소와 긴밀하게 결합되어 있는 비 AOSP 구성요소의 위치입니다. /system_ext 파티션은 두 파티션에 걸쳐 정의된 인터페이스가 없는 /system 파티션의 OEM 관련 확장으로 간주됩니다. /system_ext 파티션의 구성요소는 /system 파티션으로 비공개 API를 호출할 수 있고 /system 파티션의 구성요소는 /system_ext 파티션으로 비공개 API를 호출할 수 있습니다.

두 파티션이 긴밀하게 결합되어 있으므로 새 Android 버전이 출시될 때 두 파티션은 함께 업그레이드됩니다. 이전 버전의 Android용으로 만들어진 /system_ext 파티션은 다음 Android 버전의 /system 파티션과 호환되지 않아도 됩니다.

/system_ext 파티션에 모듈을 설치하려면 Android.bp 파일에 system_ext_specific: true를 추가합니다. /system_ext 파티션이 없는 기기의 경우 이러한 모듈을 /system 파티션의 ./system_ext 하위 디렉터리에 설치합니다.

기록

다음은 /system_ext 파티션에 관한 기록입니다. 설계 목표는 모든 OEM 관련 구성요소를 공통되는지 여부와 상관없이 /product 파티션에 배치하는 것이었습니다. 그러나 특히 일부 구성요소가 /system 파티션과 긴밀하게 결합되어 있어 모든 구성요소를 한 번에 이동하는 일은 불가능했습니다. 긴밀하게 결합된 구성요소를 /product 파티션으로 이동하려면 제품 인터페이스를 확장해야 합니다. 이로 인해 종종 구성요소 자체를 광범위하게 리팩터링해야 했고 시간과 노력이 많이 들었습니다. /system_ext 파티션은 /product 파티션으로 이동할 준비가 되지 않은 이러한 구성요소를 임시로 호스팅하는 위치로 시작되었습니다. SSI의 목표는 최종적으로 /system_ext 파티션을 제거하는 것이었습니다.

그러나 /system_ext 파티션은 /system 파티션을 최대한 AOSP에 가깝게 유지하는 데 유용합니다. SSI를 사용하면 대부분의 업그레이드 작업이 /system/system_ext 파티션의 구성요소에 집중됩니다. 시스템 이미지가 AOSP의 소스와 최대한 유사한 소스에서 빌드되면 system_ext 이미지에 업그레이드 작업을 집중할 수 있습니다.

구성요소를 /system 파티션과 /system_ext 파티션에서 /product 파티션으로 번들 해제

Android 9에는 /system 파티션과 결합된 /product 파티션이 도입되었습니다. /product 파티션의 모듈은 아무 제한 없이 시스템 리소스를 사용하며 반대의 경우도 마찬가지입니다. Android 10에서 SSI를 사용하려면 제품 구성요소를 /system_ext/product 파티션으로 분할합니다. /system_ext 파티션은 Android 9의 /product 파티션처럼 시스템 구성요소 사용에 관한 제한사항을 준수하지 않아도 됩니다. Android 10부터 /product 파티션은 /system 파티션에서 번들 해제되어야 하며 /system/system_ext 파티션의 안정적인 인터페이스를 사용해야 합니다.

/system_ext 파티션의 기본 목적은 /system_ext partition 섹션에 설명된 대로 번들 제품 모듈을 설치하는 것이 아니라 시스템 기능을 확장하는 것입니다. 이렇게 하려면 제품 관련 모듈을 번들 해제하여 /product 파티션으로 이동합니다. 제품 관련 모듈을 번들 해제하면 /system_ext가 여러 기기에 공통이 됩니다. 자세한 내용은 /system_ext 파티션을 공통으로 만들기를 참고하세요.

시스템 구성요소에서 /product 파티션을 번들 해제하려면 /product 파티션에 이미 프로젝트 Treble과 함께 번들 해제된 /vendor 파티션과 동일한 시행 정책이 있어야 합니다.

Android 11부터 /product 파티션의 네이티브 및 자바 인터페이스가 아래 설명과 같이 적용됩니다. 자세한 내용은 제품 파티션 인터페이스 적용을 참고하세요.

  • 네이티브 인터페이스: /product 파티션의 네이티브 모듈은 다른 파티션에서 번들 해제해야 합니다. 유일하게 허용된 제품 모듈의 종속 항목은 /system 파티션의 VNDK 라이브러리(LLNDK 포함)입니다. 제품 앱에서 사용하는 JNI 라이브러리는 NDK 라이브러리여야 합니다.
  • 자바 인터페이스: /product 파티션의 자바(앱) 모듈은 숨겨진 API를 사용할 수 없습니다. 불안정하기 때문입니다. 이러한 모듈은 /system 파티션의 공개 API 및 시스템 API와 /system 또는 /system_ext 파티션의 자바 SDK 라이브러리만 사용해야 합니다. 맞춤 API를 위한 자바 SDK 라이브러리를 정의할 수 있습니다.

GSI 기반 SSI를 만들기 위한 권장 단계

GSI 기반 SSI 권장 파티션

그림 2. GSI 기반 SSI 권장 파티션

일반 시스템 이미지(GSI)는 AOSP에서 직접 빌드된 시스템 이미지입니다. Treble 규정 준수 테스트(예: CTS-on-GSI)에 사용되고 앱 개발자가 필요한 Android 버전을 실행하는 실제 기기가 없을 때 앱 호환성을 테스트하는 데 사용할 수 있는 참조 플랫폼으로 사용됩니다.

OEM은 GSI를 사용하여 SSI를 만들 수도 있습니다. 이미지와 파티션에서 설명한 것처럼 SSI는 AOSP 정의 구성요소의 시스템 이미지와 OEM 정의 구성요소의 system_ext 이미지로 구성됩니다. GSI가 system 이미지로 사용되면 OEM은 업그레이드를 위해 system_ext 이미지에 집중할 수 있습니다.

이 섹션에서는 AOSP 또는 AOSP에 가까운 시스템 이미지를 사용하는 동안 맞춤설정을 /system_ext/product 파티션으로 모듈화하려는 OEM에 관한 가이드를 제공합니다. OEM이 시스템 이미지를 AOSP 소스에서 빌드하면 AOSP에서 제공한 GSI로 빌드한 시스템 이미지를 대체할 수 있습니다. 그러나 OEM은 최종 단계(GSI를 그대로 사용)까지 한 번에 도달하지 않아도 됩니다.

1단계: OEM 시스템 이미지(OEM GSI)의 generic_system.mk 상속

generic_system.mk(Android 11에서는 이름이 mainline_system.mk였고 AOSP에서 generic_system.mk로 이름이 바뀜)를 상속함으로써 시스템 이미지(OEM GSI)에는 AOSP GSI에 있는 모든 파일이 포함됩니다. 이러한 파일은 OEM에 의해 수정될 수 있으므로 OEM GSI에 AOSP GSI 파일 외에도 OEM 독점 파일이 포함될 수 있습니다. 그러나 OEM은 generic_system.mk 파일을 수정할 수 없습니다.

OEM 시스템 이미지의 `generic_system.mk` 상속

그림 3. OEM 시스템 이미지의 generic_system.mk 상속

2단계: OEM GSI가 AOSP GSI와 동일한 파일 목록을 갖도록 만들기

OEM GSI는 이 단계에서 추가 파일을 포함할 수 없습니다. OEM의 독점 파일은 system_ext 또는 product 파티션으로 이동해야 합니다.

추가된 파일을 OEM GSI에서 이동

그림 4. 추가된 파일을 OEM GSI에서 이동

3단계: 허용 목록을 정의하여 OEM GSI에서 수정된 파일 제한

OEM은 수정된 파일을 확인하기 위해 compare_images 도구를 사용하여 AOSP GSI를 OEM GSI와 비교할 수 있습니다. AOSP lunch 타겟 generic_system_*에서 AOSP GSI를 가져옵니다.

compare_images 도구를 allowlist 매개변수와 함께 주기적으로 실행하여 허용되는 목록 외부의 차이를 모니터링할 수 있습니다. 이렇게 하면 OEM GSI를 추가로 수정할 필요가 없습니다.

허용 목록을 정의하여 OEM GSI에서 수정된 파일 목록 줄이기

그림 5. 허용 목록을 정의하여 OEM GSI에서 수정된 파일 목록 줄이기

4단계: OEM GSI가 AOSP GSI와 동일한 바이너리를 갖도록 만들기

허용 목록을 정리하면 OEM이 자체 제품의 시스템 이미지로 AOSP GSI를 사용할 수 있습니다. OEM은 허용 목록을 정리하기 위해 OEM GSI의 변경사항을 폐기하거나 AOSP GSI에 변경사항이 포함되도록 해당 변경사항을 AOSP로 업스트림할 수 있습니다.

OEM GSI가 AOSP GSI와 동일한 바이너리를 갖도록 만들기

그림 6. OEM GSI가 AOSP GSI와 동일한 바이너리를 갖도록 만들기

OEM용 SSI 정의

빌드 시간에 /system 파티션 보호

/system 파티션의 제품 관련 변경을 방지하고 OEM GSI를 정의하기 위해 OEM은 require-artifacts-in-path라는 makefile 매크로를 사용하여 매크로가 호출된 후 시스템 모듈 선언을 방지할 수 있습니다. makefile 만들기 및 아티팩트 경로 확인 사용 설정 예를 참고하세요.

OEM은 목록을 정의하여 제품 관련 모듈이 /system 파티션에 임시로 설치되도록 할 수 있습니다. 그러나 목록은 OEM GSI가 모든 OEM 제품에 공통되도록 비어 있어야 합니다. 이 프로세스는 OEM GSI를 정의하기 위한 것으로, AOSP GSI의 단계와 관련이 없을 수 있습니다.

제품 인터페이스 적용

/product 파티션이 번들 해제되도록 보장하려면 OEM은 PRODUCT_PRODUCT_VNDK_VERSION:= current를 네이티브 모듈에, PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE:= true를 자바 모듈에 설정하여 기기에서 제품 인터페이스를 적용하는지 확인하면 됩니다. 이러한 변수는 기기의 PRODUCT_SHIPPING_API_LEVEL30 이상인 경우 자동으로 설정됩니다. 자세한 내용은 제품 파티션 인터페이스 적용을 참고하세요.

/system_ext 파티션을 공통으로 만들기

/system_ext 파티션은 기기마다 다를 수 있습니다. 기기 관련 시스템 번들 모듈이 있을 수 있기 때문입니다. SSI는 /system/system_ext 파티션으로 구성되므로 /system_ext 파티션의 차이로 인해 OEM이 SSI를 정의하지 못합니다. OEM은 자체 SSI를 보유할 수 있고 차이를 제거하고 /system_ext 파티션을 공통으로 만들어 여러 기기 간에 SSI를 공유할 수 있습니다.

이 섹션에서는 /system_ext 파티션을 공통으로 만들기 위한 권장사항을 제공합니다.

시스템 파티션에서 숨겨진 API 노출

많은 제품 관련 애플리케이션은 제품 파티션에 설치할 수 없습니다. 제품 파티션에서 금지된 숨겨진 API를 사용하기 때문입니다. 기기 관련 애플리케이션을 제품 파티션으로 이동하려면 숨겨진 API 사용을 삭제하세요.

숨겨진 API를 애플리케이션에서 삭제하는 가장 좋은 방법은 대체 공개 API 또는 시스템 API를 찾아 대체하는 것입니다. 숨겨진 API를 대체할 API가 없다면 OEM은 AOSP에 참여하여 기기의 새로운 시스템 API를 정의하면 됩니다.

또는 OEM이 /system_ext 파티션에서 자체 자바 SDK 라이브러리를 만들어 맞춤 API를 정의할 수 있습니다. 시스템 파티션에서 숨겨진 API를 사용할 수 있고 제품 또는 공급업체 파티션의 애플리케이션에 API를 제공할 수 있습니다. OEM은 이전 버전과의 호환성을 위해 제품 관련 API를 중지해야 합니다.

모든 APK의 상위 집합 포함 및 각 기기의 일부 패키지 설치 건너뛰기

시스템과 함께 제공된 특정 패키지는 여러 기기에서 공통으로 사용되지 않습니다. 이러한 APK 모듈을 번들 해제하여 제품 또는 공급업체 파티션으로 이동하는 것은 어려울 수 있습니다. 임시 솔루션으로 OEM은 SSI에 모든 모듈이 포함되도록 하고 SKU 속성(ro.boot.hardware.sku)을 사용하여 원치 않는 모듈을 필터링할 수 있습니다. OEM은 필터를 사용하기 위해 프레임워크 리소스 config_disableApkUnlessMatchedSku_skus_listconfig_disableApksUnlessMatchedSku_apk_list를 오버레이합니다.

더 정확하게 설정하려면 필요하지 않은 패키지를 사용 중지하는 broadcast receiver를 선언합니다. broadcast receiver는 setApplicationEnabledSetting을 호출하여 ACTION_BOOT_COMPLETED 메시지를 수신할 때 패키지를 사용 중지합니다.

정적 리소스 오버레이를 사용하는 대신 RRO 정의

정적 리소스 오버레이는 오버레이된 패키지를 조작합니다. 그러나 SSI 정의를 방해할 수 있으므로 RRO의 속성이 사용 설정되고 올바르게 설정되어 있는지 확인합니다. 다음과 같이 속성을 설정하여 OEM은 자동 생성된 모든 오버레이를 RRO로 보유할 수 있습니다.

PRODUCT_ENFORCE_RRO_TARGETS := *
PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS := # leave it empty

자세한 구성이 필요하면 자동 생성된 구성을 사용하는 대신 RRO를 수동으로 정의합니다. 자세한 내용은 런타임 리소스 오버레이(RRO)를 참고하세요. OEM은 android:requiredSystemPropertyNameandroid:requiredSystemPropertyValue 속성을 사용하여 시스템 속성에 의존하는 조건부 RRO를 정의할 수도 있습니다.

자주 묻는 질문(FAQ)

여러 SSI를 정의할 수 있나요?

기기 또는 기기 그룹의 공통성과 특성에 따라 다릅니다. OEM은 system_ext 파티션을 공통으로 만들기에 설명된 대로 system_ext 파티션을 공통으로 만들려고 할 수 있습니다. 기기 그룹에 차이가 많은 경우 SSI를 여러 개 정의하는 것이 좋습니다.

OEM GSI의 generic_system.mk(mainline_system.mk)를 수정할 수 있나요?

아니요. 그러나 OEM은 generic_system.mk 파일을 상속하는OEM GSI의 새 makefile을 정의하여 대신 새 makefile을 사용할 수 있습니다. 예는 제품 파티션 인터페이스 적용을 참고하세요.

generic_system.mk에서 내 구현과 충돌하는 모듈을 삭제할 수 있나요?

아니요. GSI에는 부팅 가능하고 테스트 가능한 모듈이 최소한으로 있습니다. 모듈이 필요하지 않다고 생각되면 버그를 신고하여 AOSP에서 generic_system.mk 파일을 업데이트하세요.