唤醒锁和打瞌睡模式
Wakelock and doze mode
根据 Android Marshmallow 文档,当系统处于休眠模式时,任何唤醒锁都会被忽略。但是,我不清楚唤醒锁是否会阻止打瞌睡模式。
根据一些测试,使用安装了 Android 6.0 的最终(?)预览版的 Nexus 5:
按住 PARTIAL_WAKE_LOCK
不足以阻止打瞌睡模式 — 即使您有 WakeLock
并且正在尝试进行常规工作(例如, setExactAndAllowWhileIdle()
每分钟获得一次控制)
使用android:keepScreenOn
(或等效的Java)保持屏幕打开,在屏幕打开的情况下,足以阻止打瞌睡模式
使用 android:keepScreenOn
(或 Java 等价物)保持屏幕打开,屏幕关闭(用户按下电源按钮),不足以阻止打瞌睡模式
IOW、视频播放器等在用户观看视频时不应受到影响,即使播放器可能没有移动或充电。但是,如果用户按下 POWER 按钮,您又会面临打瞌睡的风险。
我还没有尝试使用 FULL_WAKE_LOCK
(我希望行为与 android:keepScreenOn
相同,但我不确定)。
针对上面的评论讨论,这不是问题的答案。
它旨在阐明应用程序在打瞌睡模式下的一般行为。
在我的测试应用程序中,我尝试每 2 分钟获取一次 GPS 位置,GPS 信号强度始终足够。
测试条件:
- Nexus 9,Android M 预览,构建 MPA44I
- "ignore optimizations"开
- setExactAndAllowWhileIdle() 间隔 2 分钟
- 每个操作都有 1 分钟的超时时间来获取 GPS 定位并且被部分唤醒锁包围
- 日志已写入 SQLiteOpenHelper.getWritableDatabase()
打瞌睡模式的 GPS 测试日志:
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)
现在我再次查看我的日志,我注意到一个非常奇怪的行为:
"ignore optimizations" OFF 的相同测试显示出基本相同的结果(就像它应该的那样),但大多数时候超时没有按预期工作,我得到 'active millis' 在 ~330000 范围内(~5 timeout time) 甚至 ~580000 (~10 timeout time) 空闲时。
我无法解释这种奇怪的行为,但它似乎表明 "ignore optimizations" 的设置对打瞌睡模式确实有一些影响。
编辑: 上面描述的 'strange' 行为只是现在 documented:只有当 "ignore optimizations" 开启时,您才可以持有部分唤醒锁处于打瞌睡空闲模式。
有趣
Google 在 Android 6.0 中自己的时钟应用程序能够完全阻止打瞌睡模式:
- 在时钟应用程序中设置闹钟时间 < 60 分钟后
- 关闭设备
- 在控制台中设置$adb shell dumpsys battery unplug
- 在控制台设置$adb shell dumpsys deviceidle step
状态保持'Stepped to: ACTIVE'
如果您设置的闹钟时间大于 60 分钟,它会正常工作(设备可能会进入空闲状态)。但是一旦警报距离 < 60 分钟,设备似乎会从打瞌睡空闲状态悄悄醒来,因为状态 returns 'ACTIVE' 再次(而不是 'IDLE_MAINTENANCE')。
我真的很想知道他们是怎么做到的!
- 编辑 -
似乎 setAlarmClock()
默认情况下有此行为。
这可能对某些用例有帮助。
据我所知,当深度打瞌睡开始时,所有唤醒锁(除了由具有当前前台服务的应用程序持有的唤醒锁外)都会被丢弃。打瞌睡的全部目的是让系统在 'relevant conditions' 设置时进入睡眠状态。所以是的,我猜他们不会太在意锁。
我对 JobScheduler 的看法是将来进行调度、后台任务等的方式。虽然从开发人员那里夺走了一些控制权,但我猜这就是框架人员对电池寿命的要求。更像是 'trigger and hope things will happen more or less on time'.
关于您的用例,JobScheduler has an onStopJob 回调以了解您的作业何时停止[出于任何原因 - 比如说 wifi 被切换] 您需要采取适当的行动,例如重新安排您的作业下次维护 window。来自文档:
One immediate repercussion is that the system will cease holding a wakelock for you.
根据 Android Marshmallow 文档,当系统处于休眠模式时,任何唤醒锁都会被忽略。但是,我不清楚唤醒锁是否会阻止打瞌睡模式。
根据一些测试,使用安装了 Android 6.0 的最终(?)预览版的 Nexus 5:
按住
PARTIAL_WAKE_LOCK
不足以阻止打瞌睡模式 — 即使您有WakeLock
并且正在尝试进行常规工作(例如,setExactAndAllowWhileIdle()
每分钟获得一次控制)使用
android:keepScreenOn
(或等效的Java)保持屏幕打开,在屏幕打开的情况下,足以阻止打瞌睡模式使用
android:keepScreenOn
(或 Java 等价物)保持屏幕打开,屏幕关闭(用户按下电源按钮),不足以阻止打瞌睡模式
IOW、视频播放器等在用户观看视频时不应受到影响,即使播放器可能没有移动或充电。但是,如果用户按下 POWER 按钮,您又会面临打瞌睡的风险。
我还没有尝试使用 FULL_WAKE_LOCK
(我希望行为与 android:keepScreenOn
相同,但我不确定)。
针对上面的评论讨论,这不是问题的答案。 它旨在阐明应用程序在打瞌睡模式下的一般行为。 在我的测试应用程序中,我尝试每 2 分钟获取一次 GPS 位置,GPS 信号强度始终足够。
测试条件:
- Nexus 9,Android M 预览,构建 MPA44I
- "ignore optimizations"开
- setExactAndAllowWhileIdle() 间隔 2 分钟
- 每个操作都有 1 分钟的超时时间来获取 GPS 定位并且被部分唤醒锁包围
- 日志已写入 SQLiteOpenHelper.getWritableDatabase()
打瞌睡模式的 GPS 测试日志:
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)
现在我再次查看我的日志,我注意到一个非常奇怪的行为: "ignore optimizations" OFF 的相同测试显示出基本相同的结果(就像它应该的那样),但大多数时候超时没有按预期工作,我得到 'active millis' 在 ~330000 范围内(~5 timeout time) 甚至 ~580000 (~10 timeout time) 空闲时。 我无法解释这种奇怪的行为,但它似乎表明 "ignore optimizations" 的设置对打瞌睡模式确实有一些影响。
编辑: 上面描述的 'strange' 行为只是现在 documented:只有当 "ignore optimizations" 开启时,您才可以持有部分唤醒锁处于打瞌睡空闲模式。
有趣
Google 在 Android 6.0 中自己的时钟应用程序能够完全阻止打瞌睡模式:
- 在时钟应用程序中设置闹钟时间 < 60 分钟后
- 关闭设备
- 在控制台中设置$adb shell dumpsys battery unplug
- 在控制台设置$adb shell dumpsys deviceidle step
状态保持'Stepped to: ACTIVE'
如果您设置的闹钟时间大于 60 分钟,它会正常工作(设备可能会进入空闲状态)。但是一旦警报距离 < 60 分钟,设备似乎会从打瞌睡空闲状态悄悄醒来,因为状态 returns 'ACTIVE' 再次(而不是 'IDLE_MAINTENANCE')。
我真的很想知道他们是怎么做到的!
- 编辑 -
似乎 setAlarmClock()
默认情况下有此行为。
这可能对某些用例有帮助。
据我所知,当深度打瞌睡开始时,所有唤醒锁(除了由具有当前前台服务的应用程序持有的唤醒锁外)都会被丢弃。打瞌睡的全部目的是让系统在 'relevant conditions' 设置时进入睡眠状态。所以是的,我猜他们不会太在意锁。
我对 JobScheduler 的看法是将来进行调度、后台任务等的方式。虽然从开发人员那里夺走了一些控制权,但我猜这就是框架人员对电池寿命的要求。更像是 'trigger and hope things will happen more or less on time'.
关于您的用例,JobScheduler has an onStopJob 回调以了解您的作业何时停止[出于任何原因 - 比如说 wifi 被切换] 您需要采取适当的行动,例如重新安排您的作业下次维护 window。来自文档:
One immediate repercussion is that the system will cease holding a wakelock for you.