From a8fe3dfdfdaed3c7eb31c48f63cfe6f3961e4d40 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Fri, 16 Jun 2017 15:29:26 -0700 Subject: [PATCH] Look on all displays if can't launch on a source secondary one If an activity is launched from a secondary display but is not allowed to land on it, then look for a topmost valid launch stack across all displays. Bug: 62544886 Test: go/wm-smoke Test: android.server.cts.ActivityManagerDisplayTests Test: #testLaunchNonResizeableActivityFromSecondaryDisplaySameTask Test: #testLaunchNonResizeableActivityFromSecondaryDisplayNewTask Change-Id: I57470e9ede317f7d492e2b7641a5cb02db13f1b0 --- .../server/am/ActivityStackSupervisor.java | 25 +++++++++++++++++++ .../android/server/am/ActivityStarter.java | 15 ++++++++--- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 7de56fa17877f..f37979179eaed 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2257,6 +2257,31 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return null; } + /** + * Get next valid stack for launching provided activity in the system. This will search across + * displays and stacks in last-focused order for a focusable and visible stack, except those + * that are on a currently focused display. + * + * @param r The activity that is being launched. + * @param currentFocus The display that previously had focus and thus needs to be ignored when + * searching for the next candidate. + * @return Next valid {@link ActivityStack}, null if not found. + */ + ActivityStack getNextValidLaunchStackLocked(@NonNull ActivityRecord r, int currentFocus) { + mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds); + for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) { + final int displayId = mTmpOrderedDisplayIds.get(i); + if (displayId == currentFocus) { + continue; + } + final ActivityStack stack = getValidLaunchStackOnDisplay(displayId, r); + if (stack != null) { + return stack; + } + } + return null; + } + ActivityRecord getHomeActivity() { return getHomeActivityForUser(mCurrentUser); } diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index d74d1d6dc9542..c7ee149a9727b 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -2027,7 +2027,18 @@ class ActivityStarter { return mSupervisor.mFocusedStack; } - if (mSourceDisplayId == DEFAULT_DISPLAY) { + if (mSourceDisplayId != DEFAULT_DISPLAY) { + // Try to put the activity in a stack on a secondary display. + stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r); + if (stack == null) { + // If source display is not suitable - look for topmost valid stack in the system. + if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, + "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId + + ", looking on all displays."); + stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId); + } + } + if (stack == null) { // We first try to put the task in the first dynamic stack on home display. final ArrayList homeDisplayStacks = mSupervisor.mHomeStack.mStacks; for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { @@ -2043,8 +2054,6 @@ class ActivityStarter { bounds != null ? FREEFORM_WORKSPACE_STACK_ID : FULLSCREEN_WORKSPACE_STACK_ID; stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP); - } else { - stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r); } if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r=" + r + " stackId=" + stack.mStackId);