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
This commit is contained in:
Iris Yang
2022-05-25 17:04:39 +08:00
parent 606074be18
commit 30356d273a
9 changed files with 97 additions and 6 deletions

View File

@@ -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.
*/

View File

@@ -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<RunningAppsChangedListener> 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<UserHandle> allowedUsers,
@@ -128,7 +133,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@NonNull Set<ComponentName> blockedActivities,
@ActivityPolicy int defaultActivityPolicy,
@NonNull ActivityListener activityListener,
@NonNull Consumer<ActivityInfo> activityBlockedCallback) {
@NonNull Consumer<ActivityInfo> 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.

View File

@@ -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;

View File

@@ -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.

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -242,5 +242,10 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
mRunningUids.clear();
mRunningUids.addAll(runningUids);
}
@Override
public boolean canShowTasksInRecents() {
return true;
}
}
}

View File

@@ -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