android 电耗模式(Doze)和应用待机模式(App standby)

sancaiodm Android应用 2022-07-16 2747 0

使用命令 adb shell dumpsys batterystats > batterystats.txt 获取电池状态的日志.

-------------------------------------------------------------------------

待机电流LOG中查看两关键字理解:

wakelock : 应用或者服务不停的申请/释放wakelock会造成系统不能进入休眠状态。

interrupt

SuspendResume作用

suspend: 让线程挂起,暂停,程序停止往下执行。

resume: 唤醒被suspend的程序,让程序继续执行。


BatteryStatsService: In wakeup_callback: resumed from suspend

BatteryStatsService: In wakeup_callback: suspend aborted


KeyguardViewMediator: onStartedGoingToSleep(3)

KeyguardViewMediator: setting alarm to turn off keyguard, seq = 1

KeyguardViewMediator: notifyStartedGoingToSleep


PowerManagerService: Powering off display group due to timeout (groupId= 0, uid= 1000)...

PowerManagerService: Going to sleep due to timeout (uid 1000)...

PowerManagerService: Sleeping display group (groupId=0, uid=1000)...

PowerManagerService: Sleeping (uid 1000)...


android.intent.action.SCREEN_OFF

---------------------------------------------------------

#查看电池状态

adb shell dumpsys battery

Current Battery Service state:

  AC powered: false    //排插充电头充电

  USB powered: true   //USB数据线充电 

  Wireless powered: false   //无线充电

  Max charging current: 500000

  Max charging voltage: 5000000

  Charge counter: 2946000

  status: 2

  health: 2

  present: true

  level: 100

  scale: 100

  voltage: 4436

  temperature: 271

  technology: Li-ion

# 进入未连接充电的模式

adb shell dumpsys battery unplug

#让IDLE有效化

adb shell dumpsys deviceidle enable 

# 强行进入Doze模式(deep表示深度打盹)

adb shell dumpsys deviceidle step [light|deep]

# 退出Doze模式,让手机恢复正常需要复位充电模式

adb shell dumpsys battery reset

进入 Doze 模式

adb shell dumpsys deviceidle force-idle  //不能单一条命令强制进入idel状态

C:\Users\anddrodos.net>adb shell dumpsys deviceidle force-idle

Unable to go deep idle; not enabled

#查看手机是当前状态,是否已进入IDLE状态

 adb shell dumpsys deviceidle

退出Doze模式

adb shell dumpsys deviceidle unforce

重启激活设备

adb shell dumpsys battery reset

#adb 设置让手机进入IDLE状态,博主验证如下

[1]adb shell dumpsys battery unplug

[2]adb shell dumpsys deviceidle enable 

[3]adb shell dumpsys deviceidle force-idle

[4] adb shell dumpsys deviceidle  //查看

image.png

---------------------------------------------

07-16 08:50:12.555   990  1118 I PowerManagerService: Waking up from Asleep (uid=1000, reason=WAKE_REASON_POWER_BUTTON, details=android.policy:POWER).

..

07-16 23:07:52.652   990  1073 I PowerManagerService: Going to sleep due to timeout (uid 1000)...

07-16 23:14:43.813   990  1118 I PowerManagerService: Powering on display group fromAsleep (groupId=0, uid=1000, reason=WAKE_REASON_POWER_BUTTON, deta

ils=android.policy:POWER)...

07-16 23:14:43.813   990  1118 I PowerManagerService: Waking up from Asleep (uid=1000, reason=WAKE_REASON_POWER_BUTTON, details=android.policy:POWER).

..

07-16 23:27:12.882   990  1073 I PowerManagerService: Going to sleep due to timeout (uid 1000)...

07-16 23:28:23.905   990  1118 I PowerManagerService: Powering on display group fromAsleep (groupId=0, uid=1000, reason=WAKE_REASON_POWER_BUTTON, deta

ils=android.policy:POWER)...

07-16 23:28:23.905   990  1118 I PowerManagerService: Waking up from Asleep (uid=1000, reason=WAKE_REASON_POWER_BUTTON, details=android.policy:POWER).

