diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt new file mode 100644 index 0000000000000..f91f634a00e5a --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenFromDetachedRecentTask.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.legacysplitscreen + +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.FlickerParametersRunnerFactory +import com.android.server.wm.flicker.FlickerTestParameter +import com.android.server.wm.flicker.FlickerTestParameterFactory +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test enter split screen from a detached recent task + * + * To run this test: `atest WMShellFlickerTests:EnterSplitScreenFromDetachedRecentTask` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +class EnterSplitScreenFromDetachedRecentTask( + testSpec: FlickerTestParameter +) : LegacySplitScreenTransition(testSpec) { + + override val transition: FlickerBuilder.(Map) -> Unit + get() = { configuration -> + cleanSetup(this, configuration) + setup { + eachRun { + splitScreenApp.launchViaIntent(wmHelper) + // Press back to remove the task, but it should still be shown in recent. + device.pressBack() + } + } + transitions { + device.launchSplitScreen(wmHelper) + } + } + + override val ignoredWindows: List + get() = listOf(LAUNCHER_PACKAGE_NAME, + WindowManagerStateHelper.SPLASH_SCREEN_NAME, + WindowManagerStateHelper.SNAPSHOT_WINDOW_NAME, + splitScreenApp.defaultWindowName) + + @Presubmit + @Test + fun dockedStackDividerIsVisible() = testSpec.dockedStackDividerIsVisible() + + @Presubmit + @Test + fun appWindowIsVisible() { + testSpec.assertWmEnd { + isVisible(splitScreenApp.defaultWindowName) + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection { + return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests( + repetitions = SplitScreenHelper.TEST_REPETITIONS, + supportedRotations = listOf(Surface.ROTATION_0) // bugId = 179116910 + ) + } + } +} \ No newline at end of file diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index 9f9ac3e7a7c4c..455f568d75235 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -1888,7 +1888,12 @@ class RecentTasks { */ ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) { final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo(); - tr.fillTaskInfo(rti, stripExtras); + // If the recent Task is detached, we consider it will be re-attached to the default + // TaskDisplayArea because we currently only support recent overview in the default TDA. + final TaskDisplayArea tda = tr.isAttached() + ? tr.getDisplayArea() + : mService.mRootWindowContainer.getDefaultTaskDisplayArea(); + tr.fillTaskInfo(rti, stripExtras, tda); // Fill in some deprecated values. rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID; rti.persistentId = rti.taskId; @@ -1900,7 +1905,7 @@ class RecentTasks { final Task childTask = tr.getChildAt(i).asTask(); if (childTask != null && childTask.isOrganized()) { final ActivityManager.RecentTaskInfo cti = new ActivityManager.RecentTaskInfo(); - childTask.fillTaskInfo(cti); + childTask.fillTaskInfo(cti, true /* stripExtras */, tda); rti.childrenTaskInfos.add(cti); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index e120754498a71..9730f80014b4f 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2003,6 +2003,8 @@ class Task extends WindowContainer { return false; } if (tda == null) { + Slog.w(TAG_TASKS, "Can't find TaskDisplayArea to determine support for multi" + + " window. Task id=" + mTaskId + " attached=" + isAttached()); return false; } @@ -4046,10 +4048,17 @@ class Task extends WindowContainer { fillTaskInfo(info, true /* stripExtras */); } + void fillTaskInfo(TaskInfo info, boolean stripExtras) { + fillTaskInfo(info, stripExtras, getDisplayArea()); + } + /** * Fills in a {@link TaskInfo} with information from this task. + * + * @param tda consider whether this Task can be put in multi window as it will be attached to + * the give {@link TaskDisplayArea}. */ - void fillTaskInfo(TaskInfo info, boolean stripExtras) { + void fillTaskInfo(TaskInfo info, boolean stripExtras, @Nullable TaskDisplayArea tda) { getNumRunningActivities(mReuseActivitiesReport); info.userId = isLeafTask() ? mUserId : mCurrentUser; info.taskId = mTaskId; @@ -4074,8 +4083,8 @@ class Task extends WindowContainer { info.numActivities = mReuseActivitiesReport.numActivities; info.lastActiveTime = lastActiveTime; info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription()); - info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode(); - info.supportsMultiWindow = supportsMultiWindow(); + info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingModeInDisplayArea(tda); + info.supportsMultiWindow = supportsMultiWindowInDisplayArea(tda); info.configuration.setTo(getConfiguration()); // Update to the task's current activity type and windowing mode which may differ from the // window configuration diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 95b5afc04573c..5af68021b2019 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1143,6 +1143,48 @@ public class RecentTasksTest extends WindowTestsBase { assertNull(lastSnapshotData.bufferSize); } + @Test + public void testCreateRecentTaskInfo_detachedTask() { + final Task task = createTaskBuilder(".Task").setCreateActivity(true).build(); + final TaskDisplayArea tda = task.getDisplayArea(); + + assertTrue(task.isAttached()); + assertTrue(task.supportsMultiWindow()); + + RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true); + + assertTrue(info.supportsMultiWindow); + assertTrue(info.supportsSplitScreenMultiWindow); + + // The task can be put in split screen even if it is not attached now. + task.removeImmediately(); + + info = mRecentTasks.createRecentTaskInfo(task, true); + + assertTrue(info.supportsMultiWindow); + assertTrue(info.supportsSplitScreenMultiWindow); + + // Test non-resizable. + // The non-resizable task cannot be put in split screen because of the config. + doReturn(false).when(tda).supportsNonResizableMultiWindow(); + doReturn(false).when(task).isResizeable(); + + info = mRecentTasks.createRecentTaskInfo(task, true); + + assertFalse(info.supportsMultiWindow); + assertFalse(info.supportsSplitScreenMultiWindow); + + // Even if it is not attached, the non-resizable task can be put in split screen as long as + // the device supports it. + doReturn(true).when(tda).supportsNonResizableMultiWindow(); + + info = mRecentTasks.createRecentTaskInfo(task, true); + + assertTrue(info.supportsMultiWindow); + assertTrue(info.supportsSplitScreenMultiWindow); + + } + private TaskSnapshot createSnapshot(Point taskSize, Point bufferSize) { HardwareBuffer buffer = null; if (bufferSize != null) { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 9226c0b6f32ba..d93ebb383b3b6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -289,6 +289,9 @@ public class TaskTests extends WindowTestsBase { @Test public void testResolveNonResizableTaskWindowingMode() { + // Test with no support non-resizable in multi window regardless the screen size. + mAtm.mSupportsNonResizableMultiWindow = -1; + final Task task = createTask(mDisplayContent); Configuration parentConfig = task.getParent().getConfiguration(); parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);