转自 http://blog.csdn.net/kc58236582/article/details/51568506

这篇博客主要分析power按键点亮屏幕和灭屏,而且我们主要分析在PhoneWIndowManager的流程。

之前的博客我们分析过按键的流程,当有按键会先到PhoneWindowManager的interceptKeyBeforeQueueing函数,然后再去分析到应用,而power按键也是如此,并且其最后不会分发到应用中去,下面我们看下PhoneWindowManager的interceptKeyBeforeQueueing函数对power按键处理的代码:

顺便说下这个interactive这个变量是从NativeInputManager中传过来的,在NativeInputManager也是有一个mInteractive的成员变量,是PowerManagerService改变状态的时候在Notifier.java中调用InputManagerService的Native方法,到NativeInputManager的方法nativeSetInteractive方法来设置的mInteractive变量的。所以这个值也可以说是PowerManagerService关于屏幕的状态。

[cpp] view plaincopy
  1. case KeyEvent.KEYCODE_POWER: {
  2. result &= ~ACTION_PASS_TO_USER;//不分发到应用
  3. isWakeKey = false; // wake-up will be handled separately
  4. if (down) {
  5. Log.i(TAG, "PowerKey down, interactive = " + interactive);
  6. interceptPowerKeyDown(event, interactive);//按键down
  7. } else {
  8. Log.i(TAG, "PowerKey up.");
  9. interceptPowerKeyUp(event, interactive, canceled);//按键up
  10. }
  11. break;
  12. }

一、Powerkey down

我们先来看下按键down的interceptPowerKeyDown函数:

[cpp] view plaincopy
  1. private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
  2. // Hold a wake lock until the power key is released.
  3. if (!mPowerKeyWakeLock.isHeld()) {//上层持锁
  4. mPowerKeyWakeLock.acquire();
  5. }
  6. // Cancel multi-press detection timeout.
  7. if (mPowerKeyPressCounter != 0) {//在我们的手机不支持这块,统计多次按键
  8. mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
  9. }
  10. ...
  11. if (!mPowerKeyHandled) {
  12. if (interactive) {//亮屏
  13. // When interactive, we're already awake.
  14. // Wait for a long press or for the button to be released to decide what to do.
  15. if (hasLongPressOnPowerBehavior()) {//是否支持长按键
  16. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  17. msg.setAsynchronous(true);
  18. mHandler.sendMessageDelayed(msg,
  19. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  20. }
  21. } else {
  22. wakeUpFromPowerKey(event.getDownTime());
  23. if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
  24. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  25. msg.setAsynchronous(true);
  26. mHandler.sendMessageDelayed(msg,
  27. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  28. mBeganFromNonInteractive = true;
  29. } else {
  30. final int maxCount = getMaxMultiPressPowerCount();
  31. if (maxCount <= 1) {
  32. mPowerKeyHandled = true;
  33. } else {
  34. mBeganFromNonInteractive = true;
  35. }
  36. }
  37. }
  38. }
  39. }

1.1 亮屏 长按键处理

我们先来看看hasLongPressOnPowerBehavior函数:

[cpp] view plaincopy
  1. private boolean hasLongPressOnPowerBehavior() {
  2. return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;//不为0
  3. }

再来看看getResolvedLongPressOnPowerBehavior函数

[cpp] view plaincopy
  1. private int getResolvedLongPressOnPowerBehavior() {
  2. if (FactoryTest.isLongPressOnPowerOffEnabled()) {
  3. return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
  4. }
  5. return mLongPressOnPowerBehavior;
  6. }

其中又调用了isLongPressOnPowerOffEnabled,我们没有支持这个属性。因此只要看mLongPressOnPowerBehavior这个变量

[cpp] view plaincopy
  1. public static boolean isLongPressOnPowerOffEnabled() {
  2. return SystemProperties.getInt("factory.long_press_power_off", 0) != 0;
  3. }

下面再看看mLongPressOnPowerBehavior 这个变量的初始化。

[cpp] view plaincopy
  1. mLongPressOnPowerBehavior = mContext.getResources().getInteger(
  2. com.android.internal.R.integer.config_longPressOnPowerBehavior);

看资源apk:

[html] view plaincopy
  1. ./res/values/config.xml:743:    <integer name="config_longPressOnPowerBehavior">1</integer

也就是mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回1.

[cpp] view plaincopy
  1. if (hasLongPressOnPowerBehavior()) {
  2. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  3. msg.setAsynchronous(true);
  4. mHandler.sendMessageDelayed(msg,
  5. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  6. }

然后就发消息,我们再来看处理消息:

[cpp] view plaincopy
  1. case MSG_POWER_LONG_PRESS:
  2. powerLongPress();

再来看powerLongPress函数

[cpp] view plaincopy
  1. private void powerLongPress() {
  2. final int behavior = getResolvedLongPressOnPowerBehavior();
  3. switch (behavior) {
  4. case LONG_PRESS_POWER_NOTHING:
  5. break;
  6. case LONG_PRESS_POWER_GLOBAL_ACTIONS://返回1
  7. mPowerKeyHandled = true;
  8. if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
  9. performAuditoryFeedbackForAccessibilityIfNeed();
  10. }
  11. showGlobalActionsInternal();//下面就是弹出关机,重启之类的对话框了
  12. break;

上面之前我们再添加长按对话框添加重启功能的那篇博客有涉及,这就是在亮屏的时候长按power的流程。

1.2 灭屏 按键down处理

下面我们再来看看,interceptPowerKeyDown的另一个分支,关于现在是灭屏的时候,按键down。

[cpp] view plaincopy
  1. else {//灭屏
  2. wakeUpFromPowerKey(event.getDownTime());//亮屏
  3. if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
  4. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  5. msg.setAsynchronous(true);
  6. mHandler.sendMessageDelayed(msg,
  7. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  8. mBeganFromNonInteractive = true;
  9. } else {
  10. final int maxCount = getMaxMultiPressPowerCount();
  11. if (maxCount <= 1) {
  12. mPowerKeyHandled = true;
  13. } else {
  14. mBeganFromNonInteractive = true;
  15. }
  16. }

第一步直接调用wakeUpFromPowerKey函数,我们看下这个函数:

[cpp] view plaincopy
  1. private void wakeUpFromPowerKey(long eventTime) {
  2. wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");//这里mAllowTheaterModeWakeFromPowerKey为true
  3. }
  4. private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
  5. final boolean theaterModeEnabled = isTheaterModeEnabled();
  6. if (!wakeInTheaterMode && theaterModeEnabled) {
  7. return false;
  8. }
  9. if (theaterModeEnabled) {
  10. Settings.Global.putInt(mContext.getContentResolver(),
  11. Settings.Global.THEATER_MODE_ON, 0);
  12. }
  13. mPolicyLooper.setMessageLogging(mLogPrinter);
  14. mPowerManager.wakeUp(wakeTime, reason);
  15. return true;
  16. }

这里mAllowTheaterModeWakeFromPowerKey为true,因此就直接调用了PowerManager的wakeUp函数了,reason是"android.policy:POWER"

[cpp] view plaincopy
  1. else {//灭屏
  2. wakeUpFromPowerKey(event.getDownTime());//亮屏
  3. if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
  4. Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
  5. msg.setAsynchronous(true);
  6. mHandler.sendMessageDelayed(msg,
  7. ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
  8. mBeganFromNonInteractive = true;
  9. } else {
  10. final int maxCount = getMaxMultiPressPowerCount();//返回为1,不支持多次按钮
  11. if (maxCount <= 1) {
  12. mPowerKeyHandled = true;//走这里
  13. } else {
  14. mBeganFromNonInteractive = true;
  15. }
  16. }

而下面mSupportLongPressPowerWhenNonInteractive 我们配置也是false不支持。多按钮也不支持,因此maxCount为1

二、PowerKey On

PowerKey on 又分为之前down的时候是灭屏还是亮屏处理的,逻辑又不一样。

2.1 之前power按键 down是灭屏的

我们先来看之前Power按键 down的时候手机是灭屏的情况下,下面我们分析PowerKey on的interceptPowerKeyUp函数:

[cpp] view plaincopy
  1. private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
  2. final boolean handled = canceled || mPowerKeyHandled;//记得之前灭屏按键down的时候,mPowerKeyHandled = true
  3. mScreenshotChordPowerKeyTriggered = false;
  4. cancelPendingScreenshotChordAction();
  5. cancelPendingPowerKeyAction();
  6. if (!handled) {
  7. // Figure out how to handle the key now that it has been released.
  8. mPowerKeyPressCounter += 1;
  9. final int maxCount = getMaxMultiPressPowerCount();
  10. final long eventTime = event.getDownTime();
  11. if (mPowerKeyPressCounter < maxCount) {
  12. // This could be a multi-press.  Wait a little bit longer to confirm.
  13. // Continue holding the wake lock.
  14. Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
  15. interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
  16. msg.setAsynchronous(true);
  17. mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
  18. return;
  19. }
  20. // No other actions.  Handle it immediately.
  21. powerPress(eventTime, interactive, mPowerKeyPressCounter);
  22. }
  23. // Done.  Reset our state.
  24. finishPowerKeyPress();
  25. }

之前在手机灭屏我们按power键down的时候,最后mPowerKeyHandled = true,这里handled = true,最后直接调用

[cpp] view plaincopy
  1. private void finishPowerKeyPress() {
  2. mBeganFromNonInteractive = false;//我们手机不支持
  3. mPowerKeyPressCounter = 0;//多按键,不支持
  4. if (mPowerKeyWakeLock.isHeld()) {
  5. mPowerKeyWakeLock.release();//之前按power键down时候的锁释放
  6. }
  7. }

2.2 之前power按键 down是亮屏的

之前power按键 down的时候手机亮屏,power down又分为长按和短按。我们先来看之前power down亮屏,down是长按的情况下,现在是power up的情况:

[cpp] view plaincopy
  1. private void powerLongPress() {
  2. final int behavior = getResolvedLongPressOnPowerBehavior();
  3. switch (behavior) {
  4. case LONG_PRESS_POWER_NOTHING:
  5. break;
  6. case LONG_PRESS_POWER_GLOBAL_ACTIONS://为1
  7. mPowerKeyHandled = true;
  8. if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
  9. performAuditoryFeedbackForAccessibilityIfNeed();
  10. }
  11. showGlobalActionsInternal();
  12. break;
  13. case LONG_PRESS_POWER_SHUT_OFF:
  14. case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
  15. mPowerKeyHandled = true;
  16. performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
  17. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
  18. mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
  19. break;
  20. }
  21. }

之前看过这函数,长按mPowerKeyHandled = true,和上面一样。直接最后interceptPowerKeyUp函数就调用finishPowerKeyPress函数了。

然后我们再来看之前powerKey Down的时候是亮屏的,又是短按的情况,我们再来看interceptPowerKeyUp函数:

[cpp] view plaincopy
  1. private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
  2. final boolean handled = canceled || mPowerKeyHandled;//这个实收handled为false了
  3. mScreenshotChordPowerKeyTriggered = false;
  4. cancelPendingScreenshotChordAction();
  5. cancelPendingPowerKeyAction();
  6. if (!handled) {
  7. // Figure out how to handle the key now that it has been released.
  8. mPowerKeyPressCounter += 1;
  9. final int maxCount = getMaxMultiPressPowerCount();//这个返回为1,本来是多次按钮的。这里没有配置
  10. final long eventTime = event.getDownTime();
  11. if (mPowerKeyPressCounter < maxCount) {
  12. // This could be a multi-press.  Wait a little bit longer to confirm.
  13. // Continue holding the wake lock.
  14. Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
  15. interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
  16. msg.setAsynchronous(true);
  17. mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
  18. return;
  19. }
  20. // No other actions.  Handle it immediately.
  21. powerPress(eventTime, interactive, mPowerKeyPressCounter);
  22. }
  23. // Done.  Reset our state.
  24. finishPowerKeyPress();
  25. }

我们先看看getMaxMultiPressPowerCount函数:

[cpp] view plaincopy
  1. private int getMaxMultiPressPowerCount() {
  2. if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {// 为0
  3. return 3;
  4. }
  5. if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {//为0
  6. return 2;
  7. }
  8. return 1;
  9. }

最后这个函数返回为1,因此上面函数就直接调用powerPress函数了。

[cpp] view plaincopy
  1. private void powerPress(long eventTime, boolean interactive, int count) {
  2. if (mScreenOnEarly && !mScreenOnFully) {
  3. Slog.i(TAG, "Suppressed redundant power key press while "
  4. + "already in the process of turning the screen on.");
  5. return;
  6. }
  7. if (count == 2) {
  8. powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
  9. } else if (count == 3) {
  10. powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
  11. } else if (interactive && !mBeganFromNonInteractive) {//之前我们只支持1,必须亮屏,另一个参数这里为false
  12. switch (mShortPressOnPowerBehavior) {// 这个参数也是资源apk中配置的,为1
  13. case SHORT_PRESS_POWER_NOTHING:
  14. break;
  15. case SHORT_PRESS_POWER_GO_TO_SLEEP://直接调用PowerManager的goToSleep函数了
  16. mPowerManager.goToSleep(eventTime,
  17. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
  18. break;
  19. case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
  20. mPowerManager.goToSleep(eventTime,
  21. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
  22. PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
  23. break;
  24. case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
  25. mPowerManager.goToSleep(eventTime,
  26. PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
  27. PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
  28. launchHomeFromHotKey();
  29. break;
  30. case SHORT_PRESS_POWER_GO_HOME:
  31. launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
  32. break;
  33. }
  34. }
  35. }

因为我们没有配置多次power按钮,mShortPressOnPowerBehavior配置为1,所以就直接调用了PowerManager的goToSleep函数了。

三、总结

这篇博客我们主要分析了,power按键在PhoneWindowManager的处理。

power按键down:

1.down又分长按亮屏 弹出关闭重启对话框

2. 短按灭屏 调用wakeup

power按键on:

1.之前down的时候亮屏短按才会调用goToSleep

2.之前down的时候亮屏长按不作处理

3.之前down的时候灭屏不作处理

framework中phonewindowmanager对power键的处理相关推荐

  1. android power 按键,Android Framework层Power键关机流程(一,Power长按键操作处理)

    一:Android处理Power按键长按操作 在Framework层中,Android4.x对Power键(KeyEvent.KEYCODE_POWER)的操作,我们从PhoneWindowManag ...

  2. android power键测试,Android Framework层Power键关机流程(一,Power长按键操作处理)...

    一:Android处理Power按键长按操作 在Framework层中,Android4.x对Power键(KeyEvent.KEYCODE_POWER)的操作,我们从PhoneWindowManag ...

  3. Android Framework层Power键关机流程(二,关机流程)

    二,关机流程 从前一篇博文我们知道,当用户长按Power键时会弹出(关机.重启,飞行模式等选项)对话框,我们点击关机,则会弹出关机确认对话框.那么从选项对话框到关机确认对话框又是一个什么流程呢.下面我 ...

  4. android4.2 拦截power键,Android 屏蔽Power键 Home键

    2014-04-18 17:22 1557人阅读 评论(0) 收藏 举报 分类: Android(46) 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近正在处理工厂测试的功能,里面有个功能 ...

  5. android7.0 电源(Power)键流程

    对于Power键的分析文章较多,本文从android7.0源码的角度大致分析下电源键的流程!参考博主连接:http://blog.csdn.net/gaugamela/article/details/ ...

  6. android 9.0 10.0 去掉音量键+Power键组合键的屏幕截图功能

    1.概述 在10.0的系统中由WindowManagerService这个系统服务来循环读取窗口获取的消息(包括按下,弹起,双击,单击等)然后分发到各个类接收处理这些消息,在这个过程中PhoneWin ...

  7. Android 5.1 长按power键流程分析

    安全模式简述 android平台,在长按power / menu键时会快速进入一个模式选择,部分定制的平台是直接进入安装模式,也可以定制成公司需要的一些特定功能模式,比如报警 ... power 也属 ...

  8. Android中监听Home键的4种方法总结

    本文主要介绍了Android中监听Home键的4种方法总结,主要讲解了onSaveInstanceState方法.onUserLeaveHint方法.ACTION_CLOSE_SYSTEM_DIALO ...

  9. Android系统启动顺序(按下power键后所做的的工作)

    Android是一个基于Linux的开源操作系统.所有的Android设备都是运行在ARM处理器(ARM 源自进阶精简指令集机器,源自ARM架构)上,除了英特尔的Xolo设备(http://xolo. ...

  10. Android rom开发:长按Power键关机/重启优化,告别长时间等待

    最近在项目上碰到了这样的问题:在某个apk界面长按power键来选择关机或者重启,apk会出现重启现象,并且更加尴尬的是,在另外的方案上面对比后发现没有问题,明明白白地显示这是系统的锅. 好吧,改!仔 ...

最新文章

  1. 【微服务架构】SpringCloud之路由网关(zuul)
  2. android studio控件使用方法,android studio使用教程
  3. html网站开发与php网站开发_海南网站开发,网站建设,商城网站,功能性网站开发...
  4. FORTRAN学习记录(持续更新)
  5. Windows Azure 之服务总线中继服务
  6. Centos7 查看/关闭/启动防火墙
  7. vue项目打包:npm run build 进程卡死
  8. php 获取路由器mac地址,php如何获取网卡MAC地址(支持WIN与LINUX系统)
  9. 表格无边框,有内框,在table嵌套时,防止出现重复边线
  10. 【three.js详解之一】入门篇
  11. 白话SpringCloud | 第三章:服务注册与发现-高可用配置(Eureka)-下
  12. 深层网络搜索核心技术研讨
  13. windows中VMWare下安装Mac Os X 10.11踩坑记
  14. 百度图片api获取(包含获取原网址)
  15. ppm/℃是什么单位?什么意思?
  16. 交换机设置环路导致网络瘫痪
  17. 一文读懂海姆达尔Heimdallr经济模型,解析链游明星的价值优势
  18. Unity3D射线检测墙面前停止移动
  19. 关于Windows Server 2012 网络发现启动不了
  20. 算法系列1《DES》

热门文章

  1. 用布尔代数简化下列各逻辑表达式
  2. mariadb数据库基本使用
  3. Python 网页爬取图片
  4. 龙芯电脑开启串口的console控制台配置
  5. 让人喷血的92条个性签名!!!
  6. 前端个人长期的学习目标
  7. 安装好vmware后界面默认英语如何修改成中文或者其他语言
  8. 计算机研究院分所烟台,综合新闻_中科院计算所烟台分所 烟台中科网络技术研究所...
  9. Linux系列之搭建云服务器入门教程
  10. photoshop之CameraRaw