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

Commit 71355604 authored by Eghosa Ewansiha-Vlachavas's avatar Eghosa Ewansiha-Vlachavas
Browse files

Only inherit task bounds for new single tasks

Normal task launches use `FLAG_ACTIVITY_NEW_TASK` which can cause them
to be wrongly caught but the task trampoline bounds logic. Testing has
shown that a common signature of these task trampolines is to use single
task launches. Update task trampoline bounds heuristic to only apply to
single task launches.

Flag: com.android.window.flags.inherit_task_bounds_for_trampoline_task_launches
Test: atest WmTests:DesktopModeLaunchParamsModifierTests,
atest WMShellUnitTests:DesktopTasksControllerTest
Fixes: 401296527
Fixes: 403470140
Change-Id: I73492e5500b5023687a13403ef472016cb76aaa5
parent 6778496a
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.app.ActivityManager.RunningTaskInfo
import android.app.TaskInfo
import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.ActivityInfo.LAUNCH_MULTIPLE
import android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE
import android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE_PER_TASK
@@ -290,21 +289,19 @@ fun getInheritedExistingTaskBounds(
        // Top task is an instance of launching activity. Activity will be launching in a new
        // task with the existing task also being closed. Inherit existing task bounds to
        // prevent new task jumping.
        (isLaunchingNewTask(launchMode, intentFlags) && isClosingExitingInstance(intentFlags)) ->
        (isLaunchingNewSingleTask(launchMode) && isClosingExitingInstance(intentFlags)) ->
            lastTask.configuration.windowConfiguration.bounds
        else -> null
    }
}

/**
 * Returns true if the launch mode or intent will result in a new task being created for the
 * activity.
 * Returns true if the launch mode will result in a single new task being created for the activity.
 */
private fun isLaunchingNewTask(launchMode: Int, intentFlags: Int) =
private fun isLaunchingNewSingleTask(launchMode: Int) =
    launchMode == LAUNCH_SINGLE_TASK ||
        launchMode == LAUNCH_SINGLE_INSTANCE ||
        launchMode == LAUNCH_SINGLE_INSTANCE_PER_TASK ||
        (intentFlags and FLAG_ACTIVITY_NEW_TASK) != 0
        launchMode == LAUNCH_SINGLE_INSTANCE_PER_TASK

/**
 * Returns true if the intent will result in an existing task instance being closed if a new one
+9 −5
Original line number Diff line number Diff line
@@ -32,9 +32,9 @@ import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.ActivityInfo
import android.content.pm.ActivityInfo.CONFIG_DENSITY
import android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
import android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
@@ -1200,9 +1200,11 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        existingTask.topActivity = testComponent
        existingTask.configuration.windowConfiguration.setBounds(Rect(0, 0, 500, 500))
        // Set up new instance of already existing task.
        val launchingTask = setUpFullscreenTask()
        val launchingTask =
            setUpFullscreenTask().apply {
                topActivityInfo = ActivityInfo().apply { launchMode = LAUNCH_SINGLE_INSTANCE }
            }
        launchingTask.topActivity = testComponent
        launchingTask.baseIntent.addFlags(FLAG_ACTIVITY_NEW_TASK)

        // Move new instance to desktop. By default multi instance is not supported so first
        // instance will close.
@@ -1224,10 +1226,12 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
        existingTask.topActivity = testComponent
        existingTask.configuration.windowConfiguration.setBounds(Rect(0, 0, 500, 500))
        // Set up new instance of already existing task.
        val launchingTask = setUpFreeformTask(active = false)
        val launchingTask =
            setUpFreeformTask(active = false).apply {
                topActivityInfo = ActivityInfo().apply { launchMode = LAUNCH_SINGLE_INSTANCE }
            }
        taskRepository.removeTask(launchingTask.displayId, launchingTask.taskId)
        launchingTask.topActivity = testComponent
        launchingTask.baseIntent.addFlags(FLAG_ACTIVITY_NEW_TASK)

        // Move new instance to desktop. By default multi instance is not supported so first
        // instance will close.
+4 −7
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE_PER_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -242,20 +241,18 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
            @NonNull Task launchingTask) {
        if (existingTaskActivity == null || launchingActivity == null) return false;
        return (existingTaskActivity.packageName == launchingActivity.packageName)
                && isLaunchingNewTask(launchingActivity.launchMode,
                    launchingTask.getBaseIntent().getFlags())
                && isLaunchingNewSingleTask(launchingActivity.launchMode)
                && isClosingExitingInstance(launchingTask.getBaseIntent().getFlags());
    }

    /**
     * Returns true if the launch mode or intent will result in a new task being created for the
     * Returns true if the launch mode will result in a single new task being created for the
     * activity.
     */
    private boolean isLaunchingNewTask(int launchMode, int intentFlags) {
    private boolean isLaunchingNewSingleTask(int launchMode) {
        return launchMode == LAUNCH_SINGLE_TASK
                || launchMode == LAUNCH_SINGLE_INSTANCE
                || launchMode == LAUNCH_SINGLE_INSTANCE_PER_TASK
                || (intentFlags & FLAG_ACTIVITY_NEW_TASK) != 0;
                || launchMode == LAUNCH_SINGLE_INSTANCE_PER_TASK;
    }

    /**
+3 −2
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL_VALUE;
@@ -282,6 +282,7 @@ public class DesktopModeLaunchParamsModifierTests extends
        final DisplayContent dc = spy(createNewDisplay());
        final Task existingFreeformTask = new TaskBuilder(mSupervisor).setCreateActivity(true)
                .setWindowingMode(WINDOWING_MODE_FREEFORM).setPackage(packageName).build();
        existingFreeformTask.topRunningActivity().launchMode = LAUNCH_SINGLE_INSTANCE;
        existingFreeformTask.setBounds(
                /* left */ 0,
                /* top */ 0,
@@ -293,8 +294,8 @@ public class DesktopModeLaunchParamsModifierTests extends
        // so first instance will close.
        final Task launchingTask = new TaskBuilder(mSupervisor).setPackage(packageName)
                .setCreateActivity(true).build();
        launchingTask.topRunningActivity().launchMode = LAUNCH_SINGLE_INSTANCE;
        launchingTask.onDisplayChanged(dc);
        launchingTask.intent.addFlags(FLAG_ACTIVITY_NEW_TASK);

        // New instance should inherit task bounds of old instance.
        assertEquals(RESULT_DONE,