summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt11
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceParams.java132
-rw-r--r--services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java32
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java4
5 files changed, 121 insertions, 59 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2c0e6416b455..7d814d60063e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -2804,11 +2804,14 @@ package android.companion.virtual {
public final class VirtualDeviceParams implements android.os.Parcelable {
method public int describeContents();
- method @Nullable public java.util.Set<android.content.ComponentName> getAllowedActivities();
- method @Nullable public java.util.Set<android.content.ComponentName> getBlockedActivities();
+ method @NonNull public java.util.Set<android.content.ComponentName> getAllowedActivities();
+ method @NonNull public java.util.Set<android.content.ComponentName> getBlockedActivities();
+ method public int getDefaultActivityPolicy();
method public int getLockState();
method @NonNull public java.util.Set<android.os.UserHandle> getUsersWithMatchingAccounts();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int ACTIVITY_POLICY_DEFAULT_ALLOWED = 0; // 0x0
+ field public static final int ACTIVITY_POLICY_DEFAULT_BLOCKED = 1; // 0x1
field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.VirtualDeviceParams> CREATOR;
field public static final int LOCK_STATE_ALWAYS_UNLOCKED = 1; // 0x1
field public static final int LOCK_STATE_DEFAULT = 0; // 0x0
@@ -2817,8 +2820,8 @@ package android.companion.virtual {
public static final class VirtualDeviceParams.Builder {
ctor public VirtualDeviceParams.Builder();
method @NonNull public android.companion.virtual.VirtualDeviceParams build();
- method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAllowedActivities(@Nullable java.util.Set<android.content.ComponentName>);
- method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@Nullable java.util.Set<android.content.ComponentName>);
+ method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAllowedActivities(@NonNull java.util.Set<android.content.ComponentName>);
+ method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@NonNull java.util.Set<android.content.ComponentName>);
method @NonNull @RequiresPermission(value=android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY, conditional=true) public android.companion.virtual.VirtualDeviceParams.Builder setLockState(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setUsersWithMatchingAccounts(@NonNull java.util.Set<android.os.UserHandle>);
}
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 45d0ad51da04..41b1a1feae80 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -20,9 +20,7 @@ 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.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.os.Parcel;
@@ -64,20 +62,43 @@ public final class VirtualDeviceParams implements Parcelable {
*/
public static final int LOCK_STATE_ALWAYS_UNLOCKED = 1;
+ /** @hide */
+ @IntDef(prefix = "ACTIVITY_POLICY_",
+ value = {ACTIVITY_POLICY_DEFAULT_ALLOWED, ACTIVITY_POLICY_DEFAULT_BLOCKED})
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ public @interface ActivityPolicy {}
+
+ /**
+ * Indicates that activities are allowed by default on this virtual device, unless they are
+ * explicitly blocked by {@link Builder#setBlockedActivities}.
+ */
+ public static final int ACTIVITY_POLICY_DEFAULT_ALLOWED = 0;
+
+ /**
+ * Indicates that activities are blocked by default on this virtual device, unless they are
+ * allowed by {@link Builder#setAllowedActivities}.
+ */
+ public static final int ACTIVITY_POLICY_DEFAULT_BLOCKED = 1;
+
private final int mLockState;
private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
- @Nullable private final ArraySet<ComponentName> mAllowedActivities;
- @Nullable private final ArraySet<ComponentName> mBlockedActivities;
+ @NonNull private final ArraySet<ComponentName> mAllowedActivities;
+ @NonNull private final ArraySet<ComponentName> mBlockedActivities;
+ @ActivityPolicy
+ private final int mDefaultActivityPolicy;
private VirtualDeviceParams(
@LockState int lockState,
@NonNull Set<UserHandle> usersWithMatchingAccounts,
- @Nullable Set<ComponentName> allowedActivities,
- @Nullable Set<ComponentName> blockedActivities) {
+ @NonNull Set<ComponentName> allowedActivities,
+ @NonNull Set<ComponentName> blockedActivities,
+ @ActivityPolicy int defaultActivityPolicy) {
mLockState = lockState;
mUsersWithMatchingAccounts = new ArraySet<>(usersWithMatchingAccounts);
mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities);
mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities);
+ mDefaultActivityPolicy = defaultActivityPolicy;
}
@SuppressWarnings("unchecked")
@@ -86,6 +107,7 @@ public final class VirtualDeviceParams implements Parcelable {
mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null);
mAllowedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
mBlockedActivities = (ArraySet<ComponentName>) parcel.readArraySet(null);
+ mDefaultActivityPolicy = parcel.readInt();
}
/**
@@ -113,12 +135,10 @@ public final class VirtualDeviceParams implements Parcelable {
*
* @see Builder#setAllowedActivities(Set)
*/
- // Null and empty have different semantics - Null allows all activities to be streamed
- @SuppressLint("NullableCollection")
- @Nullable
+ @NonNull
public Set<ComponentName> getAllowedActivities() {
if (mAllowedActivities == null) {
- return null;
+ return Collections.emptySet();
}
return Collections.unmodifiableSet(mAllowedActivities);
}
@@ -129,16 +149,27 @@ public final class VirtualDeviceParams implements Parcelable {
*
* @see Builder#setBlockedActivities(Set)
*/
- // Allowing null to enforce that at most one of allowed / blocked activities can be non-null
- @SuppressLint("NullableCollection")
- @Nullable
+ @NonNull
public Set<ComponentName> getBlockedActivities() {
if (mBlockedActivities == null) {
- return null;
+ return Collections.emptySet();
}
return Collections.unmodifiableSet(mBlockedActivities);
}
+ /**
+ * Returns {@link #ACTIVITY_POLICY_DEFAULT_ALLOWED} if activities are allowed to launch on this
+ * virtual device by default, or {@link #ACTIVITY_POLICY_DEFAULT_BLOCKED} if activities must be
+ * allowed by {@link Builder#setAllowedActivities} to launch here.
+ *
+ * @see Builder#setBlockedActivities
+ * @see Builder#setAllowedActivities
+ */
+ @ActivityPolicy
+ public int getDefaultActivityPolicy() {
+ return mDefaultActivityPolicy;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -150,6 +181,7 @@ public final class VirtualDeviceParams implements Parcelable {
dest.writeArraySet(mUsersWithMatchingAccounts);
dest.writeArraySet(mAllowedActivities);
dest.writeArraySet(mBlockedActivities);
+ dest.writeInt(mDefaultActivityPolicy);
}
@Override
@@ -164,12 +196,15 @@ public final class VirtualDeviceParams implements Parcelable {
return mLockState == that.mLockState
&& mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts)
&& Objects.equals(mAllowedActivities, that.mAllowedActivities)
- && Objects.equals(mBlockedActivities, that.mBlockedActivities);
+ && Objects.equals(mBlockedActivities, that.mBlockedActivities)
+ && mDefaultActivityPolicy == that.mDefaultActivityPolicy;
}
@Override
public int hashCode() {
- return Objects.hash(mLockState, mUsersWithMatchingAccounts);
+ return Objects.hash(
+ mLockState, mUsersWithMatchingAccounts, mAllowedActivities, mBlockedActivities,
+ mDefaultActivityPolicy);
}
@Override
@@ -180,6 +215,7 @@ public final class VirtualDeviceParams implements Parcelable {
+ " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts
+ " mAllowedActivities=" + mAllowedActivities
+ " mBlockedActivities=" + mBlockedActivities
+ + " mDefaultActivityPolicy=" + mDefaultActivityPolicy
+ ")";
}
@@ -202,8 +238,11 @@ public final class VirtualDeviceParams implements Parcelable {
private @LockState int mLockState = LOCK_STATE_DEFAULT;
private Set<UserHandle> mUsersWithMatchingAccounts;
- @Nullable private Set<ComponentName> mBlockedActivities;
- @Nullable private Set<ComponentName> mAllowedActivities;
+ @NonNull private Set<ComponentName> mBlockedActivities = Collections.emptySet();
+ @NonNull private Set<ComponentName> mAllowedActivities = Collections.emptySet();
+ @ActivityPolicy
+ private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
+ private boolean mDefaultActivityPolicyConfigured = false;
/**
* Sets the lock state of the device. The permission {@code ADD_ALWAYS_UNLOCKED_DISPLAY}
@@ -248,53 +287,53 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
- * 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.
+ * Sets the activities allowed to be launched in the virtual device. Calling this method
+ * will cause {@link #getDefaultActivityPolicy()} to be
+ * {@link #ACTIVITY_POLICY_DEFAULT_BLOCKED}, meaning activities not in
+ * {@code allowedActivities} will be blocked from launching here.
*
- * <p>{@code allowedActivities} and the set in {@link #setBlockedActivities(Set)} cannot
- * both be non-null at the same time.
+ * <p>This method must not be called if {@link #setBlockedActivities(Set)} has been called.
*
- * @throws IllegalArgumentException if {@link #setBlockedActivities(Set)} has been set to a
- * non-null value.
+ * @throws IllegalArgumentException if {@link #setBlockedActivities(Set)} has been called.
*
* @param allowedActivities A set of activity {@link ComponentName} allowed to be launched
* in the virtual device.
*/
- // Null and empty have different semantics - Null allows all activities to be streamed
- @SuppressLint("NullableCollection")
@NonNull
- public Builder setAllowedActivities(@Nullable Set<ComponentName> allowedActivities) {
- if (mBlockedActivities != null && allowedActivities != null) {
+ public Builder setAllowedActivities(@NonNull Set<ComponentName> allowedActivities) {
+ if (mDefaultActivityPolicyConfigured
+ && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_BLOCKED) {
throw new IllegalArgumentException(
"Allowed activities and Blocked activities cannot both be set.");
}
+ mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_BLOCKED;
+ mDefaultActivityPolicyConfigured = true;
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.
+ * Sets the activities blocked from launching in the virtual device. Calling this method
+ * will cause {@link #getDefaultActivityPolicy()} to be
+ * {@link #ACTIVITY_POLICY_DEFAULT_ALLOWED}, meaning activities are allowed to launch here
+ * unless they are in {@code blockedActivities}.
*
- * {@code blockedActivities} and the set in {@link #setAllowedActivities(Set)} cannot both
- * be non-null at the same time.
+ * <p>This method must not be called if {@link #setAllowedActivities(Set)} has been called.
*
- * @throws IllegalArgumentException if {@link #setAllowedActivities(Set)} has been set to a
- * non-null value.
+ * @throws IllegalArgumentException if {@link #setAllowedActivities(Set)} has been called.
*
* @param blockedActivities A set of {@link ComponentName} to be blocked launching from
* virtual device.
*/
- // Allowing null to enforce that at most one of allowed / blocked activities can be non-null
- @SuppressLint("NullableCollection")
@NonNull
- public Builder setBlockedActivities(@Nullable Set<ComponentName> blockedActivities) {
- if (mAllowedActivities != null && blockedActivities != null) {
+ public Builder setBlockedActivities(@NonNull Set<ComponentName> blockedActivities) {
+ if (mDefaultActivityPolicyConfigured
+ && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_ALLOWED) {
throw new IllegalArgumentException(
"Allowed activities and Blocked activities cannot both be set.");
}
+ mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED;
+ mDefaultActivityPolicyConfigured = true;
mBlockedActivities = blockedActivities;
return this;
}
@@ -307,13 +346,12 @@ public final class VirtualDeviceParams implements Parcelable {
if (mUsersWithMatchingAccounts == null) {
mUsersWithMatchingAccounts = Collections.emptySet();
}
- 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);
+ return new VirtualDeviceParams(
+ mLockState,
+ mUsersWithMatchingAccounts,
+ mAllowedActivities,
+ mBlockedActivities,
+ mDefaultActivityPolicy);
}
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index bc1f28d1c373..b991ba87eef4 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -24,6 +24,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
+import android.companion.virtual.VirtualDeviceParams;
+import android.companion.virtual.VirtualDeviceParams.ActivityPolicy;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
@@ -77,7 +79,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
@Nullable
private final ArraySet<ComponentName> mBlockedActivities;
private final Object mGenericWindowPolicyControllerLock = new Object();
- private Consumer<ActivityInfo> mActivityBlockedCallback;
+ @ActivityPolicy
+ private final int mDefaultActivityPolicy;
+ private final Consumer<ActivityInfo> mActivityBlockedCallback;
@NonNull
@GuardedBy("mGenericWindowPolicyControllerLock")
@@ -95,18 +99,30 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
* @param windowFlags The window flags that this controller is interested in.
* @param systemWindowFlags The system window flags that this controller is interested in.
* @param allowedUsers The set of users that are allowed to stream in this display.
+ * @param allowedActivities The set of activities explicitly allowed to stream on this device.
+ * Used only if the {@code activityPolicy} is
+ * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_BLOCKED}.
+ * @param blockedActivities The set of activities explicitly blocked from streaming on this
+ * device. Used only if the {@code activityPolicy} is
+ * {@link VirtualDeviceParams#ACTIVITY_POLICY_DEFAULT_ALLOWED}
+ * @param defaultActivityPolicy Whether activities are default allowed to be displayed or
+ * blocked.
* @param activityListener Activity listener to listen for activity changes. The display ID
* is not populated in this callback and is always {@link Display#INVALID_DISPLAY}.
+ * @param activityBlockedCallback Callback that is called when an activity is blocked from
+ * launching.
*/
public GenericWindowPolicyController(int windowFlags, int systemWindowFlags,
@NonNull ArraySet<UserHandle> allowedUsers,
- @Nullable Set<ComponentName> allowedActivities,
- @Nullable Set<ComponentName> blockedActivities,
+ @NonNull Set<ComponentName> allowedActivities,
+ @NonNull Set<ComponentName> blockedActivities,
+ @ActivityPolicy int defaultActivityPolicy,
@NonNull ActivityListener activityListener,
@NonNull Consumer<ActivityInfo> activityBlockedCallback) {
mAllowedUsers = allowedUsers;
- mAllowedActivities = allowedActivities == null ? null : new ArraySet<>(allowedActivities);
- mBlockedActivities = blockedActivities == null ? null : new ArraySet<>(blockedActivities);
+ mAllowedActivities = new ArraySet<>(allowedActivities);
+ mBlockedActivities = new ArraySet<>(blockedActivities);
+ mDefaultActivityPolicy = defaultActivityPolicy;
mActivityBlockedCallback = activityBlockedCallback;
setInterestedWindowFlags(windowFlags, systemWindowFlags);
mActivityListener = activityListener;
@@ -191,11 +207,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
Slog.d(TAG, "Virtual device activity not allowed from user " + activityUser);
return false;
}
- if (mBlockedActivities != null && mBlockedActivities.contains(activityComponent)) {
+ if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED
+ && mBlockedActivities.contains(activityComponent)) {
Slog.d(TAG, "Virtual device blocking launch of " + activityComponent);
return false;
}
- if (mAllowedActivities != null && !mAllowedActivities.contains(activityComponent)) {
+ if (mDefaultActivityPolicy == VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_BLOCKED
+ && !mAllowedActivities.contains(activityComponent)) {
Slog.d(TAG, activityComponent + " is not in the allowed list.");
return false;
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index c0a904fe3d9a..dbb48aea94ff 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -505,6 +505,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
getAllowedUserHandles(),
mParams.getAllowedActivities(),
mParams.getBlockedActivities(),
+ mParams.getDefaultActivityPolicy(),
createListenerAdapter(displayId),
activityInfo -> onActivityBlocked(displayId, activityInfo));
mWindowPolicyControllers.put(displayId, dwpc);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index 3160272ef9b1..f0c907d49a46 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import android.companion.virtual.VirtualDeviceParams;
import android.companion.virtual.audio.IAudioSessionCallback;
import android.content.Context;
import android.content.ContextWrapper;
@@ -72,7 +73,8 @@ public class VirtualAudioControllerTest {
/* allowedUsers= */ new ArraySet<>(),
/* allowedActivities= */ new ArraySet<>(),
/* blockedActivities= */ new ArraySet<>(),
- /* activityListener= */null,
+ VirtualDeviceParams.ACTIVITY_POLICY_DEFAULT_ALLOWED,
+ /* activityListener= */ null,
/* activityBlockedCallback= */ null);
}