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:
@@ -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
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user