Declare new display category and enforce equality match with activity attribute in GWPC

Bug:233910285
Test: atest RestrictActivityTest
Change-Id: I0452fe45d5d5ba360bbfbe4a15586fcea68d2216
This commit is contained in:
Mary Xia
2022-10-10 13:29:30 +00:00
parent 135f60131a
commit bbbb94315e
8 changed files with 263 additions and 54 deletions

View File

@@ -2958,6 +2958,7 @@ package android.companion.virtual {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @NonNull java.util.List<java.lang.String>, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);

View File

@@ -350,14 +350,72 @@ public final class VirtualDeviceManager {
@VirtualDisplayFlag int flags,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
// TODO(b/205343547): Handle display groups properly instead of creating a new display
// group for every new virtual display created using this API.
// belongs to the same display group.
VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
getVirtualDisplayName(), width, height, densityDpi)
.setSurface(surface)
.setFlags(getVirtualDisplayFlags(flags))
.build();
return createVirtualDisplayInternal(config, executor, callback);
}
/**
* Creates a virtual display for this virtual device. All displays created on the same
* device belongs to the same display group.
*
* @param width The width of the virtual display in pixels, must be greater than 0.
* @param height The height of the virtual display in pixels, must be greater than 0.
* @param densityDpi The density of the virtual display in dpi, must be greater than 0.
* @param displayCategories The categories of the virtual display, indicating the type of
* activities allowed to run on the display. Activities can declare their type using
* {@link android.content.pm.ActivityInfo#targetDisplayCategory}.
* @param surface The surface to which the content of the virtual display should
* be rendered, or null if there is none initially. The surface can also be set later using
* {@link VirtualDisplay#setSurface(Surface)}.
* @param flags A combination of virtual display flags accepted by
* {@link DisplayManager#createVirtualDisplay}. In addition, the following flags are
* automatically set for all virtual devices:
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC VIRTUAL_DISPLAY_FLAG_PUBLIC} and
* {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
* VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
* @param executor The executor on which {@code callback} will be invoked. This is ignored
* if {@code callback} is {@code null}. If {@code callback} is specified, this executor must
* not be null.
* @param callback Callback to call when the state of the {@link VirtualDisplay} changes
* @return The newly created virtual display, or {@code null} if the application could
* not create the virtual display.
*
* @see DisplayManager#createVirtualDisplay
*/
@Nullable
public VirtualDisplay createVirtualDisplay(
@IntRange(from = 1) int width,
@IntRange(from = 1) int height,
@IntRange(from = 1) int densityDpi,
@NonNull List<String> displayCategories,
@Nullable Surface surface,
@VirtualDisplayFlag int flags,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
getVirtualDisplayName(), width, height, densityDpi)
.setDisplayCategories(displayCategories)
.setSurface(surface)
.setFlags(getVirtualDisplayFlags(flags))
.build();
return createVirtualDisplayInternal(config, executor, callback);
}
/**
* @hide
*/
@Nullable
private VirtualDisplay createVirtualDisplayInternal(
@NonNull VirtualDisplayConfig config,
@Nullable @CallbackExecutor Executor executor,
@Nullable VirtualDisplay.Callback callback) {
// TODO(b/205343547): Handle display groups properly instead of creating a new display
// group for every new virtual display created using this API.
// belongs to the same display group.
IVirtualDisplayCallback callbackWrapper =
new DisplayManagerGlobal.VirtualDisplayCallback(callback, executor);
final int displayId;

View File

@@ -30,6 +30,9 @@ import android.view.Surface;
import com.android.internal.util.DataClass;
import java.util.ArrayList;
import java.util.List;
/**
* Holds configuration used to create {@link VirtualDisplay} instances. See
* {@link MediaProjection#createVirtualDisplay(VirtualDisplayConfig, VirtualDisplay.Callback, Handler)}.
@@ -99,6 +102,13 @@ public final class VirtualDisplayConfig implements Parcelable {
*/
private boolean mWindowManagerMirroring = false;
/**
* The display categories. If set, only corresponding activities from the same category can be
* shown on the display.
*/
@DataClass.PluralOf("displayCategory")
@NonNull private List<String> mDisplayCategories = new ArrayList<>();
// Code below generated by codegen v1.0.23.
@@ -124,7 +134,8 @@ public final class VirtualDisplayConfig implements Parcelable {
@Nullable Surface surface,
@Nullable String uniqueId,
int displayIdToMirror,
boolean windowManagerMirroring) {
boolean windowManagerMirroring,
@NonNull List<String> displayCategories) {
this.mName = name;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mName);
@@ -147,6 +158,9 @@ public final class VirtualDisplayConfig implements Parcelable {
this.mUniqueId = uniqueId;
this.mDisplayIdToMirror = displayIdToMirror;
this.mWindowManagerMirroring = windowManagerMirroring;
this.mDisplayCategories = displayCategories;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mDisplayCategories);
// onConstructed(); // You can define this method to get a callback
}
@@ -233,6 +247,15 @@ public final class VirtualDisplayConfig implements Parcelable {
return mWindowManagerMirroring;
}
/**
* The display categories. If set, only corresponding activities from the same category can be
* shown on the display.
*/
@DataClass.Generated.Member
public @NonNull List<String> getDisplayCategories() {
return mDisplayCategories;
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
@@ -252,6 +275,7 @@ public final class VirtualDisplayConfig implements Parcelable {
if (mSurface != null) dest.writeTypedObject(mSurface, flags);
if (mUniqueId != null) dest.writeString(mUniqueId);
dest.writeInt(mDisplayIdToMirror);
dest.writeStringList(mDisplayCategories);
}
@Override
@@ -275,6 +299,8 @@ public final class VirtualDisplayConfig implements Parcelable {
Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
int displayIdToMirror = in.readInt();
List<String> displayCategories = new ArrayList<>();
in.readStringList(displayCategories);
this.mName = name;
com.android.internal.util.AnnotationValidations.validate(
@@ -298,6 +324,9 @@ public final class VirtualDisplayConfig implements Parcelable {
this.mUniqueId = uniqueId;
this.mDisplayIdToMirror = displayIdToMirror;
this.mWindowManagerMirroring = windowManagerMirroring;
this.mDisplayCategories = displayCategories;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mDisplayCategories);
// onConstructed(); // You can define this method to get a callback
}
@@ -332,6 +361,7 @@ public final class VirtualDisplayConfig implements Parcelable {
private @Nullable String mUniqueId;
private int mDisplayIdToMirror;
private boolean mWindowManagerMirroring;
private @NonNull List<String> mDisplayCategories;
private long mBuilderFieldsSet = 0L;
@@ -478,10 +508,30 @@ public final class VirtualDisplayConfig implements Parcelable {
return this;
}
/**
* The display categories. If set, only corresponding activities from the same category can be
* shown on the display.
*/
@DataClass.Generated.Member
public @NonNull Builder setDisplayCategories(@NonNull List<String> value) {
checkNotUsed();
mBuilderFieldsSet |= 0x200;
mDisplayCategories = value;
return this;
}
/** @see #setDisplayCategories */
@DataClass.Generated.Member
public @NonNull Builder addDisplayCategory(@NonNull String value) {
if (mDisplayCategories == null) setDisplayCategories(new ArrayList<>());
mDisplayCategories.add(value);
return this;
}
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull VirtualDisplayConfig build() {
checkNotUsed();
mBuilderFieldsSet |= 0x200; // Mark builder used
mBuilderFieldsSet |= 0x400; // Mark builder used
if ((mBuilderFieldsSet & 0x10) == 0) {
mFlags = 0;
@@ -498,6 +548,9 @@ public final class VirtualDisplayConfig implements Parcelable {
if ((mBuilderFieldsSet & 0x100) == 0) {
mWindowManagerMirroring = false;
}
if ((mBuilderFieldsSet & 0x200) == 0) {
mDisplayCategories = new ArrayList<>();
}
VirtualDisplayConfig o = new VirtualDisplayConfig(
mName,
mWidth,
@@ -507,12 +560,13 @@ public final class VirtualDisplayConfig implements Parcelable {
mSurface,
mUniqueId,
mDisplayIdToMirror,
mWindowManagerMirroring);
mWindowManagerMirroring,
mDisplayCategories);
return o;
}
private void checkNotUsed() {
if ((mBuilderFieldsSet & 0x200) != 0) {
if ((mBuilderFieldsSet & 0x400) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -520,10 +574,10 @@ public final class VirtualDisplayConfig implements Parcelable {
}
@DataClass.Generated(
time = 1646227247934L,
time = 1668534501320L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java",
inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.IntRange int mWidth\nprivate @android.annotation.IntRange int mHeight\nprivate @android.annotation.IntRange int mDensityDpi\nprivate @android.hardware.display.DisplayManager.VirtualDisplayFlag int mFlags\nprivate @android.annotation.Nullable android.view.Surface mSurface\nprivate @android.annotation.Nullable java.lang.String mUniqueId\nprivate int mDisplayIdToMirror\nprivate boolean mWindowManagerMirroring\nprivate @com.android.internal.util.DataClass.PluralOf(\"displayCategory\") @android.annotation.NonNull java.util.List<java.lang.String> mDisplayCategories\nclass VirtualDisplayConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true)")
@Deprecated
private void __metadata() {}

View File

@@ -130,6 +130,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Nullable
private final @AssociationRequest.DeviceProfile String mDeviceProfile;
@Nullable private final SecureWindowCallback mSecureWindowCallback;
@Nullable private final List<String> mDisplayCategories;
/**
* Creates a window policy controller that is generic to the different use cases of virtual
@@ -168,7 +169,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@NonNull PipBlockedCallback pipBlockedCallback,
@NonNull ActivityBlockedCallback activityBlockedCallback,
@NonNull SecureWindowCallback secureWindowCallback,
@AssociationRequest.DeviceProfile String deviceProfile) {
@AssociationRequest.DeviceProfile String deviceProfile,
@NonNull List<String> displayCategories) {
super();
mAllowedUsers = allowedUsers;
mAllowedCrossTaskNavigations = new ArraySet<>(allowedCrossTaskNavigations);
@@ -182,6 +184,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
mDeviceProfile = deviceProfile;
mPipBlockedCallback = pipBlockedCallback;
mSecureWindowCallback = secureWindowCallback;
mDisplayCategories = displayCategories;
}
/**
@@ -319,7 +322,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
if (mDeviceProfile == null) {
return true;
}
// TODO(b/234075973) : Remove this once proper API is ready.
// TODO(b/234075973) : Remove this once proper API is ready.
switch (mDeviceProfile) {
case DEVICE_PROFILE_AUTOMOTIVE_PROJECTION:
return false;
@@ -350,6 +353,15 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
}
private boolean activityMatchesDisplayCategory(ActivityInfo activityInfo) {
if (mDisplayCategories.isEmpty()) {
return activityInfo.targetDisplayCategory == null;
}
return activityInfo.targetDisplayCategory != null
&& mDisplayCategories.contains(activityInfo.targetDisplayCategory);
}
private boolean canContainActivity(ActivityInfo activityInfo, int windowFlags,
int systemWindowFlags) {
if ((activityInfo.flags & FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES) == 0) {
@@ -357,9 +369,17 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
}
ComponentName activityComponent = activityInfo.getComponentName();
if (BLOCKED_APP_STREAMING_COMPONENT.equals(activityComponent)) {
// The error dialog alerting users that streaming is blocked is always allowed.
// The error dialog alerting users that streaming is blocked is always allowed. Need to
// run before the clauses below to ensure error dialog always shows up.
return true;
}
if (!activityMatchesDisplayCategory(activityInfo)) {
Slog.d(TAG, String.format(
"The activity's target display category: %s is not found on virtual display"
+ " with the following allowed display categories: %s",
activityInfo.targetDisplayCategory, mDisplayCategories.toString()));
return false;
}
final UserHandle activityUser =
UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid);
if (!mAllowedUsers.contains(activityUser)) {

View File

@@ -74,6 +74,7 @@ import com.android.server.companion.virtual.audio.VirtualAudioController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
@@ -628,7 +629,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mInputController.dump(fout);
}
GenericWindowPolicyController createWindowPolicyController() {
GenericWindowPolicyController createWindowPolicyController(
@NonNull List<String> displayCategories) {
synchronized (mVirtualDeviceLock) {
final GenericWindowPolicyController gwpc =
new GenericWindowPolicyController(FLAG_SECURE,
@@ -643,7 +645,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
this::onEnteringPipBlocked,
this::onActivityBlocked,
this::onSecureWindowShown,
mAssociationInfo.getDeviceProfile());
mAssociationInfo.getDeviceProfile(),
displayCategories);
gwpc.registerRunningAppsChangedListener(/* listener= */ this);
return gwpc;
}

View File

@@ -332,7 +332,8 @@ public class VirtualDeviceManagerService extends SystemService {
GenericWindowPolicyController gwpc;
final long token = Binder.clearCallingIdentity();
try {
gwpc = virtualDeviceImpl.createWindowPolicyController();
gwpc = virtualDeviceImpl.createWindowPolicyController(
virtualDisplayConfig.getDisplayCategories());
} finally {
Binder.restoreCallingIdentity(token);
}

View File

@@ -99,6 +99,7 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
@Presubmit
@@ -181,14 +182,36 @@ public class VirtualDeviceManagerServiceTest {
return blockedActivities;
}
private Intent createRestrictedActivityBlockedIntent(List displayCategories,
String targetDisplayCategory) {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(displayCategories), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices= */ true,
targetDisplayCategory);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
return blockedAppIntent;
}
private ArrayList<ActivityInfo> getActivityInfoList(
String packageName, String name, boolean displayOnRemoveDevices) {
String packageName, String name, boolean displayOnRemoveDevices,
String targetDisplayCategory) {
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = packageName;
activityInfo.name = name;
activityInfo.flags = displayOnRemoveDevices
? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES;
activityInfo.applicationInfo = mApplicationInfoMock;
activityInfo.targetDisplayCategory = targetDisplayCategory;
return new ArrayList<>(Arrays.asList(activityInfo));
}
@@ -298,7 +321,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayRemovedLocked_doesNotThrowException() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
// This call should not throw any exceptions.
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
}
@@ -317,7 +340,7 @@ public class VirtualDeviceManagerServiceTest {
public void onVirtualDisplayRemovedLocked_listenersNotified() {
mLocalService.registerVirtualDisplayListener(mDisplayListener);
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
mLocalService.onVirtualDisplayRemoved(mDeviceImpl, DISPLAY_ID);
TestableLooper.get(this).processAllMessages();
@@ -379,7 +402,7 @@ public class VirtualDeviceManagerServiceTest {
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), anyInt(), eq(null));
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
nullable(String.class), eq(DISPLAY_ID), eq(null));
@@ -388,9 +411,10 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired()
throws RemoteException {
GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController();
GenericWindowPolicyController gwpc = mDeviceImpl.createWindowPolicyController(
new ArrayList<>());
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
assertThrows(IllegalStateException.class,
() -> mDeviceImpl.onVirtualDisplayCreatedLocked(gwpc, DISPLAY_ID));
TestableLooper.get(this).processAllMessages();
@@ -409,7 +433,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
@@ -425,7 +449,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class);
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(),
@@ -625,7 +649,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionStarting_hasVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
@@ -635,7 +659,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionEnded_noVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.onAudioSessionEnded();
@@ -646,7 +670,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void close_cleanVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.close();
@@ -863,14 +887,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME, /* displayOnRemoveDevices */ true);
NONBLOCKED_APP_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -882,14 +908,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
PERMISSION_CONTROLLER_PACKAGE_NAME,
PERMISSION_CONTROLLER_PACKAGE_NAME, /* displayOnRemoveDevices */ false);
PERMISSION_CONTROLLER_PACKAGE_NAME,
/* displayOnRemoveDevices */ false,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -901,14 +929,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
SETTINGS_PACKAGE_NAME,
SETTINGS_PACKAGE_NAME, /* displayOnRemoveDevices */ true);
SETTINGS_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -920,14 +950,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openVendingOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
VENDING_PACKAGE_NAME,
VENDING_PACKAGE_NAME, /* displayOnRemoveDevices */ true);
VENDING_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -939,14 +971,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
GOOGLE_DIALER_PACKAGE_NAME,
GOOGLE_DIALER_PACKAGE_NAME, /* displayOnRemoveDevices */ true);
GOOGLE_DIALER_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -958,14 +992,16 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() {
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
doNothing().when(mContext).startActivityAsUser(any(), any(), any());
ArrayList<ActivityInfo> activityInfos = getActivityInfoList(
GOOGLE_MAPS_PACKAGE_NAME,
GOOGLE_MAPS_PACKAGE_NAME, /* displayOnRemoveDevices */ true);
GOOGLE_MAPS_PACKAGE_NAME,
/* displayOnRemoveDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfos.get(0), mAssociationInfo.getDisplayName());
gwpc.canContainActivities(activityInfos, WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
@@ -978,7 +1014,7 @@ public class VirtualDeviceManagerServiceTest {
public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
@@ -993,7 +1029,7 @@ public class VirtualDeviceManagerServiceTest {
public void noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() {
ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2));
mDeviceImpl.onVirtualDisplayCreatedLocked(
mDeviceImpl.createWindowPolicyController(), DISPLAY_ID);
mDeviceImpl.createWindowPolicyController(new ArrayList<>()), DISPLAY_ID);
GenericWindowPolicyController gwpc = mDeviceImpl.getWindowPolicyControllersForTesting().get(
DISPLAY_ID);
mDeviceImpl.onVirtualDisplayRemovedLocked(DISPLAY_ID);
@@ -1003,4 +1039,37 @@ public class VirtualDeviceManagerServiceTest {
assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0);
}
@Test
public void nonRestrictedActivityOnRestrictedVirtualDisplay_startBlockedAlertActivity() {
Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"),
/* targetDisplayCategory= */ null);
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
@Test
public void restrictedActivityOnRestrictedVirtualDisplay_doesNotStartBlockedAlertActivity() {
Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"), "abc");
verify(mContext, never()).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
@Test
public void restrictedActivityOnNonRestrictedVirtualDisplay_startBlockedAlertActivity() {
Intent blockedAppIntent = createRestrictedActivityBlockedIntent(
/* displayCategories= */ List.of(), "abc");
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
@Test
public void
restrictedActivityOnNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity() {
Intent blockedAppIntent = createRestrictedActivityBlockedIntent(List.of("abc"), "def");
verify(mContext).startActivityAsUser(argThat(intent ->
intent.filterEquals(blockedAppIntent)), any(), any());
}
}

View File

@@ -72,22 +72,25 @@ public class VirtualAudioControllerTest {
MockitoAnnotations.initMocks(this);
mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
mVirtualAudioController = new VirtualAudioController(mContext);
mGenericWindowPolicyController = new GenericWindowPolicyController(
FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
/* allowedUsers= */ new ArraySet<>(),
/* allowedCrossTaskNavigations= */ new ArraySet<>(),
/* blockedCrossTaskNavigations= */ new ArraySet<>(),
/* allowedActivities= */ new ArraySet<>(),
/* blockedActivities= */ new ArraySet<>(),
VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
/* secureWindowCallback= */ null,
/* deviceProfile= */ DEVICE_PROFILE_APP_STREAMING);
mGenericWindowPolicyController =
new GenericWindowPolicyController(
FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
/* allowedUsers= */ new ArraySet<>(),
/* allowedCrossTaskNavigations= */ new ArraySet<>(),
/* blockedCrossTaskNavigations= */ new ArraySet<>(),
/* allowedActivities= */ new ArraySet<>(),
/* blockedActivities= */ new ArraySet<>(),
VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
/* activityListener= */ null,
/* pipBlockedCallback= */ null,
/* activityBlockedCallback= */ null,
/* secureWindowCallback= */ null,
/* deviceProfile= */ DEVICE_PROFILE_APP_STREAMING,
/* displayCategories= */ new ArrayList<>());
}
@Test
public void startListening_receivesCallback() throws RemoteException {
ArraySet<Integer> runningUids = new ArraySet<>();