From 30356d273a01126bf77865ced38e8a9e70ea2e1b Mon Sep 17 00:00:00 2001 From: Iris Yang Date: Wed, 25 May 2022 17:04:39 +0800 Subject: [PATCH] Use DeviceProfile to determine whether to exclude tasks from Recent For Android Auto, tasks should exclude from Recents by default. For App streaming device profile, tasks should be showed from Recents. This change also keep the most recent task of "Default display" in Recents even if it's excluded from Recents. Bug: 232385935 Test: atest WmTests:RecentTasksTest Change-Id: Ic01ed6bbae1f2b77f8664196cbc59b248f5ec3b4 --- .../window/DisplayWindowPolicyController.java | 5 ++++ .../GenericWindowPolicyController.java | 21 +++++++++++++++- .../companion/virtual/VirtualDeviceImpl.java | 3 ++- .../com/android/server/wm/DisplayContent.java | 11 ++++++++ .../DisplayWindowPolicyControllerHelper.java | 10 ++++++++ .../com/android/server/wm/RecentTasks.java | 19 +++++++++++--- .../audio/VirtualAudioControllerTest.java | 4 ++- .../DisplayWindowPolicyControllerTests.java | 5 ++++ .../android/server/wm/RecentTasksTest.java | 25 +++++++++++++++++++ 9 files changed, 97 insertions(+), 6 deletions(-) diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java index d3cc918c2a29b..a5aefd5157ce6 100644 --- a/core/java/android/window/DisplayWindowPolicyController.java +++ b/core/java/android/window/DisplayWindowPolicyController.java @@ -125,6 +125,11 @@ public abstract class DisplayWindowPolicyController { public abstract boolean keepActivityOnWindowFlagsChanged( ActivityInfo activityInfo, int windowFlags, int systemWindowFlags); + /** + * Returns {@code true} if the tasks which is on this virtual display can be showed on Recents. + */ + public abstract boolean canShowTasksInRecents(); + /** * This is called when the top activity of the display is changed. */ diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index 0b437446826a0..4473a095063ab 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -16,6 +16,8 @@ package com.android.server.companion.virtual; +import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING; +import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION; import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; @@ -24,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.WindowConfiguration; import android.app.compat.CompatChanges; +import android.companion.AssociationRequest; import android.companion.virtual.VirtualDeviceManager.ActivityListener; import android.companion.virtual.VirtualDeviceParams; import android.companion.virtual.VirtualDeviceParams.ActivityPolicy; @@ -95,6 +98,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController private final Handler mHandler = new Handler(Looper.getMainLooper()); private final ArraySet mRunningAppsChangedListener = new ArraySet<>(); + private final @AssociationRequest.DeviceProfile String mDeviceProfile; /** * Creates a window policy controller that is generic to the different use cases of virtual @@ -119,6 +123,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController * is not populated in this callback and is always {@link Display#INVALID_DISPLAY}. * @param activityBlockedCallback Callback that is called when an activity is blocked from * launching. + * @param deviceProfile The {@link AssociationRequest.DeviceProfile} of this virtual device. */ public GenericWindowPolicyController(int windowFlags, int systemWindowFlags, @NonNull ArraySet allowedUsers, @@ -128,7 +133,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set blockedActivities, @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, - @NonNull Consumer activityBlockedCallback) { + @NonNull Consumer activityBlockedCallback, + @AssociationRequest.DeviceProfile String deviceProfile) { super(); mAllowedUsers = allowedUsers; mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations); @@ -139,6 +145,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mActivityBlockedCallback = activityBlockedCallback; setInterestedWindowFlags(windowFlags, systemWindowFlags); mActivityListener = activityListener; + mDeviceProfile = deviceProfile; } /** Register a listener for running applications changes. */ @@ -248,6 +255,18 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController }); } + @Override + public boolean canShowTasksInRecents() { + // TODO(b/234075973) : Remove this once proper API is ready. + switch (mDeviceProfile) { + case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION: + return false; + case DEVICE_PROFILE_APP_STREAMING: + default: + return true; + } + } + /** * Returns true if an app with the given UID has an activity running on the virtual display for * this controller. diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java index 638b3aeef544b..33fd83bf6bd7a 100644 --- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java @@ -557,7 +557,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getBlockedActivities(), mParams.getDefaultActivityPolicy(), createListenerAdapter(displayId), - activityInfo -> onActivityBlocked(displayId, activityInfo)); + activityInfo -> onActivityBlocked(displayId, activityInfo), + mAssociationInfo.getDeviceProfile()); gwpc.registerRunningAppsChangedListener(/* listener= */ this); mWindowPolicyControllers.put(displayId, gwpc); return gwpc; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c60dfa1ed8ba8..ebe0efbbf1407 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -224,6 +224,7 @@ import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManagerPolicyConstants.PointerEventListener; +import android.window.DisplayWindowPolicyController; import android.window.IDisplayAreaOrganizer; import android.window.TransitionRequestInfo; @@ -1958,6 +1959,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayRotation.updateRotationUnchecked(false /* forceUpdate */); } + /** + * @see DisplayWindowPolicyController#canShowTasksInRecents() + */ + boolean canShowTasksInRecents() { + if (mDwpcHelper == null) { + return true; + } + return mDwpcHelper.canShowTasksInRecents(); + } + /** * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked} * (if it returned {@code true}) to actually finish the rotation. diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java index 2deb8286f95f7..5d4904264056a 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java +++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java @@ -152,6 +152,16 @@ class DisplayWindowPolicyControllerHelper { return mDisplayWindowPolicyController.isWindowingModeSupported(windowingMode); } + /** + * @see DisplayWindowPolicyController#canShowTasksInRecents() + */ + public final boolean canShowTasksInRecents() { + if (mDisplayWindowPolicyController == null) { + return true; + } + return mDisplayWindowPolicyController.canShowTasksInRecents(); + } + void dump(String prefix, PrintWriter pw) { if (mDisplayWindowPolicyController != null) { pw.println(); diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java index e259238c2879c..4860762a5f7f7 100644 --- a/services/core/java/com/android/server/wm/RecentTasks.java +++ b/services/core/java/com/android/server/wm/RecentTasks.java @@ -1390,6 +1390,13 @@ class RecentTasks { return false; } + // Ignore the task if it is started on a display which is not allow to show its tasks on + // Recents. + if (task.getDisplayContent() != null + && !task.getDisplayContent().canShowTasksInRecents()) { + return false; + } + return true; } @@ -1399,13 +1406,19 @@ class RecentTasks { private boolean isInVisibleRange(Task task, int taskIndex, int numVisibleTasks, boolean skipExcludedCheck) { if (!skipExcludedCheck) { - // Keep the most recent task even if it is excluded from recents + // Keep the most recent task of home display even if it is excluded from recents. final boolean isExcludeFromRecents = (task.getBaseIntent().getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; if (isExcludeFromRecents) { - if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\texcludeFromRecents=true"); - return taskIndex == 0; + if (DEBUG_RECENTS_TRIM_TASKS) { + Slog.d(TAG, + "\texcludeFromRecents=true, taskIndex = " + taskIndex + + ", isOnHomeDisplay: " + task.isOnHomeDisplay()); + } + // The Recents is only supported on default display now, we should only keep the + // most recent task of home display. + return (task.isOnHomeDisplay() && taskIndex == 0); } } diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java index cd836c77076db..e2c3a94fc187d 100644 --- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java @@ -16,6 +16,7 @@ package com.android.server.companion.virtual.audio; +import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING; import static android.media.AudioAttributes.FLAG_SECURE; import static android.media.AudioPlaybackConfiguration.PLAYER_STATE_STARTED; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; @@ -81,7 +82,8 @@ public class VirtualAudioControllerTest { /* blockedActivities= */ new ArraySet<>(), VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED, /* activityListener= */ null, - /* activityBlockedCallback= */ null); + /* activityBlockedCallback= */ null, + /* deviceProfile= */ DEVICE_PROFILE_APP_STREAMING); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java index 02009b75e319d..47c217651e786 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java @@ -242,5 +242,10 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { mRunningUids.clear(); mRunningUids.addAll(runningUids); } + + @Override + public boolean canShowTasksInRecents() { + return true; + } } } 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 284728397c9fe..feb1c6fa6b5c4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -690,6 +690,20 @@ public class RecentTasksTest extends WindowTestsBase { assertGetRecentTasksOrder(0 /* flags */, excludedTask1); } + @Test + public void testVisibleTasks_excludedFromRecents_nonDefaultDisplayTaskNotVisible() { + Task excludedTaskOnVirtualDisplay = createTaskBuilder(".excludedTaskOnVirtualDisplay") + .setFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + .build(); + excludedTaskOnVirtualDisplay.mUserSetupComplete = true; + doReturn(false).when(excludedTaskOnVirtualDisplay).isOnHomeDisplay(); + mRecentTasks.add(mTasks.get(0)); + mRecentTasks.add(excludedTaskOnVirtualDisplay); + + // Expect that the first visible excluded-from-recents task is visible + assertGetRecentTasksOrder(0 /* flags */, mTasks.get(0)); + } + @Test public void testVisibleTasks_excludedFromRecents_withExcluded() { // Create some set of tasks, some of which are visible and some are not @@ -801,6 +815,17 @@ public class RecentTasksTest extends WindowTestsBase { mRecentTasks.isVisibleRecentTask(task)); } + @Test + public void testVisibleTask_displayCanNotShowTaskFromRecents_expectNotVisible() { + final DisplayContent displayContent = addNewDisplayContentAt(DisplayContent.POSITION_TOP); + doReturn(false).when(displayContent).canShowTasksInRecents(); + final Task task = displayContent.getDefaultTaskDisplayArea().createRootTask( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); + mRecentTasks.add(task); + + assertFalse(mRecentTasks.isVisibleRecentTask(task)); + } + @Test public void testFreezeTaskListOrder_reorderExistingTask() { // Add some tasks