Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d01a9aee authored by David Stevens's avatar David Stevens Committed by Android (Google) Code Review
Browse files

Merge "Prefer to launch activities on the source display"

parents 5beefa69 c6b91c65
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -2885,9 +2885,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;
@@ -2903,17 +2904,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) {
                // 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,
+39 −32
Original line number Diff line number Diff line
@@ -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,17 +1933,13 @@ 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;
        }

        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) {
@@ -1946,12 +1950,14 @@ class ActivityStarter {
                    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 (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.