唤醒锁和打瞌睡模式

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 中自己的时钟应用程序能够完全阻止打瞌睡模式:

  1. 在时钟应用程序中设置闹钟时间 < 60 分钟后
  2. 关闭设备
  3. 在控制台中设置$adb shell dumpsys battery unplug
  4. 在控制台设置$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.