framework中phonewindowmanager对power键的处理

转自 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 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.         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 plain  copy
  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.   
  7.     // Cancel multi-press detection timeout.  
  8.     if (mPowerKeyPressCounter != 0) {//在我们的手机不支持这块,统计多次按键  
  9.         mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);  
  10.     }  
  11. ...   
  12.     if (!mPowerKeyHandled) {  
  13.         if (interactive) {//亮屏  
  14.             // When interactive, we're already awake.  
  15.             // Wait for a long press or for the button to be released to decide what to do.  
  16.             if (hasLongPressOnPowerBehavior()) {//是否支持长按键  
  17.                 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  18.                 msg.setAsynchronous(true);  
  19.                 mHandler.sendMessageDelayed(msg,  
  20.                         ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  21.             }  
  22.         } else {  
  23.             wakeUpFromPowerKey(event.getDownTime());  
  24.   
  25.             if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
  26.                 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  27.                 msg.setAsynchronous(true);  
  28.                 mHandler.sendMessageDelayed(msg,  
  29.                         ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  30.                 mBeganFromNonInteractive = true;  
  31.             } else {  
  32.                 final int maxCount = getMaxMultiPressPowerCount();  
  33.   
  34.                 if (maxCount <= 1) {  
  35.                     mPowerKeyHandled = true;  
  36.                 } else {  
  37.                     mBeganFromNonInteractive = true;  
  38.                 }  
  39.             }  
  40.         }  
  41.     }  
  42. }  


1.1 亮屏 长按键处理

我们先来看看hasLongPressOnPowerBehavior函数:

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

再来看看getResolvedLongPressOnPowerBehavior函数

[cpp]  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. }  

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

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

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

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

看资源apk:

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

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

[cpp]  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. }  

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

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

再来看powerLongPress函数

[cpp]  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://返回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 plain  copy
  1. else {//灭屏  
  2.       wakeUpFromPowerKey(event.getDownTime());//亮屏  
  3.   
  4.       if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
  5.           Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
  6.           msg.setAsynchronous(true);  
  7.           mHandler.sendMessageDelayed(msg,  
  8.                   ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
  9.           mBeganFromNonInteractive = true;  
  10.       } else {  
  11.           final int maxCount = getMaxMultiPressPowerCount();  
  12.   
  13.           if (maxCount <= 1) {  
  14.               mPowerKeyHandled = true;  
  15.           } else {  
  16.               mBeganFromNonInteractive = true;  
  17.           }  
  18.       }  
第一步直接调用wakeUpFromPowerKey函数,我们看下这个函数:

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

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

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

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

二、PowerKey On

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


2.1 之前power按键 down是灭屏的

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

[cpp]  view plain  copy
  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.   
  7.     if (!handled) {  
  8.         // Figure out how to handle the key now that it has been released.  
  9.         mPowerKeyPressCounter += 1;  
  10.   
  11.         final int maxCount = getMaxMultiPressPowerCount();  
  12.         final long eventTime = event.getDownTime();  
  13.         if (mPowerKeyPressCounter < maxCount) {  
  14.             // This could be a multi-press.  Wait a little bit longer to confirm.  
  15.             // Continue holding the wake lock.  
  16.             Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
  17.                     interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
  18.             msg.setAsynchronous(true);  
  19.             mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
  20.             return;  
  21.         }  
  22.   
  23.         // No other actions.  Handle it immediately.  
  24.         powerPress(eventTime, interactive, mPowerKeyPressCounter);  
  25.     }  
  26.   
  27.     // Done.  Reset our state.  
  28.     finishPowerKeyPress();  
  29. }  

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

[cpp]  view plain  copy
  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 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://为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 plain  copy
  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.   
  7.     if (!handled) {  
  8.         // Figure out how to handle the key now that it has been released.  
  9.         mPowerKeyPressCounter += 1;  
  10.   
  11.         final int maxCount = getMaxMultiPressPowerCount();//这个返回为1,本来是多次按钮的。这里没有配置  
  12.         final long eventTime = event.getDownTime();  
  13.         if (mPowerKeyPressCounter < maxCount) {  
  14.             // This could be a multi-press.  Wait a little bit longer to confirm.  
  15.             // Continue holding the wake lock.  
  16.             Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
  17.                     interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
  18.             msg.setAsynchronous(true);  
  19.             mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
  20.             return;  
  21.         }  
  22.   
  23.         // No other actions.  Handle it immediately.  
  24.         powerPress(eventTime, interactive, mPowerKeyPressCounter);  
  25.     }  
  26.   
  27.     // Done.  Reset our state.  
  28.     finishPowerKeyPress();  
  29. }  
我们先看看getMaxMultiPressPowerCount函数:
[cpp]  view plain  copy
  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 plain  copy
  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.   
  8.     if (count == 2) {  
  9.         powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);  
  10.     } else if (count == 3) {  
  11.         powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);  
  12.     } else if (interactive && !mBeganFromNonInteractive) {//之前我们只支持1,必须亮屏,另一个参数这里为false  
  13.         switch (mShortPressOnPowerBehavior) {// 这个参数也是资源apk中配置的,为1  
  14.             case SHORT_PRESS_POWER_NOTHING:  
  15.                 break;  
  16.             case SHORT_PRESS_POWER_GO_TO_SLEEP://直接调用PowerManager的goToSleep函数了  
  17.                 mPowerManager.goToSleep(eventTime,  
  18.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);  
  19.                 break;  
  20.             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:  
  21.                 mPowerManager.goToSleep(eventTime,  
  22.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  23.                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  24.                 break;  
  25.             case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:  
  26.                 mPowerManager.goToSleep(eventTime,  
  27.                         PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
  28.                         PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
  29.                 launchHomeFromHotKey();  
  30.                 break;  
  31.             case SHORT_PRESS_POWER_GO_HOME:  
  32.                 launchHomeFromHotKey(true /* awakenFromDreams */false /*respectKeyguard*/);  
  33.                 break;  
  34.         }  
  35.     }  
  36. }  
因为我们没有配置多次power按钮,mShortPressOnPowerBehavior配置为1,所以就直接调用了PowerManager的goToSleep函数了。


三、总结

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

power按键down:

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

    2. 短按灭屏 调用wakeup

power按键on:

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

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

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


猜你喜欢

转载自blog.csdn.net/weixin_38451161/article/details/80204194