본문 바로가기

개발이야기/Android

Android Q 부터 비 SDK 인터페이스 제한 하는 이유와 비 SDK 인터페이스 제한 확인하는 방법

android Q targetSdkVerison부터 공개된 SDK API만 사용가능하다. 

이에 따라 android Q를 targetSdkVersion으로 하는 application은 공식 SDK인터페이스가 아닌 기능에는 접근하지 못하도록 제한한다.(공식홈페이지 참고)

왜 비 SDK를 제한하게 되었나?

안드로이드에서 @hide annotation으로 선언한 여러 sdk(android.xxx.xxx 같은 package)의 method들이 존재한다. @hide 구문을 사용하면 android내부에서만 접근 가능하고, 외부(application)은 접근하지 못하며 공식 패키지 색인에도 노출되지 않는다. 즉, 공식적으로 application단에서 사용이 불가하도록 선언해 놓은것이다.

 

그러나, 많은 전세계의 개발자들이 개발 편의를 위해 @hide method를 application단에서 java의 class invokation 혹은 reflection 혹은 @hide annotation을 강제로 지우고 사용하는 일이 빈번했다.

 

예를 들어 Wifi mode에서 access point를 scan하는 method가 @hide startScanActive()로 선언되어있는데, application이 호출할 수 없게되어 있음. 강제로 reflection을 통해 application이 method를 호출.

 

이와 같은 사용 패턴을막아서 android application을 사용하는 사용자와 개발자의 환경을 개선하고 사용자의 비정상 종료 위험과 개발자의 긴급 출시 위험을 줄이기 위해 android Q 부터는 non-sdk interface를 사용하지 못하게 제한하게 되었다.(구글 공식 블로그 설명글(바로가기))


SDK와 비 SDK 인터페이스

공개 SDK인터페이스는 Android 프레임워크 패키지 색인에 문서화 되어 있다. > 패키지색인(바로가기)
상기 공식 문서화 되어있는 부분만 사용. 상기 공식 문서화 되어 있지 않은 SDK의 api들에 대해서 강제로 java reflection을 주입하여 사용하는 경우에 대해서 android Q 부터는 사용 불가하다.

블랙리스트/그레이리스트/허용 구분

android Q가 targetSdkVersion으로 사용할경우

Blacklist 사용할 수 없는 비 SDK 인터페이스 액세스 불가하여 시스템오류 발생
Graylist Light graylist : 제한되지 않은 그레이 리스트의 비 SDK인터페이스
Dark graylist : 제한된 그레이 리스트의 비 SDK인터페이스
허용 자유롭게 사용가능한 공식 문서화된 패키지들

제한된 비 SDK interface를 사용시 예상되는 동작

필드를 참조하는 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 인터페이스가 포함되어 있는지 테스트하는 방법

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

앱을 빌드하고 Android Q os가 올라간 기기에서 앱을 실행하면 테스트를 실행하는동안 비 SDK 인터페이스에 액세스하는경우 로그 메시지를 출력.

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

android studio를 통해 logcat을 사용하면 아래와 같은 로그를 확인 할 수 있고 이에 대응하여 확인 가능.

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

 

2.StrictMode API를 사용한 테스트

detectNonSdkApiUsage(바로가기)를 사용. penaltyListener(바로가기)을 사용하여 비 sdk 인터페이스를 사용할 때 마다 콜백 받을 수 있음.

3.veridex 도구를 사용한 테스트

veridex 도구(바로가기)를 통해 apk를 code base로 검색, 노출
단, 아래와 같은 경우 검출 불가

  • JNI(C,C++)을 통한 호출
  • 리플렉션을 통한 호출의 경우 일부감지
  • API수준 검사로 제한