android 6.0 power按键深度解析

主要分析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
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;//不分发到应用
isWakeKey = false; // wake-up will be handled separately
if (down) {
Log.i(TAG, “PowerKey down, interactive = ” + interactive);
interceptPowerKeyDown(event, interactive);//按键down
} else {
Log.i(TAG, “PowerKey up.”);
interceptPowerKeyUp(event, interactive, canceled);//按键up
}
break;
}
一、Powerkey down
我们先来看下按键down的interceptPowerKeyDown函数:
[cpp] view plain copy
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
if (!mPowerKeyWakeLock.isHeld()) {//上层持锁
mPowerKeyWakeLock.acquire();
}

// Cancel multi-press detection timeout.  
if (mPowerKeyPressCounter != 0) {//在我们的手机不支持这块,统计多次按键  
    mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);  
}  


if (!mPowerKeyHandled) {
if (interactive) {//亮屏
// When interactive, we’re already awake.
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) {//是否支持长按键
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
} else {
wakeUpFromPowerKey(event.getDownTime());

        if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
            Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
            msg.setAsynchronous(true);  
            mHandler.sendMessageDelayed(msg,  
                    ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
            mBeganFromNonInteractive = true;  
        } else {  
            final int maxCount = getMaxMultiPressPowerCount();  

            if (maxCount <= 1) {  
                mPowerKeyHandled = true;  
            } else {  
                mBeganFromNonInteractive = true;  
            }  
        }  
    }  
}  

}

1.1 亮屏 长按键处理
我们先来看看hasLongPressOnPowerBehavior函数:
[cpp] view plain copy
private boolean hasLongPressOnPowerBehavior() {
return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;//不为0
}
再来看看getResolvedLongPressOnPowerBehavior函数
[cpp] view plain copy
private int getResolvedLongPressOnPowerBehavior() {
if (FactoryTest.isLongPressOnPowerOffEnabled()) {
return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
}
return mLongPressOnPowerBehavior;
}
其中又调用了isLongPressOnPowerOffEnabled,我们没有支持这个属性。因此只要看mLongPressOnPowerBehavior这个变量
[cpp] view plain copy
public static boolean isLongPressOnPowerOffEnabled() {
return SystemProperties.getInt(“factory.long_press_power_off”, 0) != 0;
}
下面再看看mLongPressOnPowerBehavior 这个变量的初始化。
[cpp] view plain copy
mLongPressOnPowerBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
看资源apk:
[html] view plain copy
./res/values/config.xml:743: 1 也就是mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回1.
[cpp] view plain copy
if (hasLongPressOnPowerBehavior()) {
Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
然后就发消息,我们再来看处理消息:
[cpp] view plain copy
case MSG_POWER_LONG_PRESS:
powerLongPress();
再来看powerLongPress函数
[cpp] view plain copy
private void powerLongPress() {
final int behavior = getResolvedLongPressOnPowerBehavior();
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS://返回1
mPowerKeyHandled = true;
if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
performAuditoryFeedbackForAccessibilityIfNeed();
}
showGlobalActionsInternal();//下面就是弹出关机,重启之类的对话框了
break;
上面之前我们再添加长按对话框添加重启功能的那篇博客有涉及,这就是在亮屏的时候长按power的流程。

1.2 灭屏 按键down处理
下面我们再来看看,interceptPowerKeyDown的另一个分支,关于现在是灭屏的时候,按键down。
[cpp] view plain copy
else {//灭屏
wakeUpFromPowerKey(event.getDownTime());//亮屏

  if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
      Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
      msg.setAsynchronous(true);  
      mHandler.sendMessageDelayed(msg,  
              ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
      mBeganFromNonInteractive = true;  
  } else {  
      final int maxCount = getMaxMultiPressPowerCount();  

      if (maxCount <= 1) {  
          mPowerKeyHandled = true;  
      } else {  
          mBeganFromNonInteractive = true;  
      }  
  }  

第一步直接调用wakeUpFromPowerKey函数,我们看下这个函数:
[cpp] view plain copy
private void wakeUpFromPowerKey(long eventTime) {
wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, “android.policy:POWER”);//这里mAllowTheaterModeWakeFromPowerKey为true
}

private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) {
final boolean theaterModeEnabled = isTheaterModeEnabled();
if (!wakeInTheaterMode && theaterModeEnabled) {
return false;
}

if (theaterModeEnabled) {  
    Settings.Global.putInt(mContext.getContentResolver(),  
            Settings.Global.THEATER_MODE_ON, 0);  
}  

mPolicyLooper.setMessageLogging(mLogPrinter);  
mPowerManager.wakeUp(wakeTime, reason);  
return true;  

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

[cpp] view plain copy
else {//灭屏
wakeUpFromPowerKey(event.getDownTime());//亮屏

  if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {  
      Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);  
      msg.setAsynchronous(true);  
      mHandler.sendMessageDelayed(msg,  
              ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());  
      mBeganFromNonInteractive = true;  
  } else {  
      final int maxCount = getMaxMultiPressPowerCount();//返回为1,不支持多次按钮  

      if (maxCount <= 1) {  
          mPowerKeyHandled = true;//走这里  
      } else {  
          mBeganFromNonInteractive = true;  
      }  
  }  

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

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

2.1 之前power按键 down是灭屏的
我们先来看之前Power按键 down的时候手机是灭屏的情况下,下面我们分析PowerKey on的interceptPowerKeyUp函数:
[cpp] view plain copy
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;//记得之前灭屏按键down的时候,mPowerKeyHandled = true
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();

if (!handled) {  
    // Figure out how to handle the key now that it has been released.  
    mPowerKeyPressCounter += 1;  

    final int maxCount = getMaxMultiPressPowerCount();  
    final long eventTime = event.getDownTime();  
    if (mPowerKeyPressCounter < maxCount) {  
        // This could be a multi-press.  Wait a little bit longer to confirm.  
        // Continue holding the wake lock.  
        Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
                interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
        msg.setAsynchronous(true);  
        mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
        return;  
    }  

    // No other actions.  Handle it immediately.  
    powerPress(eventTime, interactive, mPowerKeyPressCounter);  
}  

// Done.  Reset our state.  
finishPowerKeyPress();  

}
之前在手机灭屏我们按power键down的时候,最后mPowerKeyHandled = true,这里handled = true,最后直接调用
[cpp] view plain copy
private void finishPowerKeyPress() {
mBeganFromNonInteractive = false;//我们手机不支持
mPowerKeyPressCounter = 0;//多按键,不支持
if (mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.release();//之前按power键down时候的锁释放
}
}

2.2 之前power按键 down是亮屏的
之前power按键 down的时候手机亮屏,power down又分为长按和短按。我们先来看之前power down亮屏,down是长按的情况下,现在是power up的情况:
[cpp] view plain copy
private void powerLongPress() {
final int behavior = getResolvedLongPressOnPowerBehavior();
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS://为1
mPowerKeyHandled = true;
if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
performAuditoryFeedbackForAccessibilityIfNeed();
}
showGlobalActionsInternal();
break;
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
break;
}
}
之前看过这函数,长按mPowerKeyHandled = true,和上面一样。直接最后interceptPowerKeyUp函数就调用finishPowerKeyPress函数了。

然后我们再来看之前powerKey Down的时候是亮屏的,又是短按的情况,我们再来看interceptPowerKeyUp函数:
[cpp] view plain copy
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;//这个实收handled为false了
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();

if (!handled) {  
    // Figure out how to handle the key now that it has been released.  
    mPowerKeyPressCounter += 1;  

    final int maxCount = getMaxMultiPressPowerCount();//这个返回为1,本来是多次按钮的。这里没有配置  
    final long eventTime = event.getDownTime();  
    if (mPowerKeyPressCounter < maxCount) {  
        // This could be a multi-press.  Wait a little bit longer to confirm.  
        // Continue holding the wake lock.  
        Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,  
                interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);  
        msg.setAsynchronous(true);  
        mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());  
        return;  
    }  

    // No other actions.  Handle it immediately.  
    powerPress(eventTime, interactive, mPowerKeyPressCounter);  
}  

// Done.  Reset our state.  
finishPowerKeyPress();  

}
我们先看看getMaxMultiPressPowerCount函数:
[cpp] view plain copy
private int getMaxMultiPressPowerCount() {
if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {// 为0
return 3;
}
if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {//为0
return 2;
}
return 1;
}
最后这个函数返回为1,因此上面函数就直接调用powerPress函数了。
[cpp] view plain copy
private void powerPress(long eventTime, boolean interactive, int count) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, “Suppressed redundant power key press while ”
+ “already in the process of turning the screen on.”);
return;
}

if (count == 2) {  
    powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);  
} else if (count == 3) {  
    powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);  
} else if (interactive && !mBeganFromNonInteractive) {//之前我们只支持1,必须亮屏,另一个参数这里为false  
    switch (mShortPressOnPowerBehavior) {// 这个参数也是资源apk中配置的,为1  
        case SHORT_PRESS_POWER_NOTHING:  
            break;  
        case SHORT_PRESS_POWER_GO_TO_SLEEP://直接调用PowerManager的goToSleep函数了  
            mPowerManager.goToSleep(eventTime,  
                    PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);  
            break;  
        case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:  
            mPowerManager.goToSleep(eventTime,  
                    PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
            break;  
        case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:  
            mPowerManager.goToSleep(eventTime,  
                    PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,  
                    PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);  
            launchHomeFromHotKey();  
            break;  
        case SHORT_PRESS_POWER_GO_HOME:  
            launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);  
            break;  
    }  
}  

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

三、总结
这篇博客我们主要分析了,power按键在PhoneWindowManager的处理。
power按键down:
1.down又分长按亮屏 弹出关闭重启对话框
2. 短按灭屏 调用wakeup
power按键on:
1.之前down的时候亮屏短按才会调用goToSleep
2.之前down的时候亮屏长按不作处理
3.之前down的时候灭屏不作处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值