生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。—海明威
WakeLock是什么
WakeLock是Android框架层提供的一套机制,应用使用该机制可以达到控制Android设备状态的目的。这里的设备状态主要指屏幕的打开关闭,cpu的保持运行。简单的理解WakeLock是让系统保持”清醒”的一种手段.
WakeLock作用
当手机灭屏状态下保持一段时间后,系统会进入休眠,一些后台运行的任务就可能得不到正常执行,比如网络下载中断,后台播放音乐暂停等。WakeLock正是为了解决这类问题,应用只要申请了WakeLock,那么在释放WakeLock之前,系统不会进入休眠,即使在灭屏的状态下,应用要执行的任务依旧不会被系统打断。
WakeLock有那些分类
WakeLock是PowerManager的内部类,其代码路径位于:
frameworks/base/core/java/android/os/PowerManager.java
WakeLock 分类如下:
- PARTIAL_WAKE_LOCK: 灭屏,关闭键盘背光的情况下,CPU依然保持运行。
- PROXIMITY_SCREEN_OFF_WAKE_LOCK: 基于距离感应器熄灭屏幕。最典型的运用场景是我们贴近耳朵打电话时,屏幕会自动熄灭。
- SCREEN_DIM_WAKE_LOCK/SCREEN_BRIGHT_WAKE_LOCK/FULL_WAKE_LOCK:这三种WakeLock都已经过时了,它们的目的是为了保持屏幕长亮,Android官方建议用
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
方式替换。因为比起申请WakeLock,这种方式更简单,还不需要特别申请android.permission.WAKE_LOCK
权限。 - DOZE_WAKE_LOCK/DRAW_WAKE_LOCK: 隐藏的分类,系统级别才会用到。
WakeLock的flag如下:
- ACQUIRE_CAUSES_WAKEUP: 点亮屏幕,比如应用接收到通知后,屏幕亮起。
- ON_AFTER_RELEASE: 释放WakeLock后,屏幕不马上熄灭。
- UNIMPORTANT_FOR_LOGGING: 隐藏的flag,系统级别才会用到。
WakeLock的设置过程
WakeLock从用户空间下发设置操作,然后进入kernel空间,最终写入到了/sys/power/wake_lock
文件节点。
下面来从源码的角度跟踪下acquire WakeLock的过程。
frameworks/base/core/java/android/os/PowerManager.java
acquire—>acquireLocked—->PowerManagerService.acquireWakeLockframeworks/base/services/core/java/com/android/server/power/PowerManagerService.java
acquireWakeLock—>acquireWakeLockInternal—->updatePowerStateLocked—->updateSuspendBlockerLocked—->mWakeLockSuspendBlocker.acquire—->PowerManagerService$SuspendBlockerImpl.acquire—->nativeAcquireSuspendBlockerframeworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
nativeAcquireSuspendBlocker—->acqu