https://nobase-dev.tistory.com/77



전원 관리와 관련하여 앱 대기 버킷 추가 및 배터리 세이버 개선

개인정보 보호정책 변경

  • 백그라운드 센서 액세스 제한
  • 통화 로그/전화번호 액세스 제한
  • Wi-Fi 관련 액세스 제한

리플렉션이나 JNI를 이용한 비 SDK 인터페이스 사용 제한

보안 동작 관련하여 암호화 알고리즘 구현 변경 및 ASEC 지원 제거됨

ICU 라이브러리 60 업데이트로 시간대 및 통화 텍스트 처리가 일부 변경됨

Android 테스트를 위한 JUnit 기반 클래스 재구성

Java UTF 디코더에서 엄격한 Unicode 표준 준수

인증서를 사용한 서버 호스트 이름 확인

StrictMode를 통한 네트워크 주소 조회시 발생하는 네트워크 위반 감지

소켓 태그 제거 및 사용 가능 바이트 크기 보고 변경

xt_qtaguid 폴더의 파일을 더 이상 앱에 직접 사용 불가함

비 액티비티 컨텍스트에서 FLAG_ACTIVITY_NEW_TASK 전달하지 않을 시 액티비티 시작 안됨

화면회전 모드인 세로 회전 모드가 회전 잠금 기능으로 변경

비표준 ClassLoader를 사용하여 Apache HTTP 클라이언트 사용 제한

전/후방 카메라가 복수일 것을 가정한 카마레 리스트 지원


전원 관리

Android 9에서 기기 전원 관리 개선을 위한 새로운 기능이 도입되며 다음의 두가지 범주로 구분됨.

  • 앱 대기 버킷 : 사용 패턴에 따른 앱의 기기 리소스 액세스 제한. Android 9의 새 기능.
  • 배터리 세이버 개선 : 활성화시 시스템이 모든 앱에 제한 적용. Android 9에서 개선된 기존 기능.

앱 대기 버킷

새로운 배터리 관리 기능.

최근에 사용 빈도에 따라 앱의 리소스 요청에 우선순위를 부여하고 사용에 제한을 부여함.

  • Active : 현재 사용 중인 앱. 시스템은 앱의 작업, 알람 또는 FCM 메시지에 어떤 제한도 적용하지 않음.
    • 앱이 액티비티를 시작함.
    • 앱이 포그라운드 서비스를 실행 중.
    • 앱에 포그라운드 앱이 사용하는 콘텐츠 프로바이더와 동기화 어댑터가 있음.
    • 사용자가 앱에서 알림을 클릭함.
  • Working Set : 앱이 자주 실행되지만 현재는 활성이 아닌 앱. 작업을 실행하고 알람을 트리거 하는 기능에 가벼운 제한을 적용함.
    • 사용자가 거의 매일 실행하는 소셜 미디어 앱은 Working Set일 가능성이 높음.
    • 앱이 간접적으로 사용될 경우에도 Working Set으로 승격됨.
  • Rare : 자주 사용되지 않는 앱. 작업을 실행하고 알람을 트리거하고 우선순위가 높은 FCM 메시지를 수신하는 앱의 기능에 엄격한 제한을 적용함. 앱의 인터넷 연결 기능도 제한함.
    • 사용자가 특정 호텔에 머무는 동안에만 실행되는 호텔 앱은 Rare 버킷에 있을 수 있음.
  • Never : 설치되었지만 한번도 실행되지 않음 앱. 매우 엄격한 제한을 적용함.

시스템은 각 앱이 얼마나 자주 사용될지 판별하기 위해 머신러닝을 사용하는 사전 로드된 앱을 사용할 수도 있음.

아닌 경우 최근 사용되었는지에 따라 앱을 정렬함.

버킷은 아래 것들을 판별함.

  • 앱 작업이 얼마나 자주 실행되는지
  • 앱이 얼마나 자주 알람을 트리거 하는지
  • 우선순위가 높은 FCM 메시지를 얼마나 자주 수신할 수 있는지

이러한 제한은 기기가 배터리 전원 사용 중인 경우만 적용되며, 충전 중일 때는 제한을 적용하지 않음.

각 제조사가 버킷에 할당되는 방식에 대해 자체적인 기준을 설정할 수도 있음.

앱에서 UsageStateManager.getAppStandbyBucket()을 호출하여 현재 어떤 버킷인지 확인 가능함.

Doze모드 허용 목록에 있는 앱은 버킷 기반의 제한을 받지 않음.

모범사례
  • 앱을 특정 버킷에 넣기 위해 시스템 조작을 시도하지 말 것.

  • 앱에 시작 액티비티가 없는 경우 앱이 Active 버킷 승격되지 않을 수 있음.

  • 앱의 알림이 실행되지 않을 경우 사용자가 알림과의 상호작용을 통해 Active 버킷으로 앱 승격을 트리거할 수 없음.

  • 우선순위가 높은 FCM 메시지 수신시 앱이 알림을 표시하지 않는다면 사용자가 앱과 상호작용하여 앱을 Active 버킷으로 승격시킬 기회가 부여되지 않음.

    참고 : 사용자가 반복해서 알림을 해제하는 경우 시스템은 향후에 알림을 차단하는 옵션을 사용자에게 제공함.

  • 앱이 여러 패키지에 분할된 경우 이들 패키지가 다른 버킷에 잇을 수 있으며, 그 결과 액세스 레벨이 달라질 수 있음.

배터리 세이버 개선

Android 9에서 배터리 세이버 모드가 개선되었으며, 제조사가 적용되는 정확한 제한사항을 결정함.

AOSP 빌드에서 시스템은 아래 제한을 적용함.

  • 시스템은 유휴 상태가 되기를 기다리는 대신 적극적으로 앱을 대기모드에 둠.
  • 백그라운드 실행 제한은 대사 API 레벨 상관없이 모든 앱에 적용됨.
  • 화면이 꺼지면 위치 서비스가 비활성화될 수도 있음.
  • 백그라운드 앱에는 네트워크 액세스 권한이 없음.

테스트

ADB를 사용하여 여러가지 전원 관리 기능을 테스트할 수 있음.

Doze 모드 전환 등은 링크 참조 : https://developer.android.com/training/monitoring-device-state/doze-standby

앱 대기 버킷
  • 앱의 버킷 변경시

    $ adb shell am set-standby-bucket [packagename] active|working_set|frequent|rare
  • 여러 패키지 동시 설정시

    $ adb shell am set-standby-bucket package1 bucket1 package2 bucket2...
  • 앱이 어떤 버킷에 있는지 확인

    $ adb shell am get-standby-bucket [packagename]

    [packagename] 파라미터를 전달하지 않을 경우 모든 앱의 버킷을 나열함. 런타임에서는 UsageStatsManager.getAppStandbyBucket()을 호출하여 찾을 수 있음.

배터리 세이버

저전력 조건하에서 앱 동작 테스트를 위한 명령들

참고 : 기기의 Settings > Battery saver 화면을 사용하여 기기를 배터리 세이버 모드로 전환 가능함.

  • 기기의 플러그를 뽑고 시뮬레이션할 경우

    $ adb shell dumpsys battery unplug
  • 저전력 조건 하에서 기기 테스트

    $ adb shell settings put global low_power 1
  • 테스트 종료 후, 수동 기기 설정 실행취소시

    $ adb shell dumpsys battery reset

개인정보 보호정책 변경사항

백그라운드 앱의 기기 센서 액세스를 제한.

Wi-Fi 스캔으로 검색되는 정보를 제한.

전화동화/상태, Wi-Fi 스캔과 관련하여 새로운 권한 규칙 과 권한 그룹을 적용

백그라운드에서 센서 액세스 제한

  • 앱이 마이크나 카메라 액세스 금지
  • 연속 보고 모드를 사용하는 센서(가속도계 및 자이로스코프 등)는 이벤트 수신하지 않음.
  • 변경시 또는 원샷 보고 모드를 사용하는 센서는 이벤트를 수신하지 않음.

Android 9이 실행되는 기기에서 앱이 센서 이벤트를 감지해야하는 경우 포그라운드 서비스 사용해야 함.

통화 로그 액세스 제한

CALL_LOG 권한 그룹 도입.

READ_CALL_LOGWRITE_CALL_LOGPROCESS_OUTGOING_CALLS 권한이 이동함. (기존엔 PHONE 권한 그룹)

앱에서 통화 로그 액세스나 발신 통화 처리시 CALL_LOG 권한 그룹으로부터 명시적으로 권한 요청을 해야함.

그렇지 않으면 SecurityException 발생함.

참고 : 이런 권한은 런타임에 부여되므로 사용자가 앱에서 액세스 못하도록 거부할 수 있으므로 적절히 처리해야 함.

전화번호 액세스 제한

수신 및 발신 통화와 관련된 전화번호 READ_CALL_LOG 권한이 있어야 함.

  • PHONE_STATE 인텐트 액션에서 전화번호를 읽으려면 READ_CALL_LOGREAD_PHONE_STATE 권한 모두 필요함.
  • onCallStateChanged()에서 전화번호를 읽으려면 READ_CALL_LOG 권한만 필요함.

Wi-Fi 위치 및 연결 정보 액세스 제한

Android 9 은 이전보다 앱이 Wi-Fi 스캔하는데 필요한 권한 요구사항이 엄격해짐.

제한이 getConnectionInfo() 메서드에도 적용되며 이 메서드는 현재 Wi-Fi 위치를 설명하는 WifiInfo객체를 반환함.

앱에 아래 권한이 있을 경우 이 객체의 메서드만 사용하여 SSID 및 BSSID 값을 검색할 수 있음.

  • ACCESS_FINE_LOCATION 또는 ACCESS_COARSE_LOCATION
  • ACCESS_WIFI_STATE

Wi-Fi 서비스 메서드에서 정보 삭제

다음 이벤트와 브로드캐스트는 사용자 위치나 개인 식별 데이터와 관련된 정보를 수신하지 않음.

  • WifiManager의 getScanResults()와 getConnectionInfo() 메서드
  • WifiP2pManager의 discoverServices()와 addServiceRequest() 메서드
  • NETWORK_STATE_CHANGED_ACTION 브로드캐스트

NETWORK_STATE_CHANGED_ACTION 시스템 브로드캐스트에는 SSID(EXTRA_SSID), BSSID(EXTRA_BSSID) 또는 연결정보(EXTRA_NETWORK_INFO)가 포함되지 않음.

위 정보가 필요할 경우 getConnectionInfo() 호출.

기기 위치 설정에 따라 전화정보 제공

기기 위치를 비활성화 했다면, 아래 메서드는 결과를 제공하지 않음.

  • getAllCellInfo()
  • listen()
  • getCellLocation()
  • getNeighboringCellInfo()

비 SDK 인터페이스 사용에 대한 제한

플랫폼에서는 일부 비 SDK 메서드와 필드의 사용을 제한함.

리플레션을 통한 직접 액세스를 시도하든 아니면 JNI를 사용하든 간에 모두 적용됨.

보안 동작 변경사항

기기 보안 변경사항

#####TLS 구현 변경사항

  • SSLSocket의 인스턴스가 생성되는 동안 연결에 실패할 경우, 시스템에서 NullPointerException 대신 IOException 발생
  • 어떤 close_notify 경고가 발생하더라도 SSLEngine 클래스가 깔끔하게 처리함.

#####더욱 엄격해진 SECCOMP 필터

Android 8.0(API 26)에 포함된 SECCOMP 필터의 확장 프로그램. 권한을 가진 syscall을 사용하는 앱에만 영향.

암호화 변경사항

#####매개 변수 및 알고리즘의 Conscrypt 구현

Android 9은 Conscrypt 에서 알고리즘 매개변수의 추가적인 구현을 제공함.

매개변수에는 AES, DESEDE, OAEP, EC가 포함됨.

위 매개변수의 Bouncy Castle 버전과 다수의 알고리즘이 Android 9에서 지원이 중단됨.

참고 : Conscrypt의 EC 매개변수 구현에서는 명명된 곡선만 지원함.

Android 8.1(API 27) 이하를 대상으로 하는 앱의 경우, 지원 중단된 알고리즘 중 하나인 Bouncy Castle 구현을 요청한다면 Android 9에서는 NoSuchAlgorithmException을 발생함.

기타 변경사항
  • PBE 키를 사용하는 경우, Bouncy Castle이 초기화 벡터(IV)를 예상하는데 앱이 이것을 제공하지 않으면 경고 표시됨.
  • Conscrypt의 ARC4 암호화 구현에서는 ARC4/ECB/NoPadding 또는 ARC4/NONE/NoPadding을 지정할 수 있음.
  • Crypto JCA(Java Cryptography Architecture) 제공자는 제거됨. SecureRandom.getInstance("SHA1PRNG", "Crypto") 를 호출하면 NoSuchProviderException이 발생함.
  • 앱이 키 구조보다 더 큰 버퍼로부터 RSA 키를 파싱하는 경우, 더 이상 예외 발생하지 않음.

Android 보안 암호화된 파일은 지원되지 않음

Android 9에서는 Android 보안 암호화 파일(ASEC)에 대한 지원이 완전히 제거됨.

Android 2.2(API 8)에서 Android는 SD 카드의 앱 기능을 지원하기 위해 ASEC 도입.

Android 6.0(API 23)에서 플랫폼은 개발자가 ASEC 대신 사용할 수 있는 어댑터블 스토리지 기기 기술을 도입함.

ICU 라이브러리에 대한 업데이트

Android 9는 ICU 라이브러리 버전 60을 사용함. Android 8.0(API 26), Android 8.1(API 27)은 ICU 58 사용.

ICU는 android.icu package 아래에 공개 API를 제공하는데 사용하고 Android 플랫폼 국제화 지원에 사용함.

ex) java.utiljava.textandroid.text.format 에서 Android 클래스 구현시 사용됨.

ICU 60 업데이트에는 Emoji 5.0 데이터 지원 및 개선된 날짜/시간 형식등의 변경사항이 다수 포함됨.

  • 플랫폼 시간대 처리 방식 변경
    • GMT 및 UTC 처리로 둘은 더이상 동의어가 아님. "GMT", "Etc/GMT", "UTC", "Etc/UTC", "Zulu" 같은 시간대의 서식 및 파싱엥 영향
    • java.text.SimpleDateFormat에서 ICU 사용하여 UTC/GMT 표시 이름 제공 zzzz 파싱시 "Universal Coordinated Time", "Greenwich Mean Time" 과 같은 문자열 인식함.
    • java.text.DateFormatSymbols.getZoneStrings() 동작이 변경됨.
    • 아시아/하노이 시간대 인식 안됨. java.util.TimeZones.getAvailabeIds()는 값을 반환하지 않으며, java.util.TimeZone.getTimeZone()은 이를 인식 못함.
  • android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String) 메서드의 경우 합법적 통화 텍스트를 파싱할 때도 ParseException 발생할 수 있음. 이 문제를 피하려면 스타일의 통화 텍스트에 NumberFormat.parseCurrency를 사용함. 이 메서드는 Android 7.0(API 24) 이후 버전에서 PLURALCURRENCYSTYLE을 사용할 수 있음.

Android 테스트 변경사항

프레임워크에서 라이브러리 제거

Android 9에서는 JUnit 기반 클래스를 android.test.baseandroid.test.runnerandroid.test.mock 세가지 라이브러리로 재 구성함.

테스트 모음 빌드 변경사함

TestSuiteBuilder 클래스의 addRequirements() 메서드가 제거되고 클래스가 지원 중단됨.

Java UTF 디코더

UTF-8은 Android 기본 문자 집합이며, UTF-8 바이트 시퀀스는 String 생성자에 의해 디코딩될 수 있음.

Android 9의 UTF-8 디코더는 이전보다 엄격하게 Unicode 표준을 준수함.

  • 비최단(non-shortest) 형식의 UTF-8(예: <C0, AF>)은 잘못된 형식으로 간주됨.
  • 대리(surrogate) 형식의 UTF-8(예: U+D800..U+DFFF)는 잘못된 형식으로 간주됨.
  • 최대 서브파트는 단일 U+FFFD로 대체. 예를 들어, 바이트 시퀀스 "41 C0 AF 41 F4 80 80 41"에서 최대 서브파트는 "C0," "AF" 및 "F4 80 80". "F4 80 80"은 "F4 80 80 80"의 초기 서브시퀀스가 될 수 있지만, "C0"은 올바른 형식의 코드 단위 시퀀스의 초기 서브시퀀스가 될 수 없으므로 출력은 "A\ufffd\ufffdA\ufffdA"여야 함.
  • 수정된 UTF-8 / CESU-8 시퀀스를 Android 9 이상에서 디코딩하려면 DataInputStream.readUTF() 메서드나 NewStringUTF() JNI 메서드를 사용.

인증서를 사용하여 호스트 이름 확인

호스트 이름을 확인하기 위해 서버는 일치하는 SAN이 포함된 인증서를 제공해야 함. (CN을 사용한 대체 불가)

호스트 이름과 일치하지 않는 SAN이 포함된 인증서는 더 이상 신뢰할 수 없음.

네트워크 주소 조회시 네트워크 위반 발생 가능

이름 확인을 요구하는 네트워크 주소 조회에는 네트워크 I/O가 포함될 수 있으며 이 조회는 차단 작업으로 간주됨.

메인 스레드의 차단 작업은 일시 중지나 버벅거림 현상을 유발할 수 있음.

StrictMode 클래스는 개발자가 코드에서 문제를 감지하도록 돕는 개발도구.

Android 9 이상에서 StrictMode는 이름 확인을 요구하는 네트워크 주소 조회로부터 발생하는 네트워크 위반을 감지함.

StrictMode를 활성화한 상태로 앱을 출시하면 안됨.

숫자 IP 주소 확인은 차단 작업으로 간주되지 않음.

소켓 태그 지정

기존 Android에서는 setThreadStatsTag()메서드를 사용하여 소켓에 태그를 다는 경우 바인더 IPC를 ParcelFileDescriptor컨테이너와 함께 사용하여 또 다른 프로세스로 전송시 이 소켓의 태그가 해제됨.

Android 9 이상에서는 바인더 IPC 사용하여 또 다른 프로세스로 전송시 소켓 태그가 유지됨.

이러한 변경은 네트워크 트랙픽 통계에 영향을 미칠 수 있음. (queryDetailsforUidTag() 메서드 사용시)

다른 프로세스로 전송한 소켓의 태그를 제거하고 싶다면 untagSocket()을 호출.

소켓에서 사용 가능한 바이트 크기가 보고됨

shutdownInput() 메서드를 호출한 다음 available() 메서드를 호출하면 0이 반환됨.

xt_qtaguid 폴더의 파일을 더 이상 앱에 사용 불가함

Android 9부터는 앱에서 /porc/net/xt_qtaguid 폴더에 있는 파일을 직접 읽을 수 없음.

이러한 파일을 사용하는 공개 API는 계속 작동함. (TrafficStatsNetworkStatsManager 등)

qtaguid_tagSocket() 같은 지원되지 않는 cutils 함수는 작동하지 않을 수 있음.

FLAG_ACTIVITY_NEW_TASK 요구사항 적용됨.

Android 9에서는 인텐트 플래그 FLAG_ACTIVITY_NEW_TASK를 전달하지 않을 경우 비 액티비티 컨텍스트에서 액티비티를 시작할 수 없음.

이 플래그를 전달하지 않고 액티비티를 시작하려고 하면 액티비티가 시작되지 않고, 시스템이 로그 출력함.

참고 : Android 7.0(API 24) 이전 버전부터 적용되었으나 Android 7.0 버그로 인해 적용되지 않았음.

화면 회전 변경사항

Android 9 부터 세로 회전모드가 회전 잠금으로 변경되었고 이 모드는 자동 회전이 꺼진 경우 활성화됨.

기존에는 자동 회전 및 세로 회전 모드 였으며, 자동 회전 모드에는 변화 없음.

특정 방향을 요청하는 Activity(screenOrientation=landscape같은) 는 사용자 잠금 기본설정을 무시하고 동작됨.

화면 방향동작
unspecified, user자동 회전 및 회전 잠금 모드에서 Activity가 세로 모드 또는 가로 모드(및 반전)로 렌더링될 수 있습니다. 세로 모드 및 가로 모드 레이아웃을 모두 지원할 것으로 예상됩니다.
userLandscape자동 회전 및 회전 잠금 모드에서 Activity가 가로 모드 또는 반전 가로 모드로 렌더링될 수 있습니다. 가로 모드 레이아웃만을 지원할 것으로 예상됩니다.
userPortrait자동 회전 및 회전 잠금 모드에서 Activity가 세로 모드 또는 반전 세로 모드로 렌더링될 수 있습니다. 세로 모드 레이아웃만을 지원할 것으로 예상됩니다.
fullUser자동 회전 및 회전 잠금 모드에서 Activity가 세로 모드 또는 가로 모드(및 반전)로 렌더링될 수 있습니다. 세로 모드 및 가로 모드 레이아웃을 모두 지원할 것으로 예상됩니다. 회전 잠금 모드 사용자에게는 반전 세로 모드(대개 180º 반전)로 잠글 수 있는 옵션이 제공됩니다.
sensor, fullSensor, sensorPortrait, sensorLandscape회전 잠금 모드 기본 설정이 무시되고 자동 회전이 활성화된 것처럼 처리됩니다. 이 동작은 UX를 매우 신중하게 고려하여 예외적인 경우에만 사용해야 합니다.

Apache HTTP 클라이언트 지원 중단은 비표준 ClassLoader가 있는 앱에 영향을 미침

Android 6.0에서 Apache HTTP 클라이언트에 대한 지원이 제거됨.

비표준 ClassLoader를 사용하여 org.apache.http.* 에서 클래스를 찾을 때 앱 ClassLoader에 권한을 위임해야 함.

이 경우 Android 9 이상에서는 NoClassDefFoundError 가 발생함.

카메라 나열

getCameraIdList()를 호출하면 모든 이용 가능한 카메라를 찾아낼 수 있음.

기기에 후방/전방 카메라 하나만 있는 것으로 가정하지 말아야 함. 각 카메라가 2개 이상일 수 있음.