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
This commit is contained in:
Iris Yang
2022-02-24 13:39:11 +00:00
parent e78a3443f2
commit 6d709f6f95
7 changed files with 130 additions and 10 deletions

View File

@@ -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<Integer> 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<ActivityInfo> 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<Integer> 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<ActivityInfo> activities,
@WindowConfiguration.WindowingMode int windowingMode);
/**
* Called when an Activity window is layouted with the new changes where contains the

View File

@@ -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<ActivityInfo> 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<ActivityInfo> activities) {
public boolean canContainActivities(@NonNull List<ActivityInfo> 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++) {

View File

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

View File

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

View File

@@ -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<ActivityInfo> activities) {
public boolean canContainActivities(@NonNull List<ActivityInfo> 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();

View File

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

View File

@@ -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<Integer> 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<Integer> mRunningUids = new ArraySet<>();
@Override
public boolean canContainActivities(@NonNull List<ActivityInfo> activities) {
public boolean canContainActivities(@NonNull List<ActivityInfo> activities,
@WindowConfiguration.WindowingMode int windowingMode) {
return false;
}