Merge "Specify default activity policy" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
47d52ee0bf
@@ -2823,11 +2823,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
|
||||
@@ -2836,8 +2839,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>);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user