..

07-16 23:34:55.832   990  1118 I WindowManager: sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)

07-16 23:34:55.832   990  1118 I PowerManagerService: Powering off display group due to sleep_button (groupId= 0, uid= 1000)...

07-16 23:34:55.832   990  1118 I PowerManagerService: Going to sleep due to sleep_button (uid 1000)...

------------------------------------------------------------------------

07-16 23:49:20.161   482   493 I mtkpower@impl: [setMode] type:5, enabled:1


------------------------------------------------------------------------------------

针对低电耗模式(Doze)和应用待机模式(Standby)进行优化

从 Android 6.0(API 级别 23)开始,Android 引入了两项省电功能,通过管理应用在设备未连接至电源时的行为方式,帮助用户延长电池寿命。当用户长时间未使用设备时,低电耗模式会延迟应用的后台 CPU 和网络活动,从而降低耗电量。应用待机模式会延迟用户近期未与之交互的应用的后台网络活动。

当设备处于低电耗模式时,应用对某些高耗电量资源的访问会延迟到维护期。电源管理限制中列出了具体的限制。

低电耗模式和应用待机模式管理在 Android 6.0 或更高版本上运行的所有应用的行为,无论它们是否专用于 API 级别 23。为确保用户获得最佳体验,请在低电耗模式和应用待机模式下测试您的应用,并对您的代码进行必要的调整。下面几部分提供了详细信息。

如果用户未插接设备的电源,在屏幕关闭的情况下,让设备在一段时间内保持不活动状态,那么设备就会进入低电耗模式。在低电耗模式下,系统会尝试通过限制应用访问占用大量网络和 CPU 资源的服务来节省电量它还会阻止应用访问网络,并延迟其作业、同步和标准闹钟。

系统会定期退出低电耗模式一小段时间,让应用完成其延迟的活动。在此维护期内,系统会运行所有待处理的同步、作业和闹钟,并允许应用访问网络。

图 1. 低电耗模式提供了周期性维护期,让应用使用网络并处理待处理的活动。

在每个维护期结束时,系统会再次进入低电耗模式,暂停网络访问并推迟作业、同步和闹钟。随着时间的推移,系统安排维护期的次数越来越少,这有助于在设备未连接至充电器的情况下长期处于不活动状态时降低耗电量。

而 Android 7.0 则通过在设备未插接电源且屏幕关闭状态下、但不一定要处于静止状态(例如用户外出时把手持式设备装在口袋里)时应用部分 CPU 和网络限制,进一步增强了低电耗模式。

图 1. 低电耗模式如何应用第一级系统活动限制以延长电池寿命的图示。

7.0进入Doze模式分两个阶段: 对App行为的限制分为light idle(浅度doze)和deep idle(深度doze).当设备处于非充电状态且屏幕已关闭一定时间后,设备会进入低电耗模式并应用第一部分限制(light idle):关闭应用网络访问、推迟作业和同步。如果进入低电耗模式后设备处于静止状态达到一定时间,系统则会对 PowerManager.WakeLock、AlarmManager 闹铃、GPS 和 WLAN 扫描应用余下的低电耗模式限制(deep idle)。无论是应用部分还是全部低电耗模式限制,系统都会唤醒设备以提供简短的维护时间窗口,在此窗口期间,应用程序可以访问网络并执行任何被推迟的作业/同步。

light idle:(第一级限制,图2中 第一个Doze阶段)
           进入条件:   非充电状态且屏幕已关闭一定时间后
           限制:       关闭应用网络访问、推迟作业和同步
 deep idle:(第二级限制,图2中 第二个Doze阶段)
           进入条件:   进入light idle模式后设备处于静止状态达到一定时间
           限制:       PowerManager.WakeLock、AlarmManager 闹铃、GPS 和 WLAN 扫描

在每个维护时段结束后,系统会再次进入低电耗模式,暂停网络访问并推迟作业、同步和闹铃。 随着时间的推移,系统安排维护时段的次数越来越少,这有助于在设备未连接至充电器的情况下长期处于不活动状态时降低电池消耗。

图 2. 低电耗模式如何在设备处于静止状态达到一定时间后应用第二级系统活动限制的图示。

图中,横轴表示随着时间的推移,橙色表示设备处于唤醒运行状态,绿色表示低电耗(Doze)休眠状态;

当设备处于on battery(利用电池供电,也就是未插接电源),

screen off(关闭屏幕),stationary(静止状态,7.0以后非静止状态亦可)保持以上条件一段时间之后,设备就会进入Doze模式.

maintenance window (低电耗(Doze)模式提供了定期维护时段,可供应用使用网络并处理待定Activity),Doze模式下会定期的进入maintenance window,但进入的间隔越来越长

一旦用户通过移动设备、打开屏幕或连接到充电器唤醒设备,系统就会立即退出低电耗模式,并且所有应用都将返回到正常 Activity。

在低电耗模式下,您的应用会受到以下限制:

低电耗模式可能会对应用产生不同的影响,具体取决于应用提供的功能和使用的服务。许多应用无需修改即可在低电耗模式周期内正常运行。在某些情况下,您必须优化应用管理网络、闹钟、作业和同步的方式。应用应该能够在每个维护期内高效地管理活动。

低电耗模式尤其可能会影响 AlarmManager 闹钟和定时器管理的活动,因为当系统处于低电耗模式时,不会触发 Android 5.1(API 级别 22)或更低版本中的闹钟。

为了帮助安排闹钟,Android 6.0(API 级别 23)引入了两种新的 AlarmManager 方法:setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle()。通过这些方法,您可以设置即使设备处于低电耗模式也会触发的闹钟。

注意setAndAllowWhileIdle() 及 setExactAndAllowWhileIdle() 为每个应用触发闹钟的频率都不能超过每 9 分钟一次。

低电耗模式对网络访问的限制也有可能影响应用,特别是当应用依赖于操作消息或通知等实时消息时更是如此。如果应用需要与网络建立持久性连接来接收消息,您应尽可能使用 Firebase 云消息传递 (FCM)

要确认应用在低电耗模式下的行为方式符合预期,您可以使用 adb 命令强制系统进入和退出低电耗模式并观察应用的行为。如需了解详情,请参阅在低电耗模式和应用待机模式下进行测试

应用待机模式允许系统判定应用在用户未主动使用它时是否处于闲置状态。当用户有一段时间未触摸应用时,系统便会作出此判定,以下条件均不适用:

  • 用户明确启动应用。

  • 应用当前有一个进程在前台运行(作为活动或前台服务,或者正在由其他活动或前台服务使用)。

    注意:您只能将前台服务用于用户希望系统立即执行或不中断的任务。 此类情况包括将照片上传到社交媒体,或者即使在音乐播放器应用不在前台运行时也能播放音乐。您不应该只是为了阻止系统判定您的应用处于闲置状态而启动前台服务。

  • 应用生成用户可在锁定屏幕或通知栏中看到的通知。

  • 应用是正在使用中的设备管理应用(例如设备政策控制器)。虽然设备管理应用通常在后台运行,但永远不会进入应用待机模式,因为它们必须保持可用性,以便随时从服务器接收策略。

当用户将设备插入电源时,系统会从待机状态释放应用,允许它们自由访问网络并执行任何待处理的作业和同步。如果设备长时间处于闲置状态,系统将允许闲置应用访问网络,频率大约每天一次。

在设备处于闲置状态时使用 FCM 与您的应用互动

Firebase 云消息传递 (FCM) 是一项云端至设备服务,可让您支持后端服务与 Android 设备上的应用之间的实时下游消息传递。FCM 提供了一个到云的持久性连接,所有需要实时消息传递的应用均可共享此连接。此共享连接使多个应用不必保有自己的独立持久性连接,也就避免了快速耗尽电池电量,从而显著优化耗电情况。因此,如果您的应用需要与后端服务进行消息传递集成,我们强烈建议您尽可能使用 FCM,而不是保有自己的持久性网络连接。

FCM 经过优化,可通过高优先级 FCM 消息来支持低电耗模式和应用待机闲置模式。利用高优先级 FCM 消息,您可以可靠地唤醒应用以访问网络,即使用户的设备处于低电耗模式或应用处于应用待机模式也不例外。在低电耗模式或应用待机模式下,系统将传递消息并允许应用临时访问网络服务和部分唤醒锁定,然后将设备或应用恢复到闲置状态。

高优先级 FCM 消息不会影响低电耗模式,也不会影响任何其他应用的状态。这意味着您的应用可以使用这些消息来高效地通信,同时尽可能减小对整个系统和设备的电池影响。

作为一项常规最佳做法,如果您的应用需要下游消息传递,那么应使用 FCM。如果您的服务器和客户端已经在使用 FCM,请确保您的服务对关键消息使用高优先级消息,因为即使设备处于低电耗模式,这也会可靠地唤醒应用。

通过妥善管理网络连接、闹钟、作业和同步以及使用高优先级 FCM 消息,几乎所有应用都应该能够支持低电耗模式。对于一小部分用例,这可能还不够。对于此类用例,系统提供了一个可配置的白名单,将部分免除低电耗模式和应用待机模式优化的应用列入其中。

在低电耗模式和应用待机模式期间,列入白名单的应用可以使用网络并保留部分唤醒锁定。不过,列入白名单的应用仍会受到其他限制,就像其他应用一样。例如,列入白名单的应用的作业和同步会延迟(在搭载 API 级别 23 及更低级别的设备上),并且其常规 AlarmManager 闹钟不会触发。应用可以调用 isIgnoringBatteryOptimizations() 来检查它当前是否在豁免白名单中。

用户可以依次转到设置 > 电池 > 电池优化来手动配置该白名单。另外,系统也提供了一些方法,让应用要求用户将其列入白名单。

在要求用户将您的应用添加到白名单之前,请确保该应用符合列入白名单的可接受用例

注意:除非应用的核心功能受到不利影响,否则 Google Play 政策禁止应用请求直接免除 Android 6.0 及更高版本中的电源管理功能(低电耗模式和应用待机模式)的制约。

为确保用户获得良好的体验,您应在低电耗模式和应用待机模式下全面测试您的应用。

您可以按以下步骤在低电耗模式下测试您的应用:

  1. 使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。

  2. 将设备连接到开发计算机并安装您的应用。

  3. 运行您的应用并使其保持活动状态。

  4. 运行以下命令,强制系统进入闲置模式:

        $ adb shell dumpsys deviceidle force-idle
  5. 准备就绪后,运行以下命令,使系统退出闲置模式:

        $ adb shell dumpsys deviceidle unforce
  6. 执行以下命令,重新激活设备:

        $ adb shell dumpsys battery reset
  7. 在重新激活设备后观察应用的行为。确保应用在设备退出低电耗模式时正常恢复。

如需在应用待机模式下测试您的应用,请执行以下操作:

  1. 使用 Android 6.0(API 级别 23)或更高版本的系统映像配置硬件设备或虚拟设备。

  2. 将设备连接到开发计算机并安装您的应用。

  3. 运行您的应用并使其保持活动状态。

  4. 运行以下命令,强制应用进入应用待机模式:

    $ adb shell dumpsys battery unplug
        $ adb shell am set-inactive <packageName> true
  5. 使用以下命令模拟唤醒您的应用:

    $ adb shell am set-inactive <packageName> false
        $ adb shell am get-inactive <packageName>
  6. 在唤醒应用后观察它的行为。确保应用从待机模式正常恢复。您应特别检查应用的通知和后台作业是否继续按预期运行。

下表重点介绍了请求将应用列入电池优化豁免白名单或应用目前在该白名单中的可接受用例。一般来说,除非低电耗模式或应用待机模式破坏了应用的核心功能,或者由于技术方面的原因而导致您的应用无法使用高优先级 FCM 消息,否则您的应用不应在白名单中。


评论