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

Commit 1b78887b authored by Jeff Chang's avatar Jeff Chang Committed by Android (Google) Code Review
Browse files

Merge "Don’t allow activities with different display categories in same task"

parents a7f6d53e 5ef83c77
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -2285,6 +2285,15 @@ class ActivityStarter {
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        }

        if (r.info.requiredDisplayCategory != null && mSourceRecord != null
                && !r.info.requiredDisplayCategory.equals(
                        mSourceRecord.info.requiredDisplayCategory)) {
            // Adding NEW_TASK flag for activity with display category attribute if the display
            // category of the source record is different, so that the activity won't be launched
            // in source record's task.
            mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
        }

        sendNewTaskResultRequestIfNeeded();

        if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
@@ -2372,6 +2381,12 @@ class ActivityStarter {
            Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
            mInTask = null;
        }
        // Prevent to start activity in Task with different display category
        if (mInTask != null && !mInTask.isSameRequiredDisplayCategory(r.info)) {
            Slog.w(TAG, "Starting activity in task with different display category: "
                    + mInTask);
            mInTask = null;
        }
        mInTaskFragment = inTaskFragment;

        mStartFlags = startFlags;
+2 −1
Original line number Diff line number Diff line
@@ -418,7 +418,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            } else if (!isDocument && !taskIsDocument
                    && mIdealRecord == null && mCandidateRecord == null
                    && task.rootAffinity != null) {
                if (task.rootAffinity.equals(mTaskAffinity)) {
                if (task.rootAffinity.equals(mTaskAffinity)
                        && task.isSameRequiredDisplayCategory(mInfo)) {
                    ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!");
                    // It is possible for multiple tasks to have the same root affinity especially
                    // if they are in separate root tasks. We save off this candidate, but keep
+13 −0
Original line number Diff line number Diff line
@@ -491,6 +491,9 @@ class Task extends TaskFragment {
    private int mForceHiddenFlags = 0;
    private boolean mForceTranslucent = false;

    // The display category name for this task.
    String mRequiredDisplayCategory;

    // TODO(b/160201781): Revisit double invocation issue in Task#removeChild.
    /**
     * Skip {@link ActivityTaskSupervisor#removeTask(Task, boolean, boolean, String)} execution if
@@ -1011,6 +1014,7 @@ class Task extends TaskFragment {
            // affinity -- we don't want it changing after initially set, but the initially
            // set value may be null.
            rootAffinity = affinity;
            mRequiredDisplayCategory = info.requiredDisplayCategory;
        }
        effectiveUid = info.applicationInfo.uid;
        mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
@@ -6078,6 +6082,15 @@ class Task extends TaskFragment {
        }
    }

    /**
     * Return true if the activityInfo has the same requiredDisplayCategory as this task.
     */
    boolean isSameRequiredDisplayCategory(@NonNull ActivityInfo info) {
        return mRequiredDisplayCategory != null && mRequiredDisplayCategory.equals(
                info.requiredDisplayCategory)
                || (mRequiredDisplayCategory == null && info.requiredDisplayCategory == null);
    }

    @Override
    public void dumpDebug(ProtoOutputStream proto, long fieldId,
            @WindowTraceLogLevel int logLevel) {
+115 −0
Original line number Diff line number Diff line
@@ -62,11 +62,13 @@ import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_NEW_TASK;
import static com.android.server.wm.TaskFragment.EMBEDDING_DISALLOWED_UNTRUSTED_HOST;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowTestsBase.ActivityBuilder.DEFAULT_FAKE_UID;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -1617,6 +1619,119 @@ public class ActivityStarterTests extends WindowTestsBase {
        assertNull(starter2.mMovedToTopActivity);
    }

    /**
     * Tests a task with specific display category exist in system and then launching another
     * activity with the same affinity but without define the display category. Make sure the
     * lunching activity is placed on the different task.
     */
    @Test
    public void testLaunchActivityWithoutDisplayCategory() {
        final ActivityInfo info = new ActivityInfo();
        info.applicationInfo = new ApplicationInfo();
        info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
                0 /* launchMode */);
        info.requiredDisplayCategory = "automotive";
        final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                .build();

        final ActivityRecord target = new ActivityBuilder(mAtm).setAffinity(info.taskAffinity)
                .build();
        final ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK, false);
        startActivityInner(starter, target, null /* source */, null /* options */,
                null /* inTask */, null /* inTaskFragment */);

        assertNotEquals(task, target.getTask());
    }

    /**
     * Tests a task with a specific display category exist in the system and then launches another
     * activity with the different display category. Make sure the launching activity is not placed
     * on the sourceRecord's task.
     */
    @Test
    public void testLaunchActivityWithDifferentDisplayCategory() {
        final ActivityInfo info = new ActivityInfo();
        info.applicationInfo = new ApplicationInfo();
        info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
                0 /* launchMode */);
        info.requiredDisplayCategory = "automotive";
        final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                .build();

        final ActivityRecord target = new ActivityBuilder(mAtm).setRequiredDisplayCategory("auto")
                .setAffinity(info.taskAffinity).build();
        final ActivityStarter starter = prepareStarter(0, false);
        startActivityInner(starter, target,  task.getBottomMostActivity(), null /* options */,
                null /* inTask */, null /* inTaskFragment */);

        assertNotEquals(task, target.getTask());
    }

    /**
     * Tests a task with specific display category exist in system and then launching another
     * activity with the same display category. Make sure the launching activity is placed on the
     * same task.
     */
    @Test
    public void testLaunchActivityWithSameDisplayCategory() {
        final ActivityInfo info = new ActivityInfo();
        info.applicationInfo = new ApplicationInfo();
        info.taskAffinity = ActivityRecord.computeTaskAffinity("test", DEFAULT_FAKE_UID,
                0 /* launchMode */);
        info.requiredDisplayCategory = "automotive";
        final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).setActivityInfo(info)
                .build();

        final ActivityRecord target = new ActivityBuilder(mAtm)
                .setRequiredDisplayCategory(info.requiredDisplayCategory)
                .setAffinity(info.taskAffinity).build();
        final ActivityStarter starter = prepareStarter(0, false);
        startActivityInner(starter, target,  task.getBottomMostActivity(), null /* options */,
                null /* inTask */, null /* inTaskFragment */);

        assertEquals(task, target.getTask());
    }

    /**
     * Tests a task with specific display category exist in system and launching activity into the
     * specific task within inTask attribute. Make sure the activity is not placed on the task since
     * the display category is different.
     */
    @Test
    public void testLaunchActivityInTaskWithDisplayCategory() {
        final ActivityInfo info = new ActivityInfo();
        info.applicationInfo = new ApplicationInfo();
        info.requiredDisplayCategory = "automotive";
        final Task inTask = new TaskBuilder(mSupervisor).setActivityInfo(info).build();
        inTask.inRecents = true;

        final ActivityStarter starter = prepareStarter(0, false);
        final ActivityRecord target = new ActivityBuilder(mAtm).build();
        startActivityInner(starter, target, null /* source */, null /* options */, inTask,
                null /* inTaskFragment */);

        assertNotEquals(inTask, target.getTask());
    }

    /**
     * Tests a task without a specific display category exist in the system and launches activity
     * with display category into the task within the inTask attribute. Make sure the activity is
     * not placed on the task since the display category is different.
     */
    @Test
    public void testLaunchDisplayCategoryActivityInTask() {
        final Task inTask = new TaskBuilder(mSupervisor).build();
        inTask.inRecents = true;

        final ActivityStarter starter = prepareStarter(0, false);
        final ActivityRecord target = new ActivityBuilder(mAtm).setRequiredDisplayCategory("auto")
                .build();
        startActivityInner(starter, target, null /* source */, null /* options */, inTask,
                null /* inTaskFragment */);

        assertNotEquals(inTask, target.getTask());
    }

    private static void startActivityInner(ActivityStarter starter, ActivityRecord target,
            ActivityRecord source, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment) {
+9 −0
Original line number Diff line number Diff line
@@ -1017,6 +1017,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
        private ActivityInfo.WindowLayout mWindowLayout;
        private boolean mVisible = true;
        private ActivityOptions mLaunchIntoPipOpts;
        private String mRequiredDisplayCategory;

        ActivityBuilder(ActivityTaskManagerService service) {
            mService = service;
@@ -1157,6 +1158,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
            return this;
        }

        ActivityBuilder setRequiredDisplayCategory(String requiredDisplayCategory) {
            mRequiredDisplayCategory = requiredDisplayCategory;
            return this;
        }

        ActivityRecord build() {
            SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
            try {
@@ -1201,6 +1207,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
            aInfo.configChanges |= mConfigChanges;
            aInfo.taskAffinity = mAffinity;
            aInfo.windowLayout = mWindowLayout;
            if (mRequiredDisplayCategory != null) {
                aInfo.requiredDisplayCategory = mRequiredDisplayCategory;
            }

            if (mCreateTask) {
                mTask = new TaskBuilder(mService.mTaskSupervisor)