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.
-
Please check [this answer](http://stackoverflow.com/a/35914341/2826147). – Amit Vaghela Mar 10 '16 at 10:52
5 Answers
Based on some testing, using a Nexus 5 with the the final(?) preview of Android 6.0 installed:
Holding a
PARTIAL_WAKE_LOCK
is insufficient to block Doze mode — the device will still doze, even though you have theWakeLock
and 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).

- 986,068
- 189
- 2,389
- 2,491
-
3Wow, so an app that run in background with screen off doesn't work anymore :( Thanks for your response. – greywolf82 Aug 30 '15 at 07:00
-
16
-
At this point I can't understand the methods AndAllowWhileIdle(). If the wakelock are ignored how can I process data in that situation? In the middle of processing the CPU can sleep :( am I missing anything? – greywolf82 Aug 30 '15 at 12:43
-
@greywolf82: The `...AndAllowWhileIdle()` methods affect app standby, not Doze mode. I have not attempted to model app standby and so I do not know the characteristics of the environment when you get control, including with respect to `WakeLocks`. Doze mode worries me more, as neither developers nor users have any control (other than users always having a charger lying around). With app standby, the user can whitelist the app to not go into that state. – CommonsWare Aug 30 '15 at 13:04
-
1@CommonsWare: Actually I just discovered that ...AndAllowWhileIdle() DOES affect Doze mode. It fires about every 15 minutes when idle. What I discovered with this, is that in Doze mode many functions seem to be blocked, this applies to GPS (my test) and obviously to storage access. Your log did not show the firing of ...AndAllowWhileIdle(), because you wrote to file - my tests worked with a database and that showed it. As with GPS, it just didn't work when idle, although the surrounding wakelock did - it's been blocked somehow just as your storage access. My guess. – sec_aw Sep 04 '15 at 14:41
-
@sec_aw: "Your log did not show the firing of ...AndAllowWhileIdle(), because you wrote to file - my tests worked with a database and that showed it" -- a database is a file. That being said, I'll try some other tests. – CommonsWare Sep 04 '15 at 15:19
-
@sec_aw: I cannot reproduce your findings. I recommend that you publish the source code to an app that we can use to try to reproduce your results. – CommonsWare Sep 10 '15 at 13:28
-
@CommonsWare: Unfortunately I cannot provide source code to the testing app, as it is an app I'm currently working on that I temporarily modified to test Doze mode behavior. See the actual logs and testing details in my answer. – sec_aw Sep 11 '15 at 11:13
-
https://developer.android.com/reference/android/os/PowerManager.html#FULL_WAKE_LOCK FULL_WAKE_LOCK is deprecated in 17. If any 'activity' wants to keep the screen on, they should use the flag FLAG_KEEP_SCREEN_ON for the same. – Rajat Sharma Mar 17 '17 at 06:44
-
I find that as of the June 5 2017 security patch _none_ of these approaches work. Not even `android:keepScreenOn` which does keep the screen on but still permits doze to power down the wifi. – aroth Jun 20 '17 at 14:09
-
@aroth: As I [commented on your original question on this topic](https://stackoverflow.com/questions/44593369/do-the-latest-android-updates-disable-the-battery-optimization-whitelist#comment76176209_44593369), a reproducible test case would be useful. – CommonsWare Jun 20 '17 at 14:18
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.

- 1,594
- 1
- 15
- 26
-
See the doc https://developer.android.com/training/monitoring-device-state/doze-standby.html#restrictions about `setAlarmClock()` vs. Doze mode, and sections future down the page about how whitelisted apps can still use partial wake locks. The JavaDocs don't mention this. – Jerry101 Oct 20 '15 at 18:49
-
3Well yes: "the system exits Doze shortly before those alarms fire", if *shortly* means 60 minutes :-). The documentation of Doze mode is just extremely bad, much behavior is actually not documented at all, e.g. foreground services going into Doze (http://stackoverflow.com/a/33077301/4301846), hardware features like GPS not available in Doze (http://stackoverflow.com/a/32521940/4301846), who knows what else. For quite a complex behavior, that is impacting many use cases, this is pretty incredible. – sec_aw Oct 21 '15 at 08:42
-
@sec_aw, setAlarmClock() seems definite method to make our good-behaving-alarmmanager-aware apps. But when most of alarmmanger-aware apps, including bad behaving ones start using setAlarmClock(), upgrading API to level 21 or higher, then Google's (insane) attempt made in Android 6.0 will be totally useless. I really welcome setAlarmClock() is a workaround, but can't understand Google's intention. – Tomcat Nov 04 '15 at 08:22
-
Hell yeah, really, I also don´t understand the attempt of Google on that changes. Also network connections are not working anymore and that is a really bad thing for a chat app. If only using GCM is guaranteed to be working without restrictions, than this is an apple-like-behaviour. And if it is possible to break the doze mode or app standby with `setExactAndAllowWhileIdle()` ....then this all makes no sense and is a not neccessary struggle for developers..... – Opiatefuchs May 19 '16 at 06:36
-
1.android package have access to this type of wake lock `static final int DOZE_WAKE_LOCK = 0x00000040;` only internal package can use this wake lock, it requires this permission `*Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.`.. this is how the alarm app works and why he wakes the device like a charm .... feeling disappointed with android api platform – Arthur Melo May 30 '18 at 14:04
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.

- 1,594
- 1
- 15
- 26
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.

- 502
- 4
- 8
- 17
What I found in Android 13 (On a Google Pixel 7 Pro) is that setExactAndAllowWhileIdle()
actually works, provided the user manually disables the battery optimizations for the app. This is done in the app's battery usage setting, as described here.
I couldn't figure out how to do this in Android 10 on a Huawei P20 Pro, but I didn't try too hard.
So my suggestion is to first experiment with a number of phones to get a better understanding of how things work on various Android versions and phone networks.
Then change your app to check the setting and tell the user if a change is needed, offering to open the app's settings. (Keep in mind that you don't usually know how the phone manufacturer or the network customized the phone, so the instructions might not match reality if they are too detailed.)
Also, in your app, check if your function is called late, and if so, tell the user to contact you to troubleshoot it.
I don't think the battery usage setting can be changed programmatically. I wasn't even able to open the corresponding setting UI (even after adding what I thought would be the necessary permission), but only the generic settings page, and the user can navigate from there. So:
// Check doze setting
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean ignoring = pm.isIgnoringBatteryOptimizations(getPackageName());
// Show the app's setting window
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);

- 97
- 1
- 10