summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java312
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);