From 6d709f6f95fc2e8eb958976e87ecc2c4fb4610b1 Mon Sep 17 00:00:00 2001 From: Iris Yang Date: Thu, 24 Feb 2022 13:39:11 +0000 Subject: [PATCH] Add API to indicate supported windowing modes on the virtual displays 1. Add new API in DWPC to get windowing features of the virtual display. 2. In ActivityRecord, consume the value of the allowed windowing modes of virtual display. Bug: 180435098 Test: atest WmTests:ActivityRecordTests#testSupportsPictureInPicture && atest WmTests:DisplayWindowPolicyControllerHelperTests Change-Id: I39a6cd9417f266f7fdef72cc054263c3ca4c5650 --- .../window/DisplayWindowPolicyController.java | 47 ++++++++++++++++++- .../GenericWindowPolicyController.java | 8 +++- .../com/android/server/wm/ActivityRecord.java | 4 +- .../server/wm/ActivityTaskSupervisor.java | 3 +- .../DisplayWindowPolicyControllerHelper.java | 19 ++++++-- .../server/wm/ActivityRecordTests.java | 17 ++++++- ...playWindowPolicyControllerHelperTests.java | 42 ++++++++++++++++- 7 files changed, 130 insertions(+), 10 deletions(-) diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java index 3359a41369d7d..1270d87e3a044 100644 --- a/core/java/android/window/DisplayWindowPolicyController.java +++ b/core/java/android/window/DisplayWindowPolicyController.java @@ -17,12 +17,14 @@ package android.window; import android.annotation.NonNull; +import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.util.ArraySet; import java.io.PrintWriter; import java.util.List; +import java.util.Set; /** * Abstract class to control the policies of the windows that can be displayed on the virtual @@ -45,6 +47,22 @@ public abstract class DisplayWindowPolicyController { */ private int mSystemWindowFlags; + /** + * The set of windowing mode that are supported in this display. + * @see android.app.WindowConfiguration.WindowingMode + */ + private final Set mSupportedWindowingModes = new ArraySet<>(); + + /** + * A controller to control the policies of the windows that can be displayed on the virtual + * display. + */ + public DisplayWindowPolicyController() { + synchronized (mSupportedWindowingModes) { + mSupportedWindowingModes.add(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); + } + } + /** * Returns {@code true} if the given window flags contain the flags that we're interested in. */ @@ -62,9 +80,34 @@ public abstract class DisplayWindowPolicyController { } /** - * Returns {@code true} if the given activities can be displayed on this virtual display. + * Returns {@code true} if the given windowing mode is supported in this display. */ - public abstract boolean canContainActivities(@NonNull List activities); + public final boolean isWindowingModeSupported( + @WindowConfiguration.WindowingMode int windowingMode) { + synchronized (mSupportedWindowingModes) { + return mSupportedWindowingModes.contains(windowingMode); + } + } + + /** + * Sets the windowing modes are supported in this display. + * + * @param supportedWindowingModes The set of + * {@link android.app.WindowConfiguration.WindowingMode}. + */ + public final void setSupportedWindowingModes(Set supportedWindowingModes) { + synchronized (mSupportedWindowingModes) { + mSupportedWindowingModes.clear(); + mSupportedWindowingModes.addAll(supportedWindowingModes); + } + } + + /** + * Returns {@code true} if the given activities can be displayed on this virtual display and + * the windowing mode is supported. + */ + public abstract boolean canContainActivities(@NonNull List activities, + @WindowConfiguration.WindowingMode int windowingMode); /** * Called when an Activity window is layouted with the new changes where contains the 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 b991ba87eef46..3a26c46116290 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.app.compat.CompatChanges; import android.companion.virtual.VirtualDeviceManager.ActivityListener; import android.companion.virtual.VirtualDeviceParams; @@ -119,6 +120,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @ActivityPolicy int defaultActivityPolicy, @NonNull ActivityListener activityListener, @NonNull Consumer activityBlockedCallback) { + super(); mAllowedUsers = allowedUsers; mAllowedActivities = new ArraySet<>(allowedActivities); mBlockedActivities = new ArraySet<>(blockedActivities); @@ -134,7 +136,11 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController } @Override - public boolean canContainActivities(@NonNull List activities) { + public boolean canContainActivities(@NonNull List activities, + @WindowConfiguration.WindowingMode int windowingMode) { + if (!isWindowingModeSupported(windowingMode)) { + return false; + } // Can't display all the activities if any of them don't want to be displayed. final int activityCount = activities.size(); for (int i = 0; i < activityCount; i++) { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e66f309d2cccf..d63cf3ebaabeb 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2854,7 +2854,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ boolean supportsPictureInPicture() { return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined() - && info.supportsPictureInPicture(); + && info.supportsPictureInPicture() + && (mDisplayContent != null && mDisplayContent.mDwpcHelper.isWindowingModeSupported( + WINDOWING_MODE_PINNED)); } /** diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 5573f161d1c1e..72325d87ba951 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -402,7 +402,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { activities.add(r.info); }); } - if (!displayContent.mDwpcHelper.canContainActivities(activities)) { + if (!displayContent.mDwpcHelper.canContainActivities(activities, + displayContent.getWindowingMode())) { return false; } } diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java index 60d2a5da9286e..27d46ecfb91a1 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java +++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java @@ -18,6 +18,7 @@ package com.android.server.wm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.os.UserHandle; import android.util.ArraySet; @@ -63,13 +64,14 @@ class DisplayWindowPolicyControllerHelper { } /** - * @see DisplayWindowPolicyController#canContainActivities(List) + * @see DisplayWindowPolicyController#canContainActivities(List, int) */ - public boolean canContainActivities(@NonNull List activities) { + public boolean canContainActivities(@NonNull List activities, + @WindowConfiguration.WindowingMode int windowingMode) { if (mDisplayWindowPolicyController == null) { return true; } - return mDisplayWindowPolicyController.canContainActivities(activities); + return mDisplayWindowPolicyController.canContainActivities(activities, windowingMode); } /** @@ -126,6 +128,17 @@ class DisplayWindowPolicyControllerHelper { } } + /** + * @see DisplayWindowPolicyController#isWindowingModeSupported(int) + */ + public final boolean isWindowingModeSupported( + @WindowConfiguration.WindowingMode int windowingMode) { + if (mDisplayWindowPolicyController == null) { + return true; + } + return mDisplayWindowPolicyController.isWindowingModeSupported(windowingMode); + } + void dump(String prefix, PrintWriter pw) { if (mDisplayWindowPolicyController != null) { pw.println(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index a89c5a1fbf1f7..9536a302c718d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2184,11 +2184,17 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testSupportsPictureInPicture() { + final Task task = new TaskBuilder(mSupervisor) + .setDisplay(mDisplayContent).build(); final ActivityRecord activity = new ActivityBuilder(mAtm) - .setCreateTask(true) + .setTask(task) .setResizeMode(ActivityInfo.RESIZE_MODE_UNRESIZEABLE) .setActivityFlags(FLAG_SUPPORTS_PICTURE_IN_PICTURE) .build(); + spyOn(mDisplayContent); + spyOn(mDisplayContent.mDwpcHelper); + doReturn(true).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( + WINDOWING_MODE_PINNED); // Device not supports PIP mAtm.mSupportsPictureInPicture = false; @@ -2201,6 +2207,15 @@ public class ActivityRecordTests extends WindowTestsBase { // Activity not supports PIP activity.info.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; assertFalse(activity.supportsPictureInPicture()); + + // Activity supports PIP + activity.info.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; + assertTrue(activity.supportsPictureInPicture()); + + // Display not supports PIP + doReturn(false).when(mDisplayContent.mDwpcHelper).isWindowingModeSupported( + WINDOWING_MODE_PINNED); + assertFalse(activity.supportsPictureInPicture()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java index 6e11d8cf23e17..f9689990c5e84 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerHelperTests.java @@ -16,13 +16,18 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; +import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.pm.ActivityInfo; import android.os.UserHandle; @@ -37,6 +42,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.List; +import java.util.Set; /** * Tests for the {@link DisplayWindowPolicyControllerHelper} class. @@ -113,6 +119,39 @@ public class DisplayWindowPolicyControllerHelperTests extends WindowTestsBase { return activity; } + @Test + public void testIsWindowingModeSupported_noController_returnTrueForAnyWindowingMode() { + doReturn(null).when(mWm.mDisplayManagerInternal) + .getDisplayWindowPolicyController(anyInt()); + mSecondaryDisplay = createNewDisplay(); + assertFalse(mSecondaryDisplay.mDwpcHelper.hasController()); + + assertTrue(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + assertTrue( + mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_FULLSCREEN)); + } + + @Test + public void testIsWindowingModeSupported_withoutSettingSupportedMode_returnFalse() { + assertFalse(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + } + + @Test + public void testIsWindowingModeSupported_withoutSupportedMode_defaultSupportFullScreen() { + assertTrue( + mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_FULLSCREEN)); + } + + @Test + public void testIsWindowingModeSupported_setPinnedMode_returnTrue() { + Set supportedWindowingMode = new ArraySet<>(); + supportedWindowingMode.add(WINDOWING_MODE_PINNED); + + mDwpc.setSupportedWindowingModes(supportedWindowingMode); + + assertTrue(mSecondaryDisplay.mDwpcHelper.isWindowingModeSupported(WINDOWING_MODE_PINNED)); + } + private class TestDisplayWindowPolicyController extends DisplayWindowPolicyController { ComponentName mTopActivity = null; @@ -120,7 +159,8 @@ public class DisplayWindowPolicyControllerHelperTests extends WindowTestsBase { ArraySet mRunningUids = new ArraySet<>(); @Override - public boolean canContainActivities(@NonNull List activities) { + public boolean canContainActivities(@NonNull List activities, + @WindowConfiguration.WindowingMode int windowingMode) { return false; }