비 SDK 인터페이스 제한사항

Android 9(API 수준 28)부터 플랫폼에서는 앱에서 사용할 수 있는 비 SDK 인터페이스가 제한되어 있습니다. 이러한 제한사항은 앱에서 비 SDK 인터페이스를 참조하거나 리플렉션 또는 JNI를 사용해 비 SDK 인터페이스의 핸들을 가져오려고 시도할 때마다 적용됩니다. 이는 사용자와 개발자의 환경을 개선하고 사용자의 비정상 종료 위험과 개발자의 긴급 출시 위험을 줄이기 위해 마련되었습니다. 이러한 결정에 대한 자세한 내용은 비 SDK 인터페이스 사용을 줄여 안정성 향상을 참조하세요.

SDK와 비 SDK 인터페이스의 구분

일반적으로 공개 SDK 인터페이스는 Android 프레임워크 패키지 색인에 문서화되어 있습니다. 비 SDK 인터페이스 처리는 API별 구현 세부정보이므로 이러한 인터페이스는 별도의 공지 없이 변경될 수 있습니다.

비정상 종료나 예기치 않은 동작을 방지하려면 앱에서 SDK의 클래스 중 공식적으로 문서화된 부분만 사용해야 합니다. 또한 리플렉션과 같은 메커니즘을 통해 클래스와 상호작용할 때 SDK에 등록되지 않은 메소드나 필드에 액세스하면 안 됩니다.

블랙리스트, 그레이리스트, 허용 목록

Android가 출시될 때마다 비 SDK 인터페이스가 추가로 제한됩니다. Google에서는 이러한 제한사항이 출시 워크플로에 영향을 줄 수 있음을 알고 있기 때문에 개발자에게 비 SDK 인터페이스 사용을 감지하는 도구, Google에 의견을 보낼 기회, 새로운 정책을 계획하고 조정할 시간을 제공하고자 합니다.

개발 워크플로에 비 SDK 제한사항이 미치는 영향을 최소화하기 위해 비 SDK 인터페이스는 타겟팅되는 API 수준에 따라 사용이 제한되는 정도를 정의하는 목록으로 나뉩니다. 다음 표에서는 이러한 각 목록을 설명합니다.

목록 설명
블랙리스트 앱의 타겟 API 수준과 상관없이 사용할 수 없는 비 SDK 인터페이스입니다. 앱에서 이러한 인터페이스 중 하나에 액세스하려고 하면 시스템에 오류가 발생합니다.
그레이리스트 앱의 타겟 API 수준에서 제한되지 않는 한 사용할 수 있는 비 SDK 인터페이스입니다.

Android 9(API 수준 28)부터 각 API 수준에 제한되는 비 SDK 인터페이스가 포함됩니다. 앱에서 낮은 API 수준을 타겟팅하는 경우 제한된 그레이리스트 API에 액세스할 수 있지만, 앱이 타겟 API 수준에서 제한되는 비 SDK 인터페이스에 액세스하려고 하면 시스템이 API가 블랙리스트에 포함된 것처럼 작동합니다.

참고: Android 9(API 수준 28)에서는 제한되지 않은 그레이리스트의 비 SDK 인터페이스를 라이트그레이 목록, 제한된 그레이리스트의 비 SDK 인터페이스를 다크그레이 목록이라고 했습니다.

허용 목록 자유롭게 사용할 수 있으며 공식 문서화된 Android 프레임워크 패키지 색인의 일부로 지원되는 인터페이스입니다.

현재 앱의 타겟 API 수준에 따라 그레이리스트에 속한 일부 비 SDK 인터페이스를 사용할 수 있지만, 비 SDK 메소드나 필드를 사용하면 항상 앱이 중단될 위험이 높습니다. 앱에서 비 SDK 인터페이스를 사용해야 하는 경우 SDK 인터페이스나 다른 대안으로 이전할 계획을 세워야 합니다. 앱 기능을 구현하기 위해 비 SDK 인터페이스를 사용하는 것 외에 방법을 찾을 수 없는 경우에는 새 공개 API를 요청해야 합니다.

인터페이스가 속한 목록 확인

비 SDK 인터페이스의 목록은 플랫폼의 일부로 빌드됩니다.

Android 9(API 수준 28)에서는 제한되지 않은 그레이리스트 API 목록이 이 텍스트 파일에 포함되어 있습니다. 블랙리스트와 제한된 그레이리스트는 빌드 시 파생됩니다. AOSP에 목록을 생성하는 빌드 규칙이 있습니다. AOSP 목록은 Android 9의 목록과 동일하지 않지만 상당히 많은 부분이 겹칩니다. AOSP를 다운로드하고 다음 명령어를 실행하여 블랙리스트를 직접 생성할 수도 있습니다.

make hiddenapi-aosp-blacklist
    

그러면 다음 위치에서 파일을 찾을 수 있습니다.

out/target/common/obj/PACKAGING/hiddenapi-aosp-blacklist.txt
    

제한된 비 SDK 인터페이스에 액세스할 때 예상되는 동작

다음 표에서는 앱에서 블랙리스트에 속하지 않은 비 SDK 인터페이스에 액세스하려고 시도하는 경우 예상되는 동작을 확인할 수 있습니다.

액세스 수단 결과
필드를 참조하는 Dalvik 명령어 NoSuchFieldError 발생
메소드를 참조하는 Dalvik 명령어 NoSuchMethodError 발생
Class.getDeclaredField() 또는 Class.getField()를 통한 리플렉션 NoSuchFieldException 발생
Class.getDeclaredMethod(), Class.getMethod()를 통한 리플렉션 NoSuchMethodException 발생
Class.getDeclaredFields(), Class.getFields()를 통한 리플렉션 결과에 비 SDK 구성원 없음
Class.getDeclaredMethods(), Class.getMethods()를 통한 리플렉션 결과에 비 SDK 구성원 없음
env->GetFieldID()를 통한 JNI NULL이 반환되고 NoSuchFieldError 발생
env->GetMethodID()를 통한 JNI NULL이 반환되고 NoSuchMethodError 발생

앱의 비 SDK 인터페이스 테스트

앱의 비 SDK 인터페이스 테스트에 사용할 수 있는 방법에는 여러 가지가 있습니다.

디버깅 가능한 앱을 사용해 테스트

Android 9(API 수준 28) 이상을 실행하는 기기나 에뮬레이터에서 디버그 가능한 앱을 빌드하고 실행하여 비 SDK 인터페이스를 테스트할 수 있습니다. 사용 중인 기기나 에뮬레이터가 앱의 타겟 API 수준과 일치하는지 확인하세요.

앱에서 테스트를 실행하는 동안 앱에서 특정 비 SDK 인터페이스에 액세스하는 경우 시스템에서 로그 메시지를 출력합니다. 앱의 로그 메시지에서 다음 세부정보를 찾을 수 있습니다.

  • 선언하는 클래스, 이름, 유형(Android 런타임에서 사용하는 형식)
  • 액세스 수단: 연결, 리플렉션 또는 JNI를 통해
  • 비 SDK 인터페이스가 속한 목록

adb logcat를 사용해 실행 중인 앱의 PID 아래 표시되는 이러한 로그 메시지에 액세스할 수 있습니다. 예를 들어 로그 항목의 형식은 다음과 같을 수 있습니다.

Accessing hidden field Landroid/os/Message;->flags:I (light greylist, JNI)
    

StrictMode API를 사용해 테스트

StrictMode API를 사용해 비 SDK 인터페이스를 테스트할 수도 있습니다. API를 사용 설정하려면 detectNonSdkApiUsage 메소드를 사용하세요. StrictMode API를 사용 설정한 후 맞춤 처리를 구현할 수 있는 penaltyListener를 사용하여 비 SDK 인터페이스를 사용할 때마다 콜백을 받을 수 있습니다. 콜백에 제공된 Violation 개체는 Throwable에서 파생되며 포함된 스택 추적에서 사용 컨텍스트를 제공합니다.

veridex 도구를 사용해 테스트

APK에서 정적 분석 도구인 veridex를 실행할 수도 있습니다. veridex 도구는 타사 라이브러리를 비롯한 APK의 전체 코드베이스를 검사한 후 발견되는 모든 비 SDK 인터페이스 사용을 보고합니다.

veridex 도구의 한계는 다음과 같습니다.

  • JNI를 통한 호출은 감지할 수 없습니다.
  • 리플렉션을 통한 호출의 경우 일부만 감지할 수 있습니다.
  • 비활성 코드 경로 분석이 API 수준 검사로 제한됩니다.

새 공개 API 요청

앱 기능을 구현하기 위해 비 SDK 인터페이스를 사용하는 것 외에 방법을 찾을 수 없는 경우, 새 공개 API가 SDK에 추가되도록 기능을 요청할 수 있습니다.

기능을 요청할 때는 다음 정보를 제공하세요.

  • 현재 사용 중인 그레이리스트 API(Accessing hidden ...logcat 메시지에 표시되는 전체 설명어 포함)
  • 이 API를 사용해야 하는 이유(낮은 수준의 세부정보뿐 아니라 API가 필요한 높은 수준의 기능에 관한 세부정보 포함)
  • 관련된 모든 공개 SDK API가 용도에 충분하지 않은 이유
  • 시도한 모든 대안과 대안이 효과가 없었던 이유

기능 요청에 이러한 세부정보를 제공하면 새 공개 API가 지원될 가능성이 높아집니다.

기타 문의

이 섹션에서는 개발자가 자주 묻는 기타 질문에 대한 일부 답변을 확인할 수 있습니다.

일반적인 질문

Google에서는 어떻게 문제 트래커를 통해 모든 앱의 요구사항이 파악된다고 확신할 수 있나요?

Google에서는 다음 방법으로 보완된 앱의 정적 분석을 통해 Android 9(API 수준 28)의 초기 목록을 만들었습니다.

  • 상위 Play 및 Play 이외의 앱을 수동으로 테스트
  • 내부 보고서
  • 내부 사용자로부터 자동으로 데이터 수집
  • 개발자 미리보기 보고서
  • 거짓양성을 더 포함하도록 보수적으로 설계된 추가 정적 분석

새로 출시되는 각 목록을 평가할 때는 문제 트래커를 통해 API 사용뿐 아니라 개발자 의견도 고려합니다.

비 SDK 인터페이스에 액세스할 수 있도록 설정하려면 어떻게 해야 하나요?

다음 adb 명령어를 사용해 API 시행 정책을 변경하여 개발 기기에서 비 SDK 인터페이스에 액세스하도록 설정할 수 있습니다.

adb shell settings put global hidden_api_policy_pre_p_apps  1
    adb shell settings put global hidden_api_policy_p_apps 1
    

API 시행 정책을 기본 설정으로 재설정하려면 다음 명령어를 사용하세요.

adb shell settings delete global hidden_api_policy_pre_p_apps
    adb shell settings delete global hidden_api_policy_p_apps
    

이러한 명령어를 사용하는 데는 루팅된 기기가 필요하지 않습니다.

API 시행 정책의 정수는 다음 값 중 하나로 설정할 수 있습니다.

  • 0: 비 SDK 인터페이스의 모든 감지를 사용 중지합니다. 이 설정을 사용하면 비 SDK 인터페이스 사용에 관한 모든 로그 메시지가 사용 중지되고 StrictMode API를 사용해 앱을 테스트할 수 없습니다. 이 설정은 사용하지 않는 것이 좋습니다.
  • 1: 모든 비 SDK 인터페이스에 액세스할 수 있지만 비 SDK 인터페이스를 사용하면 경고와 함께 로그 메시지가 출력됩니다. 이 설정을 사용하면 StrictMode API를 사용해 앱을 테스트할 수도 있습니다.
  • 2: 블랙리스트 또는 그레이리스트에 속하고 타겟 API 수준에서 제한되는 비 SDK 인터페이스의 사용이 금지됩니다.
  • 3: 블랙리스트에 속한 비 SDK 인터페이스의 사용은 금지되지만, 그레이리스트에 속하고 타겟 API 수준에서 제한되는 인터페이스의 사용은 허용됩니다.

비 SDK 인터페이스 목록에 대한 질문

시스템 이미지에서 블랙리스트와 그레이리스트는 어디에서 찾을 수 있나요?

블랙리스트와 그레이리스트는 플랫폼 dex 파일의 필드 및 메소드 액세스 플래그 비트에 인코딩되어 있습니다. 시스템 이미지에 이러한 목록이 포함된 별도의 파일은 없습니다.

동일한 Android 버전을 사용하는 서로 다른 OEM 기기에서는 블랙리스트와 그레이리스트가 동일한가요?

OEM에서는 자체 인터페이스를 블랙리스트에 추가할 수 있지만 AOSP 블랙리스트 또는 그레이리스트에서 인터페이스를 삭제할 수는 없습니다. CDD는 이러한 변경을 금지하며 CTS는 테스트를 통해 Android 런타임이 목록을 시행하고 있는지 확인합니다.

네이티브 코드에 비 NDK 인터페이스 관련 제한사항이 있나요?

Android SDK에는 자바 인터페이스가 포함되어 있습니다. 플랫폼에서는 Android 7(API 수준 26)에서 네이티브 C/C++ 코드의 비 NDK 인터페이스에 대한 액세스를 제한하기 시작했습니다. 자세한 내용은 Android N에서 비공개 C/C++ 기호 제한사항으로 안정성 향상을 참조하세요.

dex2oat 또는 DEX 파일 조작을 제한할 계획이 있나요?

dex2oat 바이너리에 대한 액세스를 제한할 적극적인 계획은 없지만, DEX 파일 형식을 안정화하거나 Dalvik 실행 가능 형식에 공개적으로 지정된 부분을 넘어서는 공개 인터페이스로 만들지도 않을 것입니다. Google은 언제든 dex2oat 및 DEX 형식의 지정되지 않은 부분을 수정하거나 제거할 권리를 보유합니다. 또한 ODEX(OAT라고도 함), VDEX, CDEX 등 dex2oat에서 생성된 파생 파일은 모두 지정되지 않은 형식입니다.

중요한 타사 SDK(예: Obfuscator)에서 비 SDK 인터페이스 사용을 피할 수 없지만 향후 Android 버전과의 호환성 유지를 약속하는 경우 어떻게 하나요? 이 경우 Android에서 호환성 요구사항을 포기할 수 있나요?

Google에서는 SDK별로 호환성 요구사항을 포기할 계획이 없습니다. SDK 개발자가 현재 그레이리스트의 인터페이스에 따라서만 호환성을 유지할 수 있다면 SDK 인터페이스 또는 다른 대안으로 이전을 계획해야 하며, 비 SDK 인터페이스 사용에 대한 대안을 찾을 수 없는 경우 새 공개 API를 요청해야 합니다.

 

비 SDK 인터페이스 제한사항은 타사 앱뿐 아니라 시스템 및 자사 앱을 포함한 모든 앱에 적용되나요?

예. 하지만 플랫폼 키로 서명된 앱에는 예외가 적용되며 일부 시스템 이미지 앱의 경우 패키지 허용 목록도 마련되어 있습니다. 이러한 예외는 시스템 이미지에 속한 앱(또는 업데이트된 시스템 이미지 앱)에만 적용됩니다. 이 목록은 LOCAL_PRIVATE_PLATFORM_APIS := true인 SDK API가 아닌 비공개 플랫폼 API를 대상으로 빌드된 앱에만 사용됩니다.