Add setAllowedActivities/setBlockActivities implementation

These APIs allow Virtual Device owners to configure allow and deny lists of
components which are allowed to be streamed.

Bug: 201559291
Test: To be added in ag/15781910
Change-Id: I5e9297b9fdbe987690e164b7215352e741806fd5
This commit is contained in:
Maurice Lam
2022-01-19 00:06:45 -08:00
parent 60c20f23cb
commit 9ed5fe201c
3 changed files with 133 additions and 8 deletions

View File

@@ -20,7 +20,9 @@ import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.content.ComponentName;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
@@ -65,18 +67,26 @@ public final class VirtualDeviceParams implements Parcelable {
private final int mLockState;
private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
@Nullable private final ArraySet<ComponentName> mAllowedActivities;
@Nullable private final ArraySet<ComponentName> mBlockedActivities;
private VirtualDeviceParams(
@LockState int lockState,
@NonNull Set<UserHandle> usersWithMatchingAccounts) {
@NonNull Set<UserHandle> usersWithMatchingAccounts,
@Nullable Set<ComponentName> allowedActivities,
@Nullable Set<ComponentName> blockedActivities) {
mLockState = lockState;
mUsersWithMatchingAccounts = new ArraySet<>(usersWithMatchingAccounts);
mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities);
mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities);
}
@SuppressWarnings("unchecked")
private VirtualDeviceParams(Parcel parcel) {
mLockState = parcel.readInt();
mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null);
mAllowedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
mBlockedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
}
/**
@@ -98,6 +108,33 @@ public final class VirtualDeviceParams implements Parcelable {
return Collections.unmodifiableSet(mUsersWithMatchingAccounts);
}
/**
* Returns the set of activities allowed to be streamed, or {@code null} if this is not set.
*
* @see Builder#setAllowedActivities(Set)
*/
@Nullable
public Set<ComponentName> getAllowedActivities() {
if (mAllowedActivities == null) {
return null;
}
return Collections.unmodifiableSet(mAllowedActivities);
}
/**
* Returns the set of activities that are blocked from streaming, or {@code null} if this is not
* set.
*
* @see Builder#setBlockedActivities(Set)
*/
@Nullable
public Set<ComponentName> getBlockedActivities() {
if (mBlockedActivities == null) {
return null;
}
return Collections.unmodifiableSet(mBlockedActivities);
}
@Override
public int describeContents() {
return 0;
@@ -107,6 +144,8 @@ public final class VirtualDeviceParams implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mLockState);
dest.writeArraySet(mUsersWithMatchingAccounts);
dest.writeArraySet(mAllowedActivities);
dest.writeArraySet(mBlockedActivities);
}
@Override
@@ -118,8 +157,10 @@ public final class VirtualDeviceParams implements Parcelable {
return false;
}
VirtualDeviceParams that = (VirtualDeviceParams) o;
return mLockState == that.mLockState && mUsersWithMatchingAccounts.equals(
that.mUsersWithMatchingAccounts);
return mLockState == that.mLockState
&& mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts)
&& Objects.equals(mAllowedActivities, that.mAllowedActivities)
&& Objects.equals(mBlockedActivities, that.mBlockedActivities);
}
@Override
@@ -132,6 +173,8 @@ public final class VirtualDeviceParams implements Parcelable {
return "VirtualDeviceParams("
+ " mLockState=" + mLockState
+ " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts
+ " mAllowedActivities=" + mAllowedActivities
+ " mBlockedActivities=" + mBlockedActivities
+ ")";
}
@@ -153,6 +196,8 @@ public final class VirtualDeviceParams implements Parcelable {
private @LockState int mLockState = LOCK_STATE_ALWAYS_LOCKED;
private Set<UserHandle> mUsersWithMatchingAccounts;
@Nullable private Set<ComponentName> mBlockedActivities;
@Nullable private Set<ComponentName> mAllowedActivities;
/**
* Sets the lock state of the device. The permission {@code ADD_ALWAYS_UNLOCKED_DISPLAY}
@@ -175,6 +220,7 @@ public final class VirtualDeviceParams implements Parcelable {
*
* @param usersWithMatchingAccounts A set of user handles with matching managed
* accounts on the remote device this is streaming to.
*
* @see android.app.admin.DevicePolicyManager#NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY
*/
public Builder setUsersWithMatchingAccounts(
@@ -183,6 +229,52 @@ public final class VirtualDeviceParams implements Parcelable {
return this;
}
/**
* Sets the activities allowed to be launched in the virtual device. If
* {@code allowedActivities} is non-null, all activities other than the ones in the set will
* be blocked from launching.
*
* <p>{@code allowedActivities} and the set in {@link #setBlockedActivities(Set)} cannot
* both be non-null at the same time.
*
* @throws IllegalArgumentException if {@link #setBlockedActivities(Set)} has been set to a
* non-null value.
*
* @param allowedActivities A set of activity {@link ComponentName} allowed to be launched
* in the virtual device.
*/
public Builder setAllowedActivities(@Nullable Set<ComponentName> allowedActivities) {
if (mBlockedActivities != null && allowedActivities != null) {
throw new IllegalArgumentException(
"Allowed activities and Blocked activities cannot both be set.");
}
mAllowedActivities = allowedActivities;
return this;
}
/**
* Sets the activities blocked from launching in the virtual device. If the {@code
* blockedActivities} is non-null, activities in the set are blocked from launching in the
* virtual device.
*
* {@code blockedActivities} and the set in {@link #setAllowedActivities(Set)} cannot both
* be non-null at the same time.
*
* @throws IllegalArgumentException if {@link #setAllowedActivities(Set)} has been set to a
* non-null value.
*
* @param blockedActivities A set of {@link ComponentName} to be blocked launching from
* virtual device.
*/
public Builder setBlockedActivities(@Nullable Set<ComponentName> blockedActivities) {
if (mAllowedActivities != null && blockedActivities != null) {
throw new IllegalArgumentException(
"Allowed activities and Blocked activities cannot both be set.");
}
mBlockedActivities = blockedActivities;
return this;
}
/**
* Builds the {@link VirtualDeviceParams} instance.
*/
@@ -191,7 +283,13 @@ public final class VirtualDeviceParams implements Parcelable {
if (mUsersWithMatchingAccounts == null) {
mUsersWithMatchingAccounts = Collections.emptySet();
}
return new VirtualDeviceParams(mLockState, mUsersWithMatchingAccounts);
if (mAllowedActivities != null && mBlockedActivities != null) {
// Should never reach here because the setters block this as well.
throw new IllegalStateException(
"Allowed activities and Blocked activities cannot both be set.");
}
return new VirtualDeviceParams(mLockState, mUsersWithMatchingAccounts,
mAllowedActivities, mBlockedActivities);
}
}
}

View File

@@ -21,6 +21,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
@@ -33,6 +34,7 @@ import android.util.Slog;
import android.window.DisplayWindowPolicyController;
import java.util.List;
import java.util.Set;
/**
@@ -49,13 +51,23 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
@ChangeId
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
public static final long ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE = 201712607L;
@NonNull private final ArraySet<UserHandle> mAllowedUsers;
@NonNull
private final ArraySet<UserHandle> mAllowedUsers;
@Nullable
private final ArraySet<ComponentName> mAllowedActivities;
@Nullable
private final ArraySet<ComponentName> mBlockedActivities;
@NonNull final ArraySet<Integer> mRunningUids = new ArraySet<>();
@NonNull
final ArraySet<Integer> mRunningUids = new ArraySet<>();
GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers) {
@NonNull ArraySet<UserHandle> allowedUsers,
@Nullable Set<ComponentName> allowedActivities,
@Nullable Set<ComponentName> blockedActivities) {
mAllowedUsers = allowedUsers;
mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities);
mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities);
setInterestedWindowFlags(windowFlags, systemWindowFlags);
}
@@ -108,6 +120,18 @@ class GenericWindowPolicyController extends DisplayWindowPolicyController {
Slog.d(TAG, "Virtual device activity not allowed from user " + activityUser);
return false;
}
if (mBlockedActivities != null
&& mBlockedActivities.contains(activityInfo.getComponentName())) {
Slog.d(TAG,
"Virtual device blocking launch of " + activityInfo.getComponentName());
return false;
}
if (mAllowedActivities != null
&& !mAllowedActivities.contains(activityInfo.getComponentName())) {
Slog.d(TAG,
activityInfo.getComponentName() + " is not in the allowed list.");
return false;
}
if (!CompatChanges.isChangeEnabled(ALLOW_SECURE_ACTIVITY_DISPLAY_ON_REMOTE_DEVICE,
activityInfo.packageName, activityUser)) {
// TODO(b/201712607): Add checks for the apps that use SurfaceView#setSecure.

View File

@@ -328,6 +328,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
fout.println(" VirtualDevice: ");
fout.println(" mAssociationId: " + mAssociationInfo.getId());
fout.println(" mParams: " + mParams);
fout.println(" mVirtualDisplayIds: ");
synchronized (mVirtualDeviceLock) {
for (int id : mVirtualDisplayIds) {
@@ -345,7 +346,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
mVirtualDisplayIds.add(displayId);
final GenericWindowPolicyController dwpc =
new GenericWindowPolicyController(FLAG_SECURE,
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, getAllowedUserHandles());
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, getAllowedUserHandles(),
mParams.getAllowedActivities(),
mParams.getBlockedActivities());
mWindowPolicyControllers.put(displayId, dwpc);
return dwpc;
}