제품 파티션 인터페이스 적용

Android 11은 product 파티션을 번들 해제하여 systemvendor 파티션과 독립적으로 만듭니다. 이러한 변경의 일환으로 이제 product 파티션의 네이티브 및 자바 인터페이스 액세스를 제어할 수 있습니다. 이는 인터페이스 적용이 vendor 파티션에 작동하는 방식과 유사합니다.

네이티브 인터페이스 적용

네이티브 인터페이스 적용을 사용 설정하려면 PRODUCT_PRODUCT_VNDK_VERSIONcurrent로 설정합니다. 버전은 타겟의 배송 API 수준이 29보다 클 때 current로 자동 설정됩니다. 적용에서는 다음이 허용됩니다.

  • product 파티션의 네이티브 모듈이 다음에 연결할 수 있습니다.
    • 정적, 공유 또는 헤더 라이브러리가 포함된 product 파티션의 다른 모듈에 정적 또는 동적으로 연결할 수 있습니다.
    • system 파티션의 VNDK 라이브러리에 동적으로 연결할 수 있습니다.
  • product 파티션에 있는 번들 해제된 APK의 JNI 라이브러리가 /product/lib 또는 /product/lib64의 라이브러리에 연결할 수 있습니다(NDK 라이브러리에 추가됨).

적용에서는 product 파티션 외에 다른 파티션 링크를 허용하지 않습니다.

빌드 시간 적용(Android.bp)

Android 11에서는 시스템 모듈이 코어 및 공급업체 이미지 변형 외에도 제품 이미지 변형을 만들 수 있습니다. 네이티브 인터페이스 적용이 사용 설정될 때(PRODUCT_PRODUCT_VNDK_VERSIONcurrent로 설정됨):

  • product 파티션의 네이티브 모듈은 코어 변형이 아닌 제품 변형에 있습니다.

  • Android.bp 파일의 vendor_available: true가 있는 모듈은 제품 변형과 공급업체 변형에서 사용할 수 있습니다.

  • product_specific: true를 지정하는 라이브러리나 바이너리는 Android.bp 파일에서 product_specific: truevendor_available: true를 지정하는 다른 라이브러리에 연결할 수 있습니다.

  • product 바이너리가 VNDK 라이브러리에 연결할 수 있도록 VNDK 라이브러리는 Android.bp 파일에 vendor_available: true가 있어야 합니다.

다음 표에는 이미지 변형을 만드는 데 사용되는 Android.bp 속성이 요약되어 있습니다.

Android.bp의 속성 생성된 변형
적용 전 적용 후
기본값(없음) 코어

(/system, /system_ext, /product 포함)

코어

(/system, /system_ext는 포함하고 /product는 포함하지 않음)

system_ext_specific: true 코어 코어
product_specific: true 코어 제품
vendor: true 공급업체 공급업체
vendor_available: true 코어, 공급업체 코어, 제품, 공급업체
system_ext_specific: truevendor_available: true 코어, 공급업체 코어, 제품, 공급업체
product_specific: truevendor_available: true 코어, 공급업체 제품, 공급업체

빌드 시간 적용(Android.mk)

네이티브 인터페이스 적용이 사용 설정된 경우 product 파티션에 설치된 네이티브 모듈에는 다른 native:productnative:vndk 모듈에만 연결할 수 있는 native:product 링크 유형이 있습니다. 이러한 모듈 외 다른 모듈에 연결하려고 하면 빌드 시스템에서 링크 유형 확인 오류가 발생합니다.

런타임 적용

네이티브 인터페이스 적용이 사용 설정되면 Bionic 링커의 링커 구성이 시스템 프로세스가 product 라이브러리를 사용하도록 허용하지 않으므로 product 파티션 외부의 라이브러리에 연결할 수 없는 product 프로세스의 product 섹션을 만듭니다(그러나 이러한 프로세스는 VNDK 라이브러리에는 연결할 수 있음). 런타임 링크 구성을 위반하려고 하면 프로세스가 실패하고 CANNOT LINK EXECUTABLE 오류 메시지가 생성됩니다.

자바 인터페이스 적용

자바 인터페이스 적용을 사용 설정하려면 PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACEtrue로 설정합니다. 값은 타겟의 배송 API 수준이 29보다 클 때 true로 자동 설정됩니다. 사용 설정되면 적용은 다음 액세스를 허용하거나 허용하지 않습니다.

API /system /system_ext /product /vendor /data
공개 API
@SystemApi
@hide API

vendor 파티션에서와 같이 product 파티션의 앱이나 자바 라이브러리는 공개 및 시스템 API만 사용할 수 있습니다. 숨겨진 API를 사용하는 라이브러리에 연결하는 것은 허용되지 않습니다. 이러한 제한에는 빌드 시간에 연결과 런타임에 리플렉션이 포함됩니다.

빌드 시간 적용

빌드 시간에 Make와 Soong은 platform_apissdk_version 필드를 확인하여 product 파티션의 자바 모듈이 숨겨진 API를 사용하지 않는지 확인합니다. product 파티션에 있는 앱의 sdk_version은 API의 current, system_current 또는 숫자 버전으로 채워져야 하고 platform_apis 필드는 비어 있어야 합니다.

런타임 적용

Android 런타임은 product 파티션의 앱이 리플렉션 등 숨겨진 API를 사용하지 않는지 확인합니다. 자세한 내용은 비 SDK 인터페이스 제한사항을 참고하세요.

제품 인터페이스 적용 사용 설정

이 섹션의 단계를 따라 제품 인터페이스 적용을 사용 설정하세요.

단계 작업 필수
1 system 파티션의 패키지를 지정하는 자체 시스템 makefile을 정의하고 device.mk에서 아티팩트 경로 요구사항 확인을 설정합니다(system 파티션에 시스템이 아닌 모듈이 설치되는 것을 방지하기 위함). 아니요
2 허용 목록을 정리합니다. 아니요
3 네이티브 인터페이스를 적용하고 런타임 링크 실패를 식별합니다(자바 적용과 동시에 실행할 수 있음).
4 자바 인터페이스를 적용하고 런타임 동작을 확인합니다(네이티브 적용과 동시에 실행할 수 있음).
5 런타임 동작을 확인합니다.
6 제품 인터페이스 적용으로 device.mk를 업데이트합니다.

1단계: makefile 만들기 및 아티팩트 경로 확인 사용 설정

이 단계에서는 system makefile을 정의합니다.

  1. system 파티션의 패키지를 정의하는 makefile을 만듭니다. 예를 들어 다음을 사용하여 oem_system.mk 파일을 만듭니다.

    $(call inherit-product, $(SRC_TARGET_DIR)/product/handheld_system.mk)
    $(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system.mk)
    
    # Applications
    PRODUCT_PACKAGES += \
        CommonSystemApp1 \
        CommonSystemApp2 \
        CommonSystemApp3 \
    
    # Binaries
    PRODUCT_PACKAGES += \
        CommonSystemBin1 \
        CommonSystemBin2 \
        CommonSystemBin3 \
    
    # Libraries
    PRODUCT_PACKAGES += \
        CommonSystemLib1 \
        CommonSystemLib2 \
        CommonSystemLib3 \
    
    PRODUCT_SYSTEM_NAME := oem_system
    PRODUCT_SYSTEM_BRAND := Android
    PRODUCT_SYSTEM_MANUFACTURER := Android
    PRODUCT_SYSTEM_MODEL := oem_system
    PRODUCT_SYSTEM_DEVICE := generic
    
    # For system-as-root devices, system.img should be mounted at /, so we
    # include ROOT here.
    _my_paths := \
     $(TARGET_COPY_OUT_ROOT)/ \
     $(TARGET_COPY_OUT_SYSTEM)/ \
    
    $(call require-artifacts-in-path, $(_my_paths),)
    
  2. device.mk 파일에서 system 파티션의 공통 makefile을 상속하고 아티팩트 경로 요구사항 확인을 사용 설정합니다. 예:

    $(call inherit-product, $(SRC_TARGET_DIR)/product/oem_system.mk)
    
    # Enable artifact path requirements checking
    PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS := strict
    

아티팩트 경로 요구사항 정보

PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTStruestrict로 설정되면 빌드 시스템은 다른 makefile에서 정의된 패키지가 require-artifacts-in-path에서 정의된 경로에 설치되는 것을 방지하고 또한 현재 makefile에서 정의된 패키지가 require-artifacts-in-path에서 정의된 경로 외부에 아티팩트를 설치하는 것을 방지합니다.

위의 예에서 PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTSstrict로 설정되면 oem_system.mk 외부의 makefile에는 root 또는system 파티션에 설치된 모듈이 포함될 수 없습니다. 이러한 모듈을 포함하려면 oem_system.mk 파일 자체 또는 포함된 makefile에서 모듈을 정의해야 합니다. 허용되지 않은 경로에 모듈을 설치하려고 하면 빌드가 중단됩니다. 중단 문제를 해결하려면 다음 중 하나를 실행하세요.

  • 옵션 1: oem_system.mk에 포함된 makefile에 시스템 모듈을 포함합니다. 이렇게 하면 아티팩트 경로 요구사항이 충족되어(모듈이 이제 포함된 makefile에 있으므로) `require-artifacts-in-path의 경로 집합에 설치할 수 있습니다.

  • 옵션 2: system_ext 또는 product 파티션에 모듈을 설치합니다. system 파티션에는 모듈을 설치하지 않습니다.

  • 옵션 3: PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST에 모듈을 추가합니다. 여기에는 설치가 허용된 모듈이 나열되어 있습니다.

2단계: 허용 목록 비우기

이 단계에서는 oem_system.mk를 공유하는 모든 기기가 단일 system 이미지도 공유할 수 있도록 PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST를 비웁니다. 허용 목록을 비우려면 목록의 모듈을 system_ext 또는 product 파티션으로 이동하거나 system makefile에 추가합니다. 이 단계는 선택사항입니다. 공통 system 이미지를 정의하는 것은 제품 인터페이스 적용을 사용 설정하는 데 필요하지 않기 때문입니다. 그러나 허용 목록을 비우는 것은 system_extsystem 경계를 정의하는 데 도움이 됩니다.

3단계: 네이티브 인터페이스 적용

이 단계에서는 PRODUCT_PRODUCT_VNDK_VERSION := current를 설정하고 빌드 및 런타임 오류를 찾아 해결합니다. 기기 부팅 및 로그를 확인하고 런타임 링크 실패를 찾아 해결하려면 다음을 실행하세요.

  1. PRODUCT_PRODUCT_VNDK_VERSION := current를 설정합니다.

  2. 기기를 빌드하고 빌드 오류를 찾습니다. 누락된 제품 변형이나 코어 변형의 몇 가지 빌드 중단이 발생할 수 있습니다. 일반적인 중단은 다음과 같습니다.

    • product_specific: true가 있는 모든 hidl_interface 모듈은 시스템 모듈에서 사용할 수 없습니다. 이 오류를 해결하려면 product_specific: truesystem_ext_specfic: true로 바꿉니다.
    • 모듈에는 제품 모듈에 필요한 제품 변형이 누락되어 있을 수 있습니다. 이 오류를 해결하려면 vendor_available: true를 설정하여 이 모듈을 product 파티션에서 사용할 수 있도록 하거나 product_specific: true를 설정하여 모듈을 product 파티션으로 이동합니다.
  3. 빌드 오류를 해결하고 기기가 성공적으로 빌드되는지 확인합니다.

  4. 이미지를 플래시하고 기기 부팅 및 로그에서 런타임 오류를 찾습니다.

    • 테스트 사례 로그의 linker 태그에 CANNOT LINK EXECUTABLE 메시지가 표시되면 makefile에 종속 항목이 누락되어 있습니다(빌드 시간에 캡처되지 않았음).
    • 빌드 시스템에서 이를 확인하려면 필수 라이브러리를 shared_libs: 또는 required: 필드에 추가합니다.
  5. 위의 안내에 따라 누락된 종속 항목 문제를 해결합니다.

4단계: 자바 인터페이스 적용

이 단계에서는 PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true를 설정하고 결과로 생긴 빌드 오류를 찾아 해결합니다. 다음 두 가지 특정 유형의 오류를 찾으세요.

  • 링크 유형 오류. 이 오류는 앱이 더 광범위한 sdk_version이 있는 자바 모듈에 연결된다고 나타냅니다. 오류를 해결하려면 앱의 sdk_version을 확장하거나 라이브러리의 sdk_version을 제한하면 됩니다. 오류 예:

    error: frameworks/base/packages/SystemUI/Android.bp:138:1: module "SystemUI" variant "android_common": compiles against system API, but dependency "telephony-common" is compiling against private API.Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.
    
  • 기호 오류. 이 오류는 기호가 숨겨진 API에 있어서 찾을 수 없다고 나타냅니다. 오류를 해결하려면 표시되는(숨겨지지 않음) API를 사용하거나 대안을 찾습니다. 오류 예:

    frameworks/opt/net/voip/src/java/com/android/server/sip/SipSessionGroup.java:1051: error: cannot find symbol
                ProxyAuthenticate proxyAuth = (ProxyAuthenticate)response.getHeader(
                                               ^
      symbol:   class ProxyAuthenticate
      location: class SipSessionGroup.SipSessionImpl
    

5단계: 런타임 동작 확인

이 단계에서는 런타임 동작이 예상대로 작동하는지 확인합니다. 디버그 가능한 앱의 경우 앱이 숨겨진 API를 사용할 때 로그를 생성하는 StrictMode.detectNonSdkApiUsage를 사용하여 로그를 통해 숨겨진 API 사용을 모니터링할 수 있습니다. 또는 veridex 정적 분석 도구를 사용하여 사용 유형(연결 또는 리플렉션), 제한 수준, 호출 스택을 가져올 수 있습니다.

  • veridex 구문:

    ./art/tools/veridex/appcompat.sh --dex-file={apk file}
  • veridex 결과 예:

    #1: Linking greylist-max-o Landroid/animation/AnimationHandler;-><init>()V use(s):
           Lcom/android/systemui/pip/phone/PipMotionHelper;-><init>(Landroid/content/Context;Landroid/app/IActivityManager;Landroid/app/IActivityTaskManager;Lcom/android/systemui/pip/phone/PipMenuActivityController;Lcom/android/internal/policy/PipSnapAlgorithm;Lcom/android/systemui/statusbar/FlingAnimationUtils;)V
    
    #1332: Reflection greylist Landroid/app/Activity;->mMainThread use(s):
           Landroidx/core/app/ActivityRecreator;->getMainThreadField()Ljava/lang/reflect/Field;
    

veridex 사용에 관한 자세한 내용은 veridex 도구를 사용하여 테스트를 참고하세요.

6단계: device.mk 업데이트

빌드 및 런타임 실패를 모두 해결하고 런타임 동작이 예상대로 작동하는지 확인한 후 device.mk에서 다음을 설정합니다.

  • PRODUCT_PRODUCT_VNDK_VERSION := current
  • PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE := true