diff options
| -rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 312 |
1 files changed, 189 insertions, 123 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 1dae396af76d..97af04524d5a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -41,6 +41,7 @@ import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.O; import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.STATE_OFF; import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; @@ -155,6 +156,7 @@ import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerInternal; +import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.AppOpsManager; @@ -665,9 +667,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { SleepToken mDreamingSleepToken; SleepToken mScreenOffSleepToken; volatile boolean mKeyguardOccluded; - boolean mHomePressed; - boolean mHomeConsumed; - boolean mHomeDoubleTapPending; Intent mHomeIntent; Intent mCarDockIntent; Intent mDeskDockIntent; @@ -865,7 +864,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { launchVoiceAssistWithWakeLock(); break; case MSG_POWER_DELAYED_PRESS: - powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2); + powerPress((Long) msg.obj, msg.arg1 != 0, msg.arg2); finishPowerKeyPress(); break; case MSG_POWER_LONG_PRESS: @@ -1340,7 +1339,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME: goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); - launchHomeFromHotKey(); + launchHomeFromHotKey(DEFAULT_DISPLAY); break; case SHORT_PRESS_POWER_GO_HOME: shortPressPowerGoHome(); @@ -1369,7 +1368,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void shortPressPowerGoHome() { - launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/); + launchHomeFromHotKey(DEFAULT_DISPLAY, true /* awakenFromDreams */, + false /*respectKeyguard*/); if (isKeyguardShowingAndNotOccluded()) { // Notify keyguard so it can do any special handling for the power button since the // device will not power off and only launch home. @@ -1505,7 +1505,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void sleepPress() { if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) { - launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/); + launchHomeFromHotKey(DEFAULT_DISPLAY, false /* awakenDreams */, + true /*respectKeyguard*/); } } @@ -1683,7 +1684,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; } - private void handleShortPressOnHome() { + private void handleShortPressOnHome(int displayId) { // Turn on the connected TV and switch HDMI input if we're a HDMI playback device. final HdmiControl hdmiControl = getHdmiControl(); if (hdmiControl != null) { @@ -1698,7 +1699,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Go home! - launchHomeFromHotKey(); + launchHomeFromHotKey(displayId); } /** @@ -1745,26 +1746,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void handleLongPressOnHome(int deviceId) { - if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) { - return; - } - mHomeConsumed = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, - "Home - Long Press"); - switch (mLongPressOnHomeBehavior) { - case LONG_PRESS_HOME_ALL_APPS: - launchAllAppsAction(); - break; - case LONG_PRESS_HOME_ASSIST: - launchAssistAction(null, deviceId); - break; - default: - Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior); - break; - } - } - private void launchAllAppsAction() { Intent intent = new Intent(Intent.ACTION_ALL_APPS); if (mHasFeatureLeanback) { @@ -1781,13 +1762,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { startActivityAsUser(intent, UserHandle.CURRENT); } - private void handleDoubleTapOnHome() { - if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { - mHomeConsumed = true; - toggleRecentApps(); - } - } - private void showPictureInPictureMenu(KeyEvent event) { if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event); mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU); @@ -1803,15 +1777,147 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() { - @Override - public void run() { - if (mHomeDoubleTapPending) { - mHomeDoubleTapPending = false; - handleShortPressOnHome(); + /** A handler to handle home keys per display */ + private class DisplayHomeButtonHandler { + + private final int mDisplayId; + + private boolean mHomeDoubleTapPending; + private boolean mHomePressed; + private boolean mHomeConsumed; + + private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() { + @Override + public void run() { + if (mHomeDoubleTapPending) { + mHomeDoubleTapPending = false; + handleShortPressOnHome(mDisplayId); + } } + }; + + DisplayHomeButtonHandler(int displayId) { + mDisplayId = displayId; } - }; + + int handleHomeButton(WindowState win, KeyEvent event) { + final boolean keyguardOn = keyguardOn(); + final int repeatCount = event.getRepeatCount(); + final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; + final boolean canceled = event.isCanceled(); + + if (DEBUG_INPUT) { + Log.d(TAG, String.format("handleHomeButton in display#%d mHomePressed = %b", + mDisplayId, mHomePressed)); + } + + // If we have released the home key, and didn't do anything else + // while it was pressed, then it is time to go home! + if (!down) { + if (mDisplayId == DEFAULT_DISPLAY) { + cancelPreloadRecentApps(); + } + + mHomePressed = false; + if (mHomeConsumed) { + mHomeConsumed = false; + return -1; + } + + if (canceled) { + Log.i(TAG, "Ignoring HOME; event canceled."); + return -1; + } + + // Delay handling home if a double-tap is possible. + if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { + mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case + mHomeDoubleTapPending = true; + mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, + ViewConfiguration.getDoubleTapTimeout()); + return -1; + } + + handleShortPressOnHome(mDisplayId); + return -1; + } + + // If a system window has focus, then it doesn't make sense + // right now to interact with applications. + WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; + if (attrs != null) { + final int type = attrs.type; + if (type == TYPE_KEYGUARD_DIALOG + || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + // the "app" is keyguard, so give it the key + return 0; + } + for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) { + if (type == t) { + // don't do anything, but also don't pass it to the app + return -1; + } + } + } + + // Remember that home is pressed and handle special actions. + if (repeatCount == 0) { + mHomePressed = true; + if (mHomeDoubleTapPending) { + mHomeDoubleTapPending = false; + mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); + handleDoubleTapOnHome(); + // TODO(multi-display): Remove display id check once we support recents on + // multi-display + } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI + && mDisplayId == DEFAULT_DISPLAY) { + preloadRecentApps(); + } + } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { + if (!keyguardOn) { + handleLongPressOnHome(event.getDeviceId()); + } + } + return -1; + } + + private void handleDoubleTapOnHome() { + if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { + mHomeConsumed = true; + toggleRecentApps(); + } + } + + private void handleLongPressOnHome(int deviceId) { + if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) { + return; + } + mHomeConsumed = true; + performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + "Home - Long Press"); + switch (mLongPressOnHomeBehavior) { + case LONG_PRESS_HOME_ALL_APPS: + launchAllAppsAction(); + break; + case LONG_PRESS_HOME_ASSIST: + launchAssistAction(null, deviceId); + break; + default: + Log.w(TAG, "Undefined home long press behavior: " + + mLongPressOnHomeBehavior); + break; + } + } + + @Override + public String toString() { + return String.format("mDisplayId = %d, mHomePressed = %b", mDisplayId, mHomePressed); + } + } + + /** A DisplayHomeButtonHandler map indexed by display id */ + private final SparseArray<DisplayHomeButtonHandler> mDisplayHomeButtonHandlers = + new SparseArray<>(); private boolean isRoundWindow() { return mContext.getResources().getConfiguration().isScreenRound(); @@ -3259,6 +3365,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, }; + // TODO(b/117479243): handle it in InputPolicy /** {@inheritDoc} */ @Override public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { @@ -3269,11 +3376,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int flags = event.getFlags(); final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); + final int displayId = event.getDisplayId(); if (DEBUG_INPUT) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" - + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed - + " canceled=" + canceled); + + repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled); } // If we think we might have a volume down & power key chord on the way @@ -3358,71 +3465,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { // it handle it, because that gives us the correct 5 second // timeout. if (keyCode == KeyEvent.KEYCODE_HOME) { - - // If we have released the home key, and didn't do anything else - // while it was pressed, then it is time to go home! - if (!down) { - cancelPreloadRecentApps(); - - mHomePressed = false; - if (mHomeConsumed) { - mHomeConsumed = false; - return -1; - } - - if (canceled) { - Log.i(TAG, "Ignoring HOME; event canceled."); - return -1; - } - - // Delay handling home if a double-tap is possible. - if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { - mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case - mHomeDoubleTapPending = true; - mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, - ViewConfiguration.getDoubleTapTimeout()); - return -1; - } - - handleShortPressOnHome(); - return -1; - } - - // If a system window has focus, then it doesn't make sense - // right now to interact with applications. - WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; - if (attrs != null) { - final int type = attrs.type; - if (type == TYPE_KEYGUARD_DIALOG - || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { - // the "app" is keyguard, so give it the key - return 0; - } - final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; - for (int i=0; i<typeCount; i++) { - if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { - // don't do anything, but also don't pass it to the app - return -1; - } - } - } - - // Remember that home is pressed and handle special actions. - if (repeatCount == 0) { - mHomePressed = true; - if (mHomeDoubleTapPending) { - mHomeDoubleTapPending = false; - mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); - handleDoubleTapOnHome(); - } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { - preloadRecentApps(); - } - } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { - if (!keyguardOn) { - handleLongPressOnHome(event.getDeviceId()); - } + DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(displayId); + if (handler == null) { + handler = new DisplayHomeButtonHandler(displayId); + mDisplayHomeButtonHandlers.put(displayId, handler); } - return -1; + return handler.handleHomeButton(win, event); } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Hijack modified menu keys for debugging features final int chordBug = KeyEvent.META_SHIFT_ON; @@ -3820,6 +3868,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // TODO(b/117479243): handle it in InputPolicy /** {@inheritDoc} */ @Override public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { @@ -3862,7 +3911,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { event.getAction(), fallbackAction.keyCode, event.getRepeatCount(), fallbackAction.metaState, event.getDeviceId(), event.getScanCode(), - flags, event.getSource(), null); + flags, event.getSource(), event.getDisplayId(), null); if (!interceptFallback(win, fallbackEvent, policyFlags)) { fallbackEvent.recycle(); @@ -3991,8 +4040,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void startActivityAsUser(Intent intent, UserHandle handle) { + startActivityAsUser(intent, null, handle); + } + + private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle) { if (isUserSetupComplete()) { - mContext.startActivityAsUser(intent, handle); + mContext.startActivityAsUser(intent, bundle, handle); } else { Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); } @@ -4067,15 +4120,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - void launchHomeFromHotKey() { - launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); + void launchHomeFromHotKey(int displayId) { + launchHomeFromHotKey(displayId, true /* awakenFromDreams */, true /*respectKeyguard*/); } /** * A home key -> launch home action was detected. Take the appropriate action * given the situation with the keyguard. */ - void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { + void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams, + final boolean respectKeyguard) { // Abort possibly stuck animations. mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe); @@ -4092,7 +4146,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void onKeyguardExitResult(boolean success) { if (success) { - startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); + startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams); } } }); @@ -4113,7 +4167,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { hideRecentApps(false, true); } else { // Otherwise, just launch Home - startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); + startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams); } } @@ -5677,7 +5731,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */); } - + // TODO(b/117479243): handle it in InputPolicy /** {@inheritDoc} */ @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { @@ -5690,6 +5744,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); final int keyCode = event.getKeyCode(); + final int displayId = event.getDisplayId(); final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; @@ -6193,7 +6248,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } - + // TODO(b/117479243): handle it in InputPolicy /** {@inheritDoc} */ @Override public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { @@ -7269,7 +7324,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return null; } - void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { + void startDockOrHome(int displayId, boolean fromHomeKey, boolean awakenFromDreams) { try { ActivityManager.getService().stopAppSwitches(); } catch (RemoteException e) {} @@ -7299,8 +7354,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else { intent = mHomeIntent; } + final Bundle bundle = getLaunchDisplayIdBundle(displayId); + startActivityAsUser(intent, bundle, UserHandle.CURRENT); + } - startActivityAsUser(intent, UserHandle.CURRENT); + private @Nullable Bundle getLaunchDisplayIdBundle(int displayId) { + return (displayId == INVALID_DISPLAY) ? null + : ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(); } /** @@ -7314,7 +7374,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (false) { // This code always brings home to the front. - startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); + startDockOrHome(DEFAULT_DISPLAY, false /*fromHomeKey*/, true /* awakenFromDreams */); } else { // This code brings home to the front or, if it is already // at the front, puts the device to sleep. @@ -7325,7 +7385,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else { ActivityManager.getService().stopAppSwitches(); sendCloseSystemWindows(); - Intent dock = createHomeDockIntent(); + final Intent dock = createHomeDockIntent(); if (dock != null) { int result = ActivityTaskManager.getService() .startActivityAsUser(null, null, dock, @@ -8013,7 +8073,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(incallBackBehaviorToString(mIncallBackBehavior)); pw.print(" mEndcallBehavior="); pw.println(endcallBehaviorToString(mEndcallBehavior)); - pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); + pw.print(prefix); + // TODO(b/117479243): handle it in InputPolicy + pw.print("mDisplayHomeButtonHandlers="); + for (int i = 0; i < mDisplayHomeButtonHandlers.size(); i++) { + final int key = mDisplayHomeButtonHandlers.keyAt(i); + pw.println(mDisplayHomeButtonHandlers.get(key)); + } pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); |