Android中的WakeLock

两个处理器

Application Processor (AP):

AP是ARM架构的处理器,用于运行Linux+Android系统。

Baseband Processpr (BP):

BP用于运行实时操作系统(RTOS),运行手机射频通信控制软件。

非通话时间BP能耗很低;而AP由于需要运行操作系统、用户界面和应用程序,只要处于非休眠状态能耗相对BP要高出很多,执行图形运算会更高。

让系统保持“清醒”

当手机灭屏状态下保持一段时间后,系统会进入休眠,一些后台任务比如网络下载,播放音乐会得不到正常的执行。WakeLock API可以确保应用程序中关键代码的正确执行,使应用程序有能力控制AP的休眠状态。

一种锁机制

当应用申请了WakeLock,WakeLock会阻止AP挂起,系统无法进入休眠,即使在灭屏的状态下,应用要执行的任务依然不会被打断。当所有WakeLock被释放(解锁/超时),系统会挂起启动休眠机制进入休眠。

使用WakeLock

<!--WakeLock需要的权限-->
<uses-permission android:name="android.permission.WAKE_LOCK"/>

 PowerManager pm= (PowerManager) this.getSystemService(Context.POWER_SERVICE);
 PowerManager.WakeLock wakeLock=pm.newWakeLock(PowerManager.ON_AFTER_RELEASE|PowerManager.PARTIAL_WAKE_LOCK,"Tag");
 //申请WakeLock
 wakeLock.acquire();

 //... do work...

 //释放wakeLock
 //当使用wakeLock.acquire(timeout)的方式时系统会自动释放
 wakeLock.release(); 

WakeLock的分类和Flag
分类
  • PARTIAL_WAKE_LOCK: 灭屏,关闭键盘背光的情况下,CPU依然保持运行。

  • PROXIMITY_SCREEN_OFF_WAKE_LOCK: 基于距离感应器熄灭屏幕。最典型的运用场景是我们贴近耳朵打电话时,屏幕会自动熄灭。

  • SCREEN_DIM_WAKE_LOCK
    SCREEN_BRIGHT_WAKE_LOCK
    FULL_WAKE_LOCK
    三种过时方法,它们的目的是保持屏幕常亮。

    官方建议使用:

    //不需要申请WakeLock和权限
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    
  • DOZE_WAKE_LOCK/DRAW_WAKE_LOCK: 隐藏的分类,系统级别才会用到。

Flag
  • ACQUIRE_CAUSES_WAKEUP: 点亮屏幕,比如应用接收到通知后,屏幕亮起。
  • ON_AFTER_RELEASE: 释放WakeLock后,屏幕不马上熄灭。
  • UNIMPORTANT_FOR_LOGGING: 隐藏的flag,系统级别才会用到。

其他方法

//判断是否已经获取WakeLock
 wakeLock.isHeld();
//是否引用计数器
 wakeLock.setReferenceCounted(false);

默认true开启引用计数器,如果一个WakeLock acquire了多次也必须release多次才能释放掉。但是如果释放次数比acquire多则会抛出RuntimeException(Tag)异常。
false关闭引用计数器时,无论 acquire() 了多少次,只要通过一次 release()即可解锁。

PS:PowerManager.WakeLock 的计数机制并只是对同一把锁被申请/释放的次数进行了统计再正去操作。

简单的debug方法

测试代码

/**
 * @Author: 吃茶泡饭丶
 * @CreateDate: 2018/9/3
 */
public class WakeLockActivity extends BaseActivity {

    private PowerManager.WakeLock wakeLock;

    @Override
    protected void onResume() {
        PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.ON_AFTER_RELEASE
                | PowerManager.PARTIAL_WAKE_LOCK, "Tag");
        //申请WakeLock
        wakeLock.acquire();
        super.onResume();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wake_lock);
        //... do work...
    }

    @Override
    protected void onPause() {
        //释放wakeLock
        //当使用wakeLock.acquire(timeout)的方式时系统会自动释放
        wakeLock.release();
        super.onPause();
    }
}

通过adb 命令

adb shell dumpsys "power|grep -i wake" 
and
$ adb shell dumpsys power|grep -i wake

进入onResume申请WakeLock,dumpsys的信息

  no_cached_wake_locks=true
  mWakefulness=Awake
  mWakefulnessChanging=false
  mWakeLockSummary=0x1
  mLastWakeTime=509144080 (30113 ms ago)
  mHoldingWakeLockSuspendBlocker=true
  mWakeUpWhenPluggedOrUnpluggedConfig=true
  mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  mDoubleTapWakeEnabled=false
  Wake Locks: size=1
  mLock:176961948 PARTIAL_WAKE_LOCK              'Tag' ON_AFTER_RELEASE ACQ=-2s581ms (uid=10155 pid=26429)
  PowerManagerService.WakeLocks: ref count=1
  Proxyed WakeLocks State

进入onPause释放WakeLock,dumpsys的信息

  no_cached_wake_locks=true
  mWakefulness=Awake
  mWakefulnessChanging=false
  mWakeLockSummary=0x0
  mLastWakeTime=509144080 (271089 ms ago)
  mHoldingWakeLockSuspendBlocker=false
  mWakeUpWhenPluggedOrUnpluggedConfig=true
  mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig=false
  mDoubleTapWakeEnabled=false
  Wake Locks: size=0
  PowerManagerService.WakeLocks: ref count=0
  Proxyed WakeLocks State

准确的debug方法

使用battery historian 工具,在应用运行一段时间后抓取bugreport查看wakelock申请情况。
https://github.com/google/battery-historian
需要搭建GO语言环境

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容