转自 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关于屏幕的状态。
- case KeyEvent.KEYCODE_POWER: {
- result &= ~ACTION_PASS_TO_USER;
- isWakeKey = false;
- if (down) {
- Log.i(TAG, "PowerKey down, interactive = " + interactive);
- interceptPowerKeyDown(event, interactive);
- } else {
- Log.i(TAG, "PowerKey up.");
- interceptPowerKeyUp(event, interactive, canceled);
- }
- break;
- }
一、Powerkey down
我们先来看下按键down的interceptPowerKeyDown函数:
- private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
-
- if (!mPowerKeyWakeLock.isHeld()) {
- mPowerKeyWakeLock.acquire();
- }
-
-
- if (mPowerKeyPressCounter != 0) {
- mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
- }
- ...
- if (!mPowerKeyHandled) {
- if (interactive) {
-
-
- 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函数:
- private boolean hasLongPressOnPowerBehavior() {
- return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
- }
再来看看getResolvedLongPressOnPowerBehavior函数
- private int getResolvedLongPressOnPowerBehavior() {
- if (FactoryTest.isLongPressOnPowerOffEnabled()) {
- return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
- }
- return mLongPressOnPowerBehavior;
- }
其中又调用了isLongPressOnPowerOffEnabled,我们没有支持这个属性。因此只要看mLongPressOnPowerBehavior这个变量
- public static boolean isLongPressOnPowerOffEnabled() {
- return SystemProperties.getInt("factory.long_press_power_off", 0) != 0;
- }
下面再看看mLongPressOnPowerBehavior 这个变量的初始化。
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
看资源apk:
- ./res/values/config.xml:743: <integer name="config_longPressOnPowerBehavior">1</integer
也就是mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回1.
- if (hasLongPressOnPowerBehavior()) {
- Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg,
- ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
- }
然后就发消息,我们再来看处理消息:
- case MSG_POWER_LONG_PRESS:
- powerLongPress();
再来看powerLongPress函数
- private void powerLongPress() {
- final int behavior = getResolvedLongPressOnPowerBehavior();
- switch (behavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- mPowerKeyHandled = true;
- if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
- performAuditoryFeedbackForAccessibilityIfNeed();
- }
- showGlobalActionsInternal();
- break;
上面之前我们再添加长按对话框添加重启功能的那篇博客有涉及,这就是在亮屏的时候长按power的流程。
1.2 灭屏 按键down处理
下面我们再来看看,interceptPowerKeyDown的另一个分支,关于现在是灭屏的时候,按键down。
- 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函数,我们看下这个函数:
- private void wakeUpFromPowerKey(long eventTime) {
- wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");
- }
-
- 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"
- 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;
- }
- }
而下面mSupportLongPressPowerWhenNonInteractive 我们配置也是false不支持。多按钮也不支持,因此maxCount为1
二、PowerKey On
PowerKey on 又分为之前down的时候是灭屏还是亮屏处理的,逻辑又不一样。
2.1 之前power按键 down是灭屏的
我们先来看之前Power按键 down的时候手机是灭屏的情况下,下面我们分析PowerKey on的interceptPowerKeyUp函数:
- private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
- final boolean handled = canceled || mPowerKeyHandled;
- mScreenshotChordPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- cancelPendingPowerKeyAction();
-
- if (!handled) {
-
- mPowerKeyPressCounter += 1;
-
- final int maxCount = getMaxMultiPressPowerCount();
- final long eventTime = event.getDownTime();
- if (mPowerKeyPressCounter < maxCount) {
-
-
- Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
- interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
- return;
- }
-
-
- powerPress(eventTime, interactive, mPowerKeyPressCounter);
- }
-
-
- finishPowerKeyPress();
- }
之前在手机灭屏我们按power键down的时候,最后mPowerKeyHandled = true,这里handled = true,最后直接调用
- private void finishPowerKeyPress() {
- mBeganFromNonInteractive = false;
- mPowerKeyPressCounter = 0;
- if (mPowerKeyWakeLock.isHeld()) {
- mPowerKeyWakeLock.release();
- }
- }
2.2 之前power按键 down是亮屏的
之前power按键 down的时候手机亮屏,power down又分为长按和短按。我们先来看之前power down亮屏,down是长按的情况下,现在是power up的情况:
- private void powerLongPress() {
- final int behavior = getResolvedLongPressOnPowerBehavior();
- switch (behavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- 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函数:
- private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
- final boolean handled = canceled || mPowerKeyHandled;
- mScreenshotChordPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- cancelPendingPowerKeyAction();
-
- if (!handled) {
-
- mPowerKeyPressCounter += 1;
-
- final int maxCount = getMaxMultiPressPowerCount();
- final long eventTime = event.getDownTime();
- if (mPowerKeyPressCounter < maxCount) {
-
-
- Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
- interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
- msg.setAsynchronous(true);
- mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
- return;
- }
-
-
- powerPress(eventTime, interactive, mPowerKeyPressCounter);
- }
-
-
- finishPowerKeyPress();
- }
我们先看看getMaxMultiPressPowerCount函数:
- private int getMaxMultiPressPowerCount() {
- if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
- return 3;
- }
- if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
- return 2;
- }
- return 1;
- }
最后这个函数返回为1,因此上面函数就直接调用powerPress函数了。
- 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) {
- switch (mShortPressOnPowerBehavior) {
- case SHORT_PRESS_POWER_NOTHING:
- break;
- case SHORT_PRESS_POWER_GO_TO_SLEEP:
- 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 , false );
- break;
- }
- }
- }
因为我们没有配置多次power按钮,mShortPressOnPowerBehavior配置为1,所以就直接调用了PowerManager的goToSleep函数了。
三、总结
这篇博客我们主要分析了,power按键在PhoneWindowManager的处理。
power按键down:
1.down又分长按亮屏 弹出关闭重启对话框
2. 短按灭屏 调用wakeup
power按键on:
1.之前down的时候亮屏短按才会调用goToSleep
2.之前down的时候亮屏长按不作处理
3.之前down的时候灭屏不作处理