diff options
Diffstat (limited to 'policy/src')
-rw-r--r-- | policy/src/com/android/internal/policy/impl/GlobalKeyManager.java | 1 | ||||
-rw-r--r-- | policy/src/com/android/internal/policy/impl/PhoneWindowManager.java | 581 |
2 files changed, 415 insertions, 167 deletions
diff --git a/policy/src/com/android/internal/policy/impl/GlobalKeyManager.java b/policy/src/com/android/internal/policy/impl/GlobalKeyManager.java index 8c8209f..fc65793 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalKeyManager.java +++ b/policy/src/com/android/internal/policy/impl/GlobalKeyManager.java @@ -73,6 +73,7 @@ final class GlobalKeyManager { if (component != null) { Intent intent = new Intent(Intent.ACTION_GLOBAL_BUTTON) .setComponent(component) + .setFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(Intent.EXTRA_KEY_EVENT, event); context.sendBroadcastAsUser(intent, UserHandle.CURRENT, null); return true; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 99d5848..0ac679e 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -158,6 +158,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int LONG_PRESS_POWER_SHUT_OFF = 2; static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; + static final int MULTI_PRESS_POWER_NOTHING = 0; + static final int MULTI_PRESS_POWER_THEATER_MODE = 1; + static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; + // These need to match the documentation/constant in // core/res/res/values/config.xml static final int LONG_PRESS_HOME_NOTHING = 0; @@ -300,12 +304,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { }; GlobalActions mGlobalActions; - volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread - boolean mPendingPowerKeyUpCanceled; Handler mHandler; WindowState mLastInputMethodWindow = null; WindowState mLastInputMethodTargetWindow = null; + // FIXME This state is shared between the input reader and handler thread. + // Technically it's broken and buggy but it has been like this for many years + // and we have not yet seen any problems. Someday we'll rewrite this logic + // so that only one thread is involved in handling input policy. Unfortunately + // it's on a critical path for power management so we can't just post the work to the + // handler thread. We'll need to resolve this someday by teaching the input dispatcher + // to hold wakelocks during dispatch and eliminating the critical path. + volatile boolean mPowerKeyHandled; + volatile int mPowerKeyPressCounter; + volatile boolean mEndCallKeyHandled; + boolean mRecentsVisible; int mRecentAppsHeldModifiers; boolean mLanguageSwitchKeyPressed; @@ -345,8 +358,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidKeyboardAccessibility; int mLidNavigationAccessibility; boolean mLidControlsSleep; - int mShortPressOnPowerBehavior = -1; - int mLongPressOnPowerBehavior = -1; + int mShortPressOnPowerBehavior; + int mLongPressOnPowerBehavior; + int mDoublePressOnPowerBehavior; + int mTriplePressOnPowerBehavior; boolean mAwake; boolean mScreenOnEarly; boolean mScreenOnFully; @@ -503,18 +518,26 @@ public class PhoneWindowManager implements WindowManagerPolicy { // What we do when the user double-taps on home private int mDoubleTapOnHomeBehavior; + // Allowed theater mode wake actions + private boolean mAllowTheaterModeWakeFromKey; + private boolean mAllowTheaterModeWakeFromPowerKey; + private boolean mAllowTheaterModeWakeFromMotion; + private boolean mAllowTheaterModeWakeFromCameraLens; + private boolean mAllowTheaterModeWakeFromLidSwitch; + private boolean mAllowTheaterModeWakeFromWakeGesture; + // Screenshot trigger states // Time to volume and power must be pressed within this interval of each other. private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; // Increase the chord delay when taking a screenshot from the keyguard private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; private boolean mScreenshotChordEnabled; - private boolean mVolumeDownKeyTriggered; - private long mVolumeDownKeyTime; - private boolean mVolumeDownKeyConsumedByScreenshotChord; - private boolean mVolumeUpKeyTriggered; - private boolean mPowerKeyTriggered; - private long mPowerKeyTime; + private boolean mScreenshotChordVolumeDownKeyTriggered; + private long mScreenshotChordVolumeDownKeyTime; + private boolean mScreenshotChordVolumeDownKeyConsumed; + private boolean mScreenshotChordVolumeUpKeyTriggered; + private boolean mScreenshotChordPowerKeyTriggered; + private long mScreenshotChordPowerKeyTime; /* The number of steps between min and max brightness */ private static final int BRIGHTNESS_STEPS = 10; @@ -522,6 +545,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { SettingsObserver mSettingsObserver; ShortcutManager mShortcutManager; PowerManager.WakeLock mBroadcastWakeLock; + PowerManager.WakeLock mPowerKeyWakeLock; boolean mHavePendingMediaKeyRepeatWithWakeLock; private int mCurrentUserId; @@ -547,6 +571,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10; private static final int MSG_HIDE_BOOT_MESSAGE = 11; private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; + private static final int MSG_POWER_DELAYED_PRESS = 13; + private static final int MSG_POWER_LONG_PRESS = 14; private class PolicyHandler extends Handler { @Override @@ -588,6 +614,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: launchVoiceAssistWithWakeLock(msg.arg1 != 0); break; + case MSG_POWER_DELAYED_PRESS: + powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2); + finishPowerKeyPress(); + break; + case MSG_POWER_LONG_PRESS: + powerLongPress(); + break; } } } @@ -656,7 +689,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { synchronized (mLock) { if (shouldEnableWakeGestureLp()) { performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); - mPowerManager.wakeUp(SystemClock.uptimeMillis()); + wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture); } } } @@ -781,38 +814,239 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void interceptPowerKeyDown(boolean handled) { - mPowerKeyHandled = handled; + 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); + } + + // Detect user pressing the power button in panic when an application has + // taken over the whole screen. + boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive, + event.getDownTime(), isImmersiveMode(mLastSystemUiFlags)); + if (panic) { + mHandler.post(mRequestTransientNav); + } + + // Latch power key state to detect screenshot chord. + if (interactive && !mScreenshotChordPowerKeyTriggered + && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { + mScreenshotChordPowerKeyTriggered = true; + mScreenshotChordPowerKeyTime = event.getDownTime(); + interceptScreenshotChord(); + } + + // Stop ringing or end call if configured to do so when power is pressed. + TelecomManager telecomManager = getTelecommService(); + boolean hungUp = false; + if (telecomManager != null) { + if (telecomManager.isRinging()) { + // Pressing Power while there's a ringing incoming + // call should silence the ringer. + telecomManager.silenceRinger(); + } else if ((mIncallPowerBehavior + & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 + && telecomManager.isInCall() && interactive) { + // Otherwise, if "Power button ends call" is enabled, + // the Power button will hang up any current active call. + hungUp = telecomManager.endCall(); + } + } + + // If the power key has still not yet been handled, then detect short + // press, long press, or multi press and decide what to do. + mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered + || mScreenshotChordVolumeUpKeyTriggered; + 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 { + // When non-interactive, we ordinarily wake up immediately and + // consume the key. However on some devices we need to support multi-press + // without waking so we will delay handling for later in that case + // (at the cost of increased latency). + final int maxCount = getMaxMultiPressPowerCount(); + if (maxCount <= 1) { + // No other actions. We can wake immediately. + wakeUpFromPowerKey(event.getDownTime()); + mPowerKeyHandled = true; + } + } + } + } + + private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { + final boolean handled = canceled || mPowerKeyHandled; + mScreenshotChordPowerKeyTriggered = false; + cancelPendingScreenshotChordAction(); + cancelPendingPowerKeyAction(); + if (!handled) { - mHandler.postDelayed(mPowerLongPress, - ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); + // 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(); } - private boolean interceptPowerKeyUp(boolean canceled) { - if (!mPowerKeyHandled) { - mHandler.removeCallbacks(mPowerLongPress); - return !canceled; + private void finishPowerKeyPress() { + mPowerKeyPressCounter = 0; + if (mPowerKeyWakeLock.isHeld()) { + mPowerKeyWakeLock.release(); } - return false; } private void cancelPendingPowerKeyAction() { if (!mPowerKeyHandled) { - mHandler.removeCallbacks(mPowerLongPress); + mPowerKeyHandled = true; + mHandler.removeMessages(MSG_POWER_LONG_PRESS); } - if (mPowerKeyTriggered) { - mPendingPowerKeyUpCanceled = true; + } + + 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) { + wakeUpFromPowerKey(eventTime); + } else { + 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; + } + } + } + + private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) { + switch (behavior) { + case MULTI_PRESS_POWER_NOTHING: + break; + case MULTI_PRESS_POWER_THEATER_MODE: + if (isTheaterModeEnabled()) { + Slog.i(TAG, "Toggling theater mode off."); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.THEATER_MODE_ON, 0); + if (!interactive) { + wakeUpFromPowerKey(eventTime); + } + } else { + Slog.i(TAG, "Toggling theater mode on."); + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.THEATER_MODE_ON, 1); + if (interactive) { + mPowerManager.goToSleep(eventTime, + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); + } + } + break; + case MULTI_PRESS_POWER_BRIGHTNESS_BOOST: + mPowerManager.boostScreenBrightness(eventTime); + break; + } + } + + private int getMaxMultiPressPowerCount() { + if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { + return 3; + } + if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { + return 2; + } + return 1; + } + + 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; + } + } + + private int getResolvedLongPressOnPowerBehavior() { + if (FactoryTest.isLongPressOnPowerOffEnabled()) { + return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; + } + return mLongPressOnPowerBehavior; + } + + private boolean hasLongPressOnPowerBehavior() { + return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING; } private void interceptScreenshotChord() { if (mScreenshotChordEnabled - && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) { + && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered + && !mScreenshotChordVolumeUpKeyTriggered) { final long now = SystemClock.uptimeMillis(); - if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS - && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { - mVolumeDownKeyConsumedByScreenshotChord = true; + if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS + && now <= mScreenshotChordPowerKeyTime + + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { + mScreenshotChordVolumeDownKeyConsumed = true; cancelPendingPowerKeyAction(); mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay()); @@ -833,64 +1067,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHandler.removeCallbacks(mScreenshotRunnable); } - private void powerShortPress(long eventTime) { - if (mShortPressOnPowerBehavior < 0) { - mShortPressOnPowerBehavior = mContext.getResources().getInteger( - com.android.internal.R.integer.config_shortPressOnPowerBehavior); - } - - 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; - } - } - - private final Runnable mPowerLongPress = new Runnable() { + private final Runnable mEndCallLongPress = new Runnable() { @Override public void run() { - // The context isn't read - if (mLongPressOnPowerBehavior < 0) { - mLongPressOnPowerBehavior = mContext.getResources().getInteger( - com.android.internal.R.integer.config_longPressOnPowerBehavior); - } - int resolvedBehavior = mLongPressOnPowerBehavior; - if (FactoryTest.isLongPressOnPowerOffEnabled()) { - resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; - } - - switch (resolvedBehavior) { - 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(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF); - break; + mEndCallKeyHandled = true; + if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { + performAuditoryFeedbackForAccessibilityIfNeed(); } + showGlobalActionsInternal(); } }; @@ -931,6 +1115,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; } + private void handleShortPressOnHome() { + // If there's a dream running then use home to escape the dream + // but don't actually go home. + if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) { + mDreamManagerInternal.stopDream(false /*immediate*/); + return; + } + + // Go home! + launchHomeFromHotKey(); + } + private void handleLongPressOnHome() { if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) { mHomeConsumed = true; @@ -956,7 +1152,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void run() { if (mHomeDoubleTapPending) { mHomeDoubleTapPending = false; - launchHomeFromHotKey(); + handleShortPressOnHome(); } } }; @@ -999,6 +1195,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PhoneWindowManager.mBroadcastWakeLock"); + mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "PhoneWindowManager.mPowerKeyWakeLock"); mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable")); mSupportAutoRotation = mContext.getResources().getBoolean( com.android.internal.R.bool.config_supportAutoRotation); @@ -1022,6 +1220,30 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.bool.config_lidControlsSleep); mTranslucentDecorEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_enableTranslucentDecor); + + mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); + mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey + || mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey); + mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion); + mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens); + mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch); + mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture); + + mShortPressOnPowerBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_shortPressOnPowerBehavior); + mLongPressOnPowerBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior); + mDoublePressOnPowerBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_doublePressOnPowerBehavior); + mTriplePressOnPowerBehavior = mContext.getResources().getInteger( + com.android.internal.R.integer.config_triplePressOnPowerBehavior); + readConfigurationDependentBehaviors(); mAccessibilityManager = (AccessibilityManager) context.getSystemService( @@ -2164,17 +2386,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { // but we're not sure, then tell the dispatcher to wait a little while and // try again later before dispatching. if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { - if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) { + if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) { final long now = SystemClock.uptimeMillis(); - final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; + final long timeoutTime = mScreenshotChordVolumeDownKeyTime + + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; if (now < timeoutTime) { return timeoutTime - now; } } if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - && mVolumeDownKeyConsumedByScreenshotChord) { + && mScreenshotChordVolumeDownKeyConsumed) { if (!down) { - mVolumeDownKeyConsumedByScreenshotChord = false; + mScreenshotChordVolumeDownKeyConsumed = false; } return -1; } @@ -2226,15 +2449,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return -1; } - // If there's a dream running then use home to escape the dream - // but don't actually go home. - if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) { - mDreamManagerInternal.stopDream(false /*immediate*/); - return -1; - } - - // Go home! - launchHomeFromHotKey(); + handleShortPressOnHome(); return -1; } @@ -2508,7 +2723,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { return -1; } - if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { + if (isValidGlobalKey(keyCode) + && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { return -1; } @@ -4071,7 +4287,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateRotation(true); if (lidOpen) { - mPowerManager.wakeUp(SystemClock.uptimeMillis()); + wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch); } else if (!mLidControlsSleep) { mPowerManager.userActivity(SystemClock.uptimeMillis(), false); } @@ -4093,7 +4309,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else { intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); } - mPowerManager.wakeUp(whenNanos / 1000000); + wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens); mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); } mCameraLensCoverState = lensCoverState; @@ -4269,9 +4485,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // If the key would be handled globally, just return the result, don't worry about special // key processing. - if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { + if (isValidGlobalKey(keyCode) + && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { if (isWakeKey) { - mPowerManager.wakeUp(event.getEventTime()); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey); } return result; } @@ -4287,28 +4504,28 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_VOLUME_MUTE: { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if (down) { - if (interactive && !mVolumeDownKeyTriggered + if (interactive && !mScreenshotChordVolumeDownKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { - mVolumeDownKeyTriggered = true; - mVolumeDownKeyTime = event.getDownTime(); - mVolumeDownKeyConsumedByScreenshotChord = false; + mScreenshotChordVolumeDownKeyTriggered = true; + mScreenshotChordVolumeDownKeyTime = event.getDownTime(); + mScreenshotChordVolumeDownKeyConsumed = false; cancelPendingPowerKeyAction(); interceptScreenshotChord(); } } else { - mVolumeDownKeyTriggered = false; + mScreenshotChordVolumeDownKeyTriggered = false; cancelPendingScreenshotChordAction(); } } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { if (down) { - if (interactive && !mVolumeUpKeyTriggered + if (interactive && !mScreenshotChordVolumeUpKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { - mVolumeUpKeyTriggered = true; + mScreenshotChordVolumeUpKeyTriggered = true; cancelPendingPowerKeyAction(); cancelPendingScreenshotChordAction(); } } else { - mVolumeUpKeyTriggered = false; + mScreenshotChordVolumeUpKeyTriggered = false; cancelPendingScreenshotChordAction(); } } @@ -4365,20 +4582,29 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (telecomManager != null) { hungUp = telecomManager.endCall(); } - interceptPowerKeyDown(!interactive || hungUp); + if (interactive && !hungUp) { + mEndCallKeyHandled = false; + mHandler.postDelayed(mEndCallLongPress, + ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); + } else { + mEndCallKeyHandled = true; + } } else { - if (interceptPowerKeyUp(canceled)) { - if ((mEndcallBehavior - & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { - if (goHome()) { - break; + if (!mEndCallKeyHandled) { + mHandler.removeCallbacks(mEndCallLongPress); + if (!canceled) { + if ((mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { + if (goHome()) { + break; + } + } + if ((mEndcallBehavior + & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { + mPowerManager.goToSleep(event.getEventTime(), + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); + isWakeKey = false; } - } - if ((mEndcallBehavior - & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { - mPowerManager.goToSleep(event.getEventTime(), - PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); - isWakeKey = false; } } } @@ -4387,49 +4613,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_POWER: { result &= ~ACTION_PASS_TO_USER; + isWakeKey = false; // wake-up will be handled separately if (down) { - boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive, - event.getDownTime(), isImmersiveMode(mLastSystemUiFlags)); - if (panic) { - mHandler.post(mRequestTransientNav); - } - if (interactive && !mPowerKeyTriggered - && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { - mPowerKeyTriggered = true; - mPowerKeyTime = event.getDownTime(); - interceptScreenshotChord(); - } - - TelecomManager telecomManager = getTelecommService(); - boolean hungUp = false; - if (telecomManager != null) { - if (telecomManager.isRinging()) { - // Pressing Power while there's a ringing incoming - // call should silence the ringer. - telecomManager.silenceRinger(); - } else if ((mIncallPowerBehavior - & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 - && telecomManager.isInCall() && interactive) { - // Otherwise, if "Power button ends call" is enabled, - // the Power button will hang up any current active call. - hungUp = telecomManager.endCall(); - } - } - interceptPowerKeyDown(!interactive || hungUp - || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered); + interceptPowerKeyDown(event, interactive); } else { - mPowerKeyTriggered = false; - cancelPendingScreenshotChordAction(); - if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { - if (mScreenOnEarly && !mScreenOnFully) { - Slog.i(TAG, "Suppressed redundant power key press while " - + "already in the process of turning the screen on."); - } else { - powerShortPress(event.getEventTime()); - } - isWakeKey = false; - } - mPendingPowerKeyUpCanceled = false; + interceptPowerKeyUp(event, interactive, canceled); } break; } @@ -4520,12 +4708,29 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (isWakeKey) { - mPowerManager.wakeUp(event.getEventTime()); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey); } + return result; } /** + * Returns true if the key can have global actions attached to it. + * We reserve all power management keys for the system since they require + * very careful handling. + */ + private static boolean isValidGlobalKey(int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_POWER: + case KeyEvent.KEYCODE_WAKEUP: + case KeyEvent.KEYCODE_SLEEP: + return false; + default: + return true; + } + } + + /** * When the screen is off we ignore some keys that might otherwise typically * be considered wake keys. We filter them out here. * @@ -4564,18 +4769,39 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { if ((policyFlags & FLAG_WAKE) != 0) { - mPowerManager.wakeUp(whenNanos / 1000000); - return 0; + if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) { + return 0; + } } + if (shouldDispatchInputWhenNonInteractive()) { return ACTION_PASS_TO_USER; } + return 0; } private boolean shouldDispatchInputWhenNonInteractive() { - return keyguardIsShowingTq() && mDisplay != null && - mDisplay.getState() != Display.STATE_OFF; + // Send events to keyguard while the screen is on. + if (keyguardIsShowingTq() && mDisplay != null && mDisplay.getState() != Display.STATE_OFF) { + return true; + } + + // Send events to a dozing dream even if the screen is off since the dream + // is in control of the state of the screen. + IDreamManager dreamManager = getDreamManager(); + + try { + if (dreamManager != null && dreamManager.isDreaming()) { + return true; + } + } catch (RemoteException e) { + Slog.e(TAG, "RemoteException when checking if dreaming", e); + } + + // Otherwise, consume events since the user can't see what is being + // interacted with. + return false; } void dispatchMediaKeyWithWakeLock(KeyEvent event) { @@ -4742,6 +4968,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void wakeUpFromPowerKey(long eventTime) { + wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey); + } + + private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) { + if (!wakeInTheaterMode && isTheaterModeEnabled()) { + return false; + } + + mPowerManager.wakeUp(wakeTime); + return true; + } + // Called on the PowerManager's Notifier thread. @Override public void wakingUp() { @@ -5620,6 +5859,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { ringTone.play(); } + private boolean isTheaterModeEnabled() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.THEATER_MODE_ON, 0) == 1; + } + private boolean isGlobalAccessibilityGestureEnabled() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; @@ -5943,6 +6187,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(prefix); pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); + pw.print(prefix); + pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); + pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); |