理解&测试Android M + Doze模式

时间:2018-02-24 10:27:24

标签: android-6.0-marshmallow android-doze

我正在努力使我的Android应用程序成为后Android M世界的好公民,这对设备进入打瞌睡时应用程序可以/不能做什么施加了严格限制。我对所涉问题的理解仍然相当零碎,所以我希望这里有人可以填补这些空白。

打瞌睡的持续时间

我自己的实证研究结果

  • 打盹首先在静止,屏幕关闭,不活动的大约半小时内开始
  • 第一个维护窗口在30分钟内发生
  • 下一个发生在大约一个小时
  • 比在大约2,4和6小时之后的那些。我没有测试过

这些是官方Android打瞌睡时期还是只是一个经验观察。

以上所有Android N设备。

在打盹模式下测试应用

  • 使用ADB将设备连接到计算机
  • 将应用程序带到前台
  • 关闭设备屏幕
  • 从命令行问题adb shell dumpsys battery unplug
  • 现在循环执行命令`adb shell dumpsys deviceidle step light or deep
  • 最后发出adb shell dumpsys battery reset

进入/退出打盹

  • 屏幕关闭且设备未移动时发生

  • 据推测,这会使用手机中的运动传感器,因此静静地坐在非常平稳行驶的火车上的手机仍会进入打瞌睡状态?

  • 如果我拿起一个打瞌睡的手机并开始四处走动而没有与之交互,它会自动退出打瞌睡吗?

  • 假设我的应用程序在其主机设备进入打盹时不在前台。然后我再次开始使用该设备,但没有访问该应用。它会自动启动"工作"再次,即

  • 它的广播接收器将会正常运行吗?

  • 它的处理程序将开始工作吗?

  • setRequiresDeviceIdle(true)的预定作业是否会停止

Doze& amp;的各种模式作业调度

  • 根据我的理解,有两种打盹模式LIGHT&深。他们都有子模式

  • LIGHT :有效,空闲,空闲_维护,覆盖。我不明白各种模式的作用。在亚行,我发布了step light屏幕并看到了返回值ACTIVE。关闭屏幕step light会返回IDLE

  • DEEP :激活,IDLE_PENDING,SENSING,LOCATING,IDLE,IDLE_MAINTENANCE,屏幕也会返回ACTIVE,但屏幕关闭后会返回IDLE_PENDING。那么当其他子模式完全正确时,IDLE,SENSING ......会发生吗?

我假设当设备从DOZE进入维护窗口并尝试运行来自各种应用程序的待处理作业请求时,会发生IDLE_MAINTENANCE

但是,如果是这种情况,为什么当我的应用中的计划作业运行时检查它们时,PowerManager.isDeviceIdleMode()PowerManger.isPowerSaveMode() 始终返回false

JobInfo.Builder非常友好地允许您设置setMinimumLatencysetOverrideDeadline等标准,但据我所知,操作系统母鸡会轻易忽视它们 - 有时候我有工作彼此之间相隔几秒钟,最多相隔两小时。

为什么没有API函数来测试Doze及其子模式?我希望在PowerManager中找到它,但我发现只有isDeviceIdleModeisPowerSaveMode在测试时始终返回false

处于打盹模式的应用

  • 所有其背景服务是否已被销毁?

  • 无法获得正常的优先推送消息吗?

  • 不会响应警报 - 但setAndAllowWhenIdle除外?

  • 它的任何广播接收器都没有通信?

  • 无法在套接字上连接到外部世界 - 因此推送消息,发布/订阅等不起作用?

  • 将立即销毁Android清单中声明的​​任何广播接收器。这是我自己的发现 - 我从Java代码创建的接收器仍然存在,尽管它们在打瞌睡期间不起作用。

我自己的应用程序通过设置广播接收器并呼叫.FusedLocationApi.requestLocationUpdates来监视地理位置的变化。此接收器存活打盹/唤醒周期。但是,保证我的LocationUpdates请求在唤醒后仍然有效吗?

我遇到了一个相当特殊的错误。我发现我在打瞌睡的预定工作在偶然的情况下彼此过于接近,即使我已经给他们延迟900,000毫秒(15分钟)和截止日期1,000,000毫秒。我以为我会通过跟踪我上次运行的最后一次运行来测试最后一次运行这个问题。

private static Boolean shortInstantGap()
{
  Long instantNow = Instant.now().getEpochSecond();
  if (300 > (instantNow - this.lastInstant)) return true;
  //ignore the job opportunity if the last one was
  //less than 300s (5 minutes) ago
  this.lastInstant = instantNow;
  return false;
 }

然后中止职位空缺

private static Runnable timeRunner = new Runnable() 
{
 @Override
 public void run() 
 {
  if (shortInstantGap()) return;
  callMyHandlerCode();
 }
};

然而,我发现这个代码导致操作系统突然终止我的应用程序,如果它在屏幕上,当我经历屏幕关闭屏幕开启周期。为什么会这样?

最后,是否没有我可以用来测试设备刚从打瞌睡中返回的API调用,所以我有机会做一些打瞌睡的家务管理?

0 个答案:

没有答案