Power按键流程分析

从InputManagerService分析我们知道,当按下手机的Power键之后,按键事件会传到InputDispatcher 的notifyKey 方法,然后调用到调用了NativeInputManager的interceptKeyBeforeQueueing函数,最终在这个函数中会调用到PhoneWindowManager中的interceptKeyBeforeQueueing函数,以上主要属于InputManagerService的范畴,Power按键流程我们从PhoneWindowManager 的interceptKeyBeforeQueueing 方法开始分析。

方法interceptKeyBeforeQueueing关键步骤:

第一步:初始化关键变量

[java]  view plain  copy
  1. if (!mSystemBooted) {  
  2.             return 0;  
  3.         }  
  4.   
  5.         final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;  
  6.         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;  
  7.         final boolean canceled = event.isCanceled();  
  8.         final int keyCode = event.getKeyCode();  
  9.   
  10.         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;  

首先判断系统是否启动完成,然后就是初始化一些关键变量

Interactive 表示屏幕是否点亮,这个变量表示PowerManagerService关于屏幕的状态

Down 表示是否是ActionDown事件

Canceled 事件是否取消

keyCode 按键编码

第二步,根据interative的状态的处理一些基本逻辑

[java]  view plain  copy
  1. if (interactive || (isInjected && !isWakeKey)) {  
  2.             //事件传递给用户  
  3.             result = ACTION_PASS_TO_USER;  
  4.             isWakeKey = false;  
  5.         } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {  
  6.             result = ACTION_PASS_TO_USER;  
  7.         } else {  
  8.               
  9.             result = 0;  
  10.             if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {  
  11.                 isWakeKey = false;  
  12.             }  
  13.         }  
  14.         if (isValidGlobalKey(keyCode)  
  15.                 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {  
  16.             if (isWakeKey) {  
  17.                 //直接唤醒系统  
  18.                 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, " android.policy:KEY");  
  19.             }  
  20.             return result;  
  21.         }  

第三步,处理Power按键的事件

[java]  view plain  copy
  1. case KeyEvent.KEYCODE_POWER: {  
  2.                 result &= ~ACTION_PASS_TO_USER;  
  3.                 isWakeKey = false// wake-up will be handled separately  
  4.                 if (down) {  
  5.                     Power键按下  
  6.                     interceptPowerKeyDown(event, interactive);  
  7.                 } else {  
  8.                     Power键释放  
  9.                     interceptPowerKeyUp(event, interactive, canceled);  
  10.                 }  
  11.                 break;  
  12.             }  

首先是Power按键的事件的话,不再分发到应用,如果是ActionDown事件执行InterceptPowerKeyDown()方法,如果是ActionUP事件则执行InterceptPowerKeyUp()方法

下一步继续分析interceptPowerKeyDown方法

[java]  view plain  copy
  1. private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {  
  2.           
  3.         if (!mPowerKeyWakeLock.isHeld()) {  
  4.             mPowerKeyWakeLock.acquire();  
  5.         }  

获取Power按键的锁,直到释放Power键

……   

[java]  view plain  copy
  1. if (interactive && !mScreenshotChordPowerKeyTriggered  
  2.                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {  
  3.             mScreenshotChordPowerKeyTriggered = true;  
  4.             mScreenshotChordPowerKeyTime = event.getDownTime();  
  5.             interceptScreenshotChord();  
  6.         }  

如果当前是亮屏状态,且满足触发截屏的条件,触发截屏功能

[java]  view plain  copy
  1. TelecomManager telecomManager = getTelecommService();  
  2.         boolean hungUp = false;  
  3.         if (telecomManager != null) {  
  4.             if (telecomManager.isRinging()) {  
  5.                
  6.                 telecomManager.silenceRinger();  
  7.             } else if ((mIncallPowerBehavior  
  8.                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0  
  9.                     && telecomManager.isInCall() && interactive) {  
  10.     
  11.                 hungUp = telecomManager.endCall();  
  12.             }  
  13.         }  

如果有电话拨入,且电话铃声响起的话,这个时候按Power键,设置电话响铃静音

如果正在接听电话,且配置了Power键挂断电话的话,按Power按键挂断正在接听的电话

       ……

[java]  view plain  copy
  1. mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered  
  2.                 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;  

如果按Power按键执行了截图功能或者电话静音或者挂断电话等功能后,Power事件不在传递,表示已经消耗掉了Power事件 

[java]  view plain  copy
  1. if (!mPowerKeyHandled) {  

如果未消耗掉Power事件,继续执行此处逻辑

分为两种情况

1, 当前是亮屏状态

2, 当前是灭屏状态

[java]  view plain  copy
  1. if (interactive) {  
  2.                 //是否支持长按功能  
  3.                 if (hasLongPressOnPowerBehavior()) {  
  4.                     Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  5.                     msg.setAsynchronous(true);  
  6.                     //发送MSG_POWER_LONG_PRESS消息,有Handler来处理  
  7.                     mHandler.sendMessageDelayed(msg,  
  8.                             ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  9.                 }  
  10.             } else {  
  11.                   //当前灭屏状态,此时按Power键,先唤醒系统  
  12.                    wakeUpFromPowerKey(event.getDownTime());  
  13.                   //是否支持灭屏下的长按功能  
  14.                   if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
  15.                     Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  16.                     msg.setAsynchronous(true);  
  17.                     mHandler.sendMessageDelayed(msg,  
  18.                             ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  19.                     mBeganFromNonInteractive = true;  
  20.                 } else {  
  21.                     final int maxCount = getMaxMultiPressPowerCount();  
  22.   
  23.                     if (maxCount <= 1) {  
  24.                         mPowerKeyHandled = true;  
  25.                     } else {  
  26.                         mBeganFromNonInteractive = true;  
  27.                     }  
  28.                 }  
  29.             }  
  30.         }  
  31.     }  

当前亮屏状态

首先判断是否支持长按的行为

先来看看hasLongPressOnPowerBehavior函数

[java]  view plain  copy
  1. private boolean hasLongPressOnPowerBehavior() {  
  2.         return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;  
  3.     }  

再来看看getResolvedLongPressOnPowerBehavior函数

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

由于systemProperty中的factory.long_press_power_off" 配置为0,所以不支持灭屏长按功能,。因此只要看mLongPressOnPowerBehavior这个变量

mLongPreesOnPowerBehavior 默认配置获取为

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

config_longPressOnPowerBehavior 默认值为1,所以 mLongPressOnPowerBehavior  = 1, 最后hasLongPressOnPowerBehavior返回 true


[java]  view plain  copy
  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.                 }  

hasLongPressOnPowerBehavior返回true,则发送MSG_POWER_LONG_PRESS的Handler消息,Handler处理消息调用 powerLongPress()方法,接着我们来看下Handler处理消息的逻辑

[java]  view plain  copy
  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:  
  7.             mPowerKeyHandled = true;  
  8.             if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {  
  9.                 performAuditoryFeedbackForAccessibilityIfNeed();  
  10.             }  
  11.             showGlobalActionsInternal();  
  12.             break;  
  13.        ……  

由以上的分析指导getResolvedLongPressOnPowerBehavior的值为1,所以执行case LONG_PRESS_POWER_GLOBAL_ACTIONS,

mPowerKeyHandled的值设置为true,表示处理了PowerDown事件,showGlobalActionsInternal()方法弹出关机,重启对话框

1. 当屏幕是灭屏状态

首先执行wakeUpFromPowerKey方法,唤醒手机系统,最终调用mPowerManager.wakeUp(wakeTimereason)来唤醒手机

然后mSupportLongPressPowerWhenNonInteractive默认不支持,所以默认执行

[java]  view plain  copy
  1. final int maxCount = getMaxMultiPressPowerCount();  
  2.               if (maxCount <= 1) {  
  3.                     mPowerKeyHandled = true;  
  4.                } else {  
  5.                     mBeganFromNonInteractive = true;  
  6.                }  

[java]  view plain  copy
  1. getMaxMultiPressPowerCount() ==1,默认不支持对此按键,所以将mPowerKeyHandled设置为true,表示处理了PowerDown事件  
  2. 2,处理PowerUp事件  
  3. PowerUp事件也分为两种情况,分别对应PowerDown的亮屏和灭屏两种情况  

[java]  view plain  copy
  1. private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {  
  2.         final boolean handled = canceled || mPowerKeyHandled;  
  3.       ……  
  4.         if (!handled) {  
  5.             mPowerKeyPressCounter += 1;  
  6.             final int maxCount = getMaxMultiPressPowerCount();  
  7.             final long eventTime = event.getDownTime();  
  8.             if (mPowerKeyPressCounter < maxCount) {  
  9.                 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
  10.                         interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
  11.                 msg.setAsynchronous(true);  
  12.                 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
  13.                 return;  
  14.             }  
  15.             powerPress(eventTime, interactive, mPowerKeyPressCounter);  
  16.         }  
  17.         finishPowerKeyPress();  
  18.     }  

在灭屏的时候,和亮屏长按的时候mPowerKeyHandled最后设置为true,即handle为true,直接执行finishPowerKeyPress方法,释放mPowerKeyWakeLock

在亮屏短按的时候,handled为false,由以上分析,手机默认不支持多次按键所以maxCount为1,mPowerKeyPressCounter=1,所以直接执行powerPress方法

[java]  view plain  copy
  1. private void powerPress(long eventTime, boolean interactive, int count) {  
  2.           
  3.         if (count == 2) {  
  4.             powerMultiPressAction(eventTime, interactive,mDoublePressOnPowerBehavior);  
  5.         } else if (count == 3) {  
  6.             powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);  
  7.         } else if (interactive && !mBeganFromNonInteractive) {  
  8.             switch (mShortPressOnPowerBehavior) {  
  9.                 case SHORT_PRESS_POWER_NOTHING:  
  10.                     break;  
  11.                 case SHORT_PRESS_POWER_GO_TO_SLEEP:  
  12.                     mPowerManager.goToSleep(eventTime,  
  13.                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);  
  14.                     break;  
  15.                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:  
  16.                     mPowerManager.goToSleep(eventTime,  
  17.                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  18.                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  19.                     break;  
  20.                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:  
  21.                     mPowerManager.goToSleep(eventTime,  
  22.                             PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  23.                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  24.                     launchHomeFromHotKey();  
  25.                     break;  
  26.                 case SHORT_PRESS_POWER_GO_HOME:  
  27.                     launchHomeFromHotKey(true /* awakenFromDreams */false   
  28.                     break;  
  29.             }  
  30.         }  
  31.     }  

由于mPowerKeyPressCounter 为1,所以执行case  SHORT_PRESS_POWER_GO_TO_SLEEP,调用mPowerManager.goToSleep休眠系统

 

Power按键流程总结

Power按键

1.亮屏 down 

           长按 弹出关闭重启对话框

           短按 不做处理

   亮屏 up 

       长按 不做处理

        短按 调用goToSleep休眠系统

2. 灭屏 down

            调用wakeup 唤醒系统

     灭屏 up

            不做处理


原文地址: http://blog.csdn.net/zhenjie_chang/article/details/52512823

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值