안드로이드 OS가 6.0으로 업그레이드 되면서 새로 선보인 절전 기능으로 Doze와 App standby가 있다. 이 게시물에서는 Doze만을 다룬다. Doze는 디바이스 사용이 오랫동안 되지 않는경우 네트워크와 백그라운드 작업을 미룸으로써 배터리 사용량을 줄이는 기능이다.
Doze 이해하기
스마트폰이 아래와 같은 상황에 놓였을때, Doze 모드에 진입할 수 있다. 이 조건 중 1개라도 깨지면 Doze 모드는 풀려나게 된다.
- 배터리가 충전되지 않고
- 휴대폰이 물리적으로 제자리에 계속 놓여진 상태이며
- 스크린 오프 상태로 오랫동안 방치 되었을 경우
Doze 모드에 빠지게 되면 아래와 같이 동작하게 된다.
- Doze 모드에 빠지게 되면 배터리를 아끼고자 앱의 네트워크와 CPU 사용을 제한하게 된다. 이 상황에선 SyncAdapter, JobScheduler, AlarmManager가 작동하지 않게 된다.
- 비록 Doze 모드에 들어가 있더라도, 시스템이 주기적으로 Doze에서 빠져나와 미뤄둔 작업을 한 뒤에 다시 Doze로 들어가게 된다. 이 상태를 Maintenance라 하며 SyncAdapter, JobScheduler, AlarmManager가 미뤄졌던 것이 이 때 다시 작동이 된다.
- WakeLock이 무시된다. 즉 스스로 깨어날 수가 없다.
- Wi-Fi 스캔을 하지 않는다.
즉 배터리를 아끼기 위해 죽은듯이 그냥 재워버리는 것이 Doze모드라 할 수 있다.
Doze에 적응하기
- AlarmManager를 쓰려는 경우, API Level 23에 추가된 setAndAllowWhileIdle 혹은 setExactAndAllowWhileIdle을 사용해 볼 수 있다. 두 메서드의 차이는 알람이 트리거되는 시점이 약간 부정확하냐/정확하냐의 차이로 배터리 성능은 그에 반비례한다 생각하면 된다. 이 메서드는 Doze에서도 알람을 돌릴 수 있게 해주며 System의 임시 화이트리스트에 앱을 등록하여 약 10초간은 WakeLock을 할 수 있도록 허용해준다.
- 위의 알람 메서드를 사용하는 경우 최소 주기시간이 존재한다. 비 Doze 모드에선 1분, Doze 모드에선 최소 15분이 지나야 알람이 동작한다.
- Doze에서도 지속적인 네트워크 유지를 위해선 GCM을 사용해서 메시지 수신을 해야 한다. 유일하게 시스템에서 네트워크 유지목적으로 쓸 수 있게 허용되어 있다. priority를 high로 주면 메시지를 실시간으로 수신하는 것이 가능하다.
- 도저히 GCM을 쓸 상황이 못되지만 네트워크는 어쨌든 지속적으로 유지 해야겠다면, 사용자에게 배터리 절약 모드를 무시하게 할 수 있는 dialog를 띄워줘야 한다. 앱이 직접 끄진 못하고 사용자에게 허락을 받아야 한다.
Doze 모드 테스트
폰이 Doze 모드에 빠질때까지 가만히 놔두면 된다.
adb를 이용해서 강제로 Doze 모드에 진입시킬 수 있다.
폰을 PC에 연결하고 디버그 모드를 켠 상태에서 스크린을 off 시킨 뒤 터미널에서 아래에 나와있는 커맨드를 입력한다.
$ adb shell dumpsys battery unplug $ adb shell dumpsys deviceidle step
2라인의 step을 계속 반복하다보면 step이 바뀌면서 결국 IDLE상태에 빠지게 되는데 이 때가 Doze 모드에 진입 한 상황이다. 이 상태에서 테스트를 시작하면 된다.