IT_Programming/Android_Java

[펌] 안드로이드 Doze / Stand By 모드 정리

JJun ™ 2016. 1. 21. 13:58



 출처: http://blog.yatopark.net/doze-mode-이해하기/


 참고할만한 자료
 : http://www.slideshare.net/chansukyang/60-53873120

 : http://googledevkr.blogspot.kr/2015/10/gcmonandroid-doze.html
 : http://googledevkr.blogspot.kr/2015/08/testyourapponandroid60.html

 : http://developer.android.com/intl/ko/training/monitoring-device-state/doze-standby.html

 : http://blog.hellworld.me/1




안드로이드 OS가 6.0으로 업그레이드 되면서 새로 선보인 절전 기능으로 Doze와 App standby가 있다. 
이 게시물에서는 Doze만을 다룬다. Doze는 디바이스 사용이 오랫 동안 되지 않는 경우
네트워크와 백그라운드 작업을 미룸으로써 배터리 사용량을 줄이는 기능이다.

Doze 이해하기

스마트폰이 아래와 같은 상황에 놓였을때,  Doze 모드에 진입할 수 있다.
이 조건 중 1개라도 깨지면 Doze 모드는 풀려나게 된다.

  1. 배터리가 충전되지 않고
  2. 휴대폰이 물리적으로 제자리에 계속 놓여진 상태이며
  3. 스크린 오프 상태로 오랫동안 방치 되었을 경우


Doze 모드에 빠지게 되면 아래와 같이 동작하게 된다.

  1. Doze 모드에 빠지게 되면 배터리를 아끼고자 앱의 네트워크와 CPU 사용을 제한하게 된다.
    이 상황에선 SyncAdapter, JobScheduler, AlarmManager가 작동하지 않게 된다.
  2. 비록 Doze 모드에 들어가 있더라도, 시스템이 주기적으로 Doze에서 빠져나와 미뤄둔 작업을 한 뒤에 다시 Doze로 들어가게 된다.
    이 상태를 Maintenance라 하며 SyncAdapter, JobScheduler, AlarmManager가 미뤄졌던 것이 이 때 다시 작동이 된다.
  3. WakeLock이 무시된다. 즉 스스로 깨어날 수가 없다.
  4. Wi-Fi 스캔을 하지 않는다.

즉 배터리를 아끼기 위해 죽은듯이 그냥 재워버리는 것이 Doze모드라 할 수 있다.


Doze에 적응하기

  1. AlarmManager를 쓰려는 경우,  API Level 23에 추가된 setAndAllowWhileIdle 혹은 setExactAndAllowWhileIdle을 사용해 볼 수 있다.
    두 메서드의 차이는 알람이 트리거되는 시점이 약간 부정확하냐/정확하냐의 차이로 배터리 성능은 그에 반비례한다 생각하면 된다.
    이 메서드는 Doze에서도 알람을 돌릴 수 있게 해주며 System의 임시 화이트리스트에 앱을 등록하여
    약 10초간은 WakeLock을 할 수 있도록 허용해준다.

  2. 위의 알람 메서드를 사용하는 경우 최소 주기시간이 존재한다.
    비 Doze 모드에선 1분, Doze 모드에선 최소 15분이 지나야 알람이 동작한다.

  3. Doze에서도 지속적인 네트워크 유지를 위해선 GCM을 사용해서 메시지 수신을 해야 한다.
    유일하게 시스템에서 네트워크 유지목적으로 쓸 수 있게 허용되어 있다.
    priority를 high로 주면 메시지를 실시간으로 수신하는 것이 가능하다.

  4. 도저히 GCM을 쓸 상황이 못되지만 네트워크는 어쨌든 지속적으로 유지 해야겠다면,
    사용자에게 배터리 절약 모드를 무시하게 할 수 있는
     dialog(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
    띄워줘야 한다. 앱이 직접 끄진 못하고 사용자에게 허락을 받아야 한다.
    // It is not possible to disable battery optimizations (=whitelist application for doze mode) 
    // without user interaction on Android M preview 3.
    Intent intent = new Intent();
    String packageName = context.getPackageName();
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    if (pm.isIgnoringBatteryOptimizations(packageName))
        intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
    else {
        intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
        intent.setData(Uri.parse("package:" + packageName));
    }
    context.startActivity(intent);


Doze 모드 테스트

폰이 Doze 모드에 빠질때까지 가만히 놔두면 된다.

adb를 이용해서 강제로 Doze 모드에 진입시킬 수 있다.
- Testing your app with Doze
Testing your app with App Standby

폰을 PC에 연결하고 디버그 모드를 켠 상태에서 스크린을 off 시킨 뒤 터미널에서 아래에 나와있는 커맨드를 입력한다.

sh
2 Lines
1
2
$ adb shell dumpsys battery unplug
$ adb shell dumpsys deviceidle step

2라인의 step을 계속 반복하다보면 step이 바뀌면서 결국 IDLE상태에 빠지게 되는데 이 때가 Doze 모드에 진입 한 상황이다.
이 상태에서 테스트를 시작하면 된다.




[상세 테스트 방법]



1. 다음 명령어를 통해 배터리가 충전되지 않도록 변경 합니다.

  • $ adb shell dumpsys battery unplug
2. 디바이스 스크린을 끕니다.
3. 다음 명령어를 반복 실행 하여, 디바이스 상태가 idle이 되도록 합니다.

  • $ adb shell dumpsys deviceidle step
4. 화면을 켜거나, 디바이스를 크게 움직이면 Doze 모드에서 빠져나옵니다.
5. 다음 명령어를 통해 배터리 충전 상태를 원래되로 되돌릴 수 있습니다.
  • $ adb shell dumpsys battery reset
6. 다음 명령을 통해, 현재 디바이스의 상태를 확인 할 수 있습니다.
  • $ adb shell dumpsys deviceidle








어떻게 하면 Doze 모드에서 탈출할 수 있는가?

  

 1) 스크린을 킨다.

 2) 핸드폰을 흔든다.

 3) 충전기를 꼽는다.

 4) GCM을 받는다.

 5) 화이트 리스트에 등록한다.


 (위 방법들 중, 1, 2, 3은 핸드폰을 건드려야 하는 부분이고 5는 구글신 및 제조사에서 기록하는 부분)
 








App Standby


안드로이드 플랫폼이 판단할 때 사용자가 더 이상 사용하지 않는 앱은 유휴 상태 앱으로 지정 될 수 있습니다.
일정 기간 아래 이벤트 중 어느 한 가지도 발생하지 않는 앱은 유휴 상태 앱으로 지정될 수 있습니다.

  • 사용자가 명시적으로 앱을 시작합니다.
  • 엑티비티 혹은 서비스의 형태로 해당 앱이 포그라운드 프로세스에서 실행 됩니다. 혹은 다른 포그라운드 프로세스에서 동작 중인 앱이 해당 앱의 서비스나 다른 앱 구성 요소를 사용하고 있습니다.
  • 앱이 알림을 생성하였고, 사용자가 해당 알림을 잠금 화면에서 보거나 알림 트레이에서 확인합니다.
  • 설정 메뉴에서 사용자가 명시적으로 앱이 전원 최적화 옵션에서 제외 되도록 요청했습니다.
디바이스가 충전 중이 아닌 경우, 유휴 상태인 것으로 간주된 앱은 네트워크 액세스를 할 수 없고,
동기화 작업이 일시 중단됩니다. 디바이스가 충전 중일 때는 네트워크 액세스가 허용되며 보류 중이었던
작업이 실행됩니다. 디바이스가 오랜 시간 동안 유휴 상태인 경우, 유휴 앱은 하루에 한 번 정도
네트워크 액세스가 허용됩니다.

만일 여러분의 앱이 사용자 상호작용 없이 백그라운드 상에서만 동작하는 경우, 유휴 상태 앱으로
지정될 수 있습니다. 이런 경우에도 앱의 주요 동작에 문제가 없는지 테스트 할 필요가 있습니다. 
개발자 여러분은 새롭게 추가된 다음 adb 명령어를 통해 특정 앱을 StandBy 모드로 변경할 수 있습니다.

  1. $ adb shell am broadcast -a android.os.action.DISCHARGING
  2. $ adb shell am set-inactive <packageName> true
또한, 다음 명령어를 통해 현재 앱의 StandBy 모드 여부를 확인 할 수 있습니다.
  • $ adb shell am get-inactive <packageName>
마지막으로, 다음 adb 명령어를 통해 특정 앱을 다시 정상 모드로 변경할 수 있습니다.
  • $ adb shell am set-inactive <packageName> false