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