diff options
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 24 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityStarter.java | 71 |
2 files changed, 54 insertions, 41 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 2ae815e305c1..7c3280efcccc 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2884,9 +2884,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } - ActivityRecord findTaskLocked(ActivityRecord r) { + ActivityRecord findTaskLocked(ActivityRecord r, int displayId) { mTmpFindTaskResult.r = null; mTmpFindTaskResult.matchedByRootAffinity = false; + ActivityRecord affinityMatch = null; if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r); for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; @@ -2902,17 +2903,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D continue; } stack.findTaskLocked(r, mTmpFindTaskResult); - // It is possible to have task in multiple stacks with the same root affinity. - // If the match we found was based on root affinity we keep on looking to see if - // there is a better match in another stack. We eventually return the match based - // on root affinity if we don't find a better match. - if (mTmpFindTaskResult.r != null && !mTmpFindTaskResult.matchedByRootAffinity) { - return mTmpFindTaskResult.r; + // It is possible to have tasks in multiple stacks with the same root affinity, so + // we should keep looking after finding an affinity match to see if there is a + // better match in another stack. Also, task affinity isn't a good enough reason + // to target a display which isn't the source of the intent, so skip any affinity + // matches not on the specified display. + if (mTmpFindTaskResult.r != null) { + if (!mTmpFindTaskResult.matchedByRootAffinity) { + return mTmpFindTaskResult.r; + } else if (mTmpFindTaskResult.r.getDisplayId() == displayId) { + affinityMatch = mTmpFindTaskResult.r; + } } } } - if (DEBUG_TASKS && mTmpFindTaskResult.r == null) Slog.d(TAG_TASKS, "No task found"); - return mTmpFindTaskResult.r; + if (DEBUG_TASKS && affinityMatch == null) Slog.d(TAG_TASKS, "No task found"); + return affinityMatch; } ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 2bbfc21c299f..1b7b22527df1 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -54,6 +54,7 @@ import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP; +import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS; @@ -169,6 +170,7 @@ class ActivityStarter { private boolean mDoResume; private int mStartFlags; private ActivityRecord mSourceRecord; + private int mSourceDisplayId; private TaskRecord mInTask; private boolean mAddingToTask; @@ -208,6 +210,7 @@ class ActivityStarter { mDoResume = false; mStartFlags = 0; mSourceRecord = null; + mSourceDisplayId = INVALID_DISPLAY; mInTask = null; mAddingToTask = false; @@ -451,8 +454,8 @@ class ActivityStarter { Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from uid " + callingUid + " on display " + (container == null ? (mSupervisor.mFocusedStack == null ? - Display.DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : - (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : + DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId) : + (container.mActivityDisplay == null ? DEFAULT_DISPLAY : container.mActivityDisplay.mDisplayId))); } } @@ -1193,6 +1196,11 @@ class ActivityStarter { mVoiceSession = voiceSession; mVoiceInteractor = voiceInteractor; + mSourceDisplayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY; + if (mSourceDisplayId == INVALID_DISPLAY) { + mSourceDisplayId = DEFAULT_DISPLAY; + } + mLaunchBounds = getOverrideBounds(r, options, inTask); mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP; @@ -1439,7 +1447,7 @@ class ActivityStarter { !mLaunchSingleTask); } else { // Otherwise find the best task to put the activity in. - intentActivity = mSupervisor.findTaskLocked(mStartActivity); + intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId); } } return intentActivity; @@ -1925,33 +1933,31 @@ class ActivityStarter { return container.mStack; } - // The fullscreen stack can contain any task regardless of if the task is resizeable - // or not. So, we let the task go in the fullscreen task if it is the focus stack. - // Same also applies to dynamic stacks, as they behave similar to fullscreen stack. - // If the freeform or docked stack has focus, and the activity to be launched is resizeable, - // we can also put it in the focused stack. if (canLaunchIntoFocusedStack(r, newTask)) { if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack); return mSupervisor.mFocusedStack; } - // We first try to put the task in the first dynamic stack on home display. - final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks; - for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { - stack = homeDisplayStacks.get(stackNdx); - if (isDynamicStack(stack.mStackId)) { - if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, - "computeStackFocus: Setting focused stack=" + stack); - return stack; + if (mSourceDisplayId == DEFAULT_DISPLAY) { + // We first try to put the task in the first dynamic stack on home display. + final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks; + for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { + stack = homeDisplayStacks.get(stackNdx); + if (isDynamicStack(stack.mStackId)) { + if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, + "computeStackFocus: Setting focused stack=" + stack); + return stack; + } } + // If there is no suitable dynamic stack then we figure out which static stack to use. + final int stackId = task != null ? task.getLaunchStackId() : + 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 there is no suitable dynamic stack then we figure out which static stack to use. - final int stackId = task != null ? task.getLaunchStackId() : - bounds != null ? FREEFORM_WORKSPACE_STACK_ID : - FULLSCREEN_WORKSPACE_STACK_ID; - stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP); if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r=" + r + " stackId=" + stack.mStackId); return stack; @@ -1959,35 +1965,35 @@ class ActivityStarter { /** Check if provided activity record can launch in currently focused stack. */ private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) { - // The fullscreen stack can contain any task regardless of if the task is resizeable - // or not. So, we let the task go in the fullscreen task if it is the focus stack. - // Same also applies to dynamic stacks, as they behave similar to fullscreen stack. - // If the freeform or docked stack has focus, and the activity to be launched is resizeable, - // we can also put it in the focused stack. final ActivityStack focusedStack = mSupervisor.mFocusedStack; final int focusedStackId = mSupervisor.mFocusedStack.mStackId; final boolean canUseFocusedStack; switch (focusedStackId) { case FULLSCREEN_WORKSPACE_STACK_ID: + // The fullscreen stack can contain any task regardless of if the task is resizeable + // or not. So, we let the task go in the fullscreen task if it is the focus stack. canUseFocusedStack = true; break; case ASSISTANT_STACK_ID: canUseFocusedStack = r.isAssistantActivity(); break; case DOCKED_STACK_ID: + // Any activty which supports split screen can go in the docked stack. canUseFocusedStack = r.supportsSplitScreen(); break; case FREEFORM_WORKSPACE_STACK_ID: + // Any activty which supports freeform can go in the freeform stack. canUseFocusedStack = r.supportsFreeform(); break; default: - canUseFocusedStack = isDynamicStack(focusedStackId) - && mSupervisor.isCallerAllowedToLaunchOnDisplay(r.launchedFromPid, - r.launchedFromUid, focusedStack.mDisplayId); + // Dynamic stacks behave similarly to the fullscreen stack and can contain any task. + canUseFocusedStack = isDynamicStack(focusedStackId); } return canUseFocusedStack - && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks()); + && (!newTask || focusedStack.mActivityContainer.isEligibleForNewTasks()) + // We strongly prefer to launch activities on the same display as their source. + && (mSourceDisplayId == focusedStack.mDisplayId); } private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task, @@ -2034,7 +2040,8 @@ class ActivityStarter { return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r); } - if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) { + if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0 + || mSourceDisplayId != DEFAULT_DISPLAY) { return null; } // Otherwise handle adjacent launch. |