According to Android Marshmallow documentation when the system is in doze mode, any wakelock is ignored. However it's not clear to me if a wakelock prevent doze mode or not.
问题:
回答1:
Based on some testing, using a Nexus 5 with the the final(?) preview of Android 6.0 installed:
Holding a
PARTIAL_WAKE_LOCKis insufficient to block Doze mode ― the device will still doze, even though you have theWakeLockand are trying to do regular work (e.g.,setExactAndAllowWhileIdle()to get control every minute)Keeping the screen on using
android:keepScreenOn(or the Java equivalent), with the screen on, is sufficient to block Doze modeKeeping the screen on using
android:keepScreenOn(or the Java equivalent), with the screen off (user presses POWER button), is insufficient to block Doze mode
IOW, video players and the like should not be affected while the user is watching the video, even though the player may not be moving or charging. However, if the user presses the POWER button, you're back into having Doze risk.
I have not tried using FULL_WAKE_LOCK (I would expect behavior identical to android:keepScreenOn, but I am far from certain).
回答2:
Interesting
Google's own clock app in Android 6.0 is able to block Doze mode altogether:
- In the clock app set an alarm with a time < 60 minutes from now
- Turn off the device
- In the console set $adb shell dumpsys battery unplug
- In the console set $adb shell dumpsys deviceidle step
The state remains as 'Stepped to: ACTIVE'
If you set an alarm with a time > 60 minutes from now, it works normally (device may go into idle states). BUT once the alarm is < 60 min away it seems that the device quietly awakes from Doze idle, as the state returns 'ACTIVE' again (instead of 'IDLE_MAINTENANCE').
I really wonder how they are doing this!
- EDIT -
It seems to be setAlarmClock() that is having this behavior by default. This might be helpful for some use cases.
回答3:
In response to the comment discussion above, this is not an answer to the question. It's meant to clarify app behaviour in Doze mode in general. In my testing app, I tried to get a GPS position every 2 minutes, GPS signal strength was sufficient at all times.
Testing conditions:
- Nexus 9, Android M Preview, Build MPA44I
- "ignore optimizations" ON
- setExactAndAllowWhileIdle() with 2 minute interval
- each operation has a 1 minute timeout for getting a GPS fix and is surrounded by a partial wakelock
- logs were written to SQLiteOpenHelper.getWritableDatabase()
GPS test log for Doze mode:
1 2015-09-04 - 12:14 GPS ok (device left stationary unplugged) 2 2015-09-04 - 12:16 GPS ok 3 2015-09-04 - 12:18 GPS ok 4 2015-09-04 - 12:20 GPS ok 5 2015-09-04 - 12:22 GPS ok 6 2015-09-04 - 12:24 GPS ok 7 2015-09-04 - 12:26 GPS ok 8 2015-09-04 - 12:28 GPS ok 9 2015-09-04 - 12:30 GPS ok 10 2015-09-04 - 12:32 GPS ok 11 2015-09-04 - 12:34 GPS ok ... 31 2015-09-04 - 13:14 GPS ok 32 2015-09-04 - 13:16 GPS ok 33 2015-09-04 - 13:18 GPS ok 34 2015-09-04 - 13:20 GPS ok 35 2015-09-04 - 13:22 GPS ok 36 2015-09-04 - 13:24 GPS ok 37 2015-09-04 - 13:26 GPS ok (entering Doze mode some time after) 38 2015-09-04 - 13:42 GPS failed, active millis: 60174 (idle) 39 2015-09-04 - 13:57 GPS failed, active millis: 60128 (idle) 40 2015-09-04 - 14:12 GPS failed, active millis: 60122 (idle) 41 2015-09-04 - 14:16 GPS ok (idle maintenance) 42 2015-09-04 - 14:18 GPS ok (idle maintenance) 43 2015-09-04 - 14:20 GPS ok (idle maintenance) 44 2015-09-04 - 14:22 GPS ok (idle maintenance) 45 2015-09-04 - 14:38 GPS failed, active millis: 60143 (idle) 46 2015-09-04 - 14:53 GPS failed, active millis: 60122 (idle) 47 2015-09-04 - 15:08 GPS failed, active millis: 60068 (idle) 48 2015-09-04 - 15:23 GPS failed, active millis: 60138 (idle) 49 2015-09-04 - 15:38 GPS failed, active millis: 60140 (idle) 50 2015-09-04 - 15:53 GPS failed, active millis: 60131 (idle) 51 2015-09-04 - 16:08 GPS failed, active millis: 60185 (idle) 52 2015-09-04 - 16:12 GPS ok (ending Doze mode - power button on) Now that I looked at my logs again, I noticed a very strange behavior: The same test with "ignore optimizations" OFF showed basically identical results (like it should), BUT most of the times the timeout did not work as expected, I got 'active millis' in the range of either ~330000 (~5 times timeout time) or even ~580000 (~10 times timeout time) while idle. This weird behavior I can not explain, but it seems to show that there actually IS some effect of the setting of "ignore optimizations" on Doze mode.
Edit: The 'strange' behavior described above is just now documented: Only with "ignore optimizations" ON, you may hold a partial wakelock in Doze idle mode.
回答4:
As far as I have explored, all wake locks (except the ones held by apps with a current foreground service) are dropped when the deeper doze starts. The whole point of doze is to let the system sleep when the 'relevant conditions' set in. So yes locks is not something they would care too much about I guess.
The way I see it JobScheduler is the way to go about scheduling, background tasks etc in future. Takes some control away from developers though but that's the call I guess framework guys took for battery life. It's more like 'trigger and hope things will happen more or less on time'.
Coming to your use case, JobScheduler has an onStopJob callback to know when the execution of your job has stopped [for any reason - say wifi was toggled] you need to take appropriate action such as rescheduling your job for the next maintenance window. From the docs:
One immediate repercussion is that the system will cease holding a wakelock for you.