Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c53c6b36 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski
Browse files

Package level activity policy API in VDM

Bug: 333443509
Test: presubmit, CTS
Flag: android.companion.virtualdevice.flags.activity_control_api
Change-Id: I7becc6fa8b85ec2f7262014d5636feff82cad7aa
parent 753160d9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3465,7 +3465,9 @@ package android.companion.virtual {
  public static class VirtualDeviceManager.VirtualDevice implements java.lang.AutoCloseable {
    method public void addActivityListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
    method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull android.content.ComponentName);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull String);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull android.content.ComponentName, int);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void addActivityPolicyExemption(@NonNull String, int);
    method public void addSoundEffectListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
    method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
    method @NonNull public android.content.Context createContext();
@@ -3490,7 +3492,9 @@ package android.companion.virtual {
    method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void registerIntentInterceptor(@NonNull android.content.IntentFilter, @NonNull java.util.concurrent.Executor, @NonNull android.companion.virtual.VirtualDeviceManager.IntentInterceptorCallback);
    method public void removeActivityListener(@NonNull android.companion.virtual.VirtualDeviceManager.ActivityListener);
    method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName);
    method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull String);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull android.content.ComponentName, int);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void removeActivityPolicyExemption(@NonNull String, int);
    method public void removeSoundEffectListener(@NonNull android.companion.virtual.VirtualDeviceManager.SoundEffectListener);
    method @FlaggedApi("android.companion.virtual.flags.dynamic_policy") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int);
    method @FlaggedApi("android.companion.virtualdevice.flags.activity_control_api") @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void setDevicePolicy(int, int, int);
+24 −0
Original line number Diff line number Diff line
@@ -111,6 +111,18 @@ interface IVirtualDevice {
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void removeActivityPolicyExemption(in ComponentName exemption);

    /**
     * Adds a package level exemption to the default activity launch policy.
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void addActivityPolicyPackageExemption(in String exemption);

    /**
     * Removes a package level exemption to the default activity launch policy.
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void removeActivityPolicyPackageExemption(in String exemption);

    /**
     * Specifies a policy for this virtual device on the given display.
     */
@@ -129,6 +141,18 @@ interface IVirtualDevice {
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void removeActivityPolicyExemptionForDisplay(int displayId, in ComponentName exemption);

    /**
     * Adds a package level exemption to the default activity launch policy on the given display.
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void addActivityPolicyPackageExemptionForDisplay(int displayId, in String exemption);

    /**
     * Removes a package level exemption to the default activity launch policy on the given display.
     */
    @EnforcePermission("CREATE_VIRTUAL_DEVICE")
    void removeActivityPolicyPackageExemptionForDisplay(int displayId, in String exemption);

    /**
     * Notifies that an audio session being started.
     */
+34 −0
Original line number Diff line number Diff line
@@ -321,6 +321,23 @@ public class VirtualDeviceInternal {
        }
    }

    void addActivityPolicyPackageExemption(@NonNull String packageName) {
        try {
            mVirtualDevice.addActivityPolicyPackageExemption(packageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    void removeActivityPolicyPackageExemption(@NonNull String packageName) {
        try {
            mVirtualDevice.removeActivityPolicyPackageExemption(packageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    void setDevicePolicyForDisplay(int displayId,
            @VirtualDeviceParams.DynamicDisplayPolicyType int policyType,
            @VirtualDeviceParams.DevicePolicy int devicePolicy) {
@@ -357,6 +374,23 @@ public class VirtualDeviceInternal {
        }
    }

    void addActivityPolicyPackageExemptionForDisplay(int displayId, @NonNull String packageName) {
        try {
            mVirtualDevice.addActivityPolicyPackageExemptionForDisplay(displayId, packageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    void removeActivityPolicyPackageExemptionForDisplay(int displayId,
            @NonNull String packageName) {
        try {
            mVirtualDevice.removeActivityPolicyPackageExemptionForDisplay(displayId, packageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    @NonNull
    VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
        try {
+129 −0
Original line number Diff line number Diff line
@@ -798,6 +798,62 @@ public final class VirtualDeviceManager {
                    Objects.requireNonNull(componentName));
        }

        /**
         * Specifies a package name to be exempt from the current activity launch policy.
         *
         * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
         * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
         * then all activities from the specified package will be blocked from launching.
         * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
         * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then all
         * activities from the specified package will be allowed to launch.</p>
         *
         * <p>Package level exemptions are independent of component level exemptions added via
         * {@link #addActivityPolicyExemption(String)}, i.e. removing a package exemption will not
         * remove any existing component exemptions, even if the component belongs to that package.
         * </p>
         *
         * <p>Note that changing the activity launch policy will clear current set of exempt
         * packages.</p>
         *
         * @see #removeActivityPolicyExemption(String)
         * @see #setDevicePolicy
         */
        @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        public void addActivityPolicyExemption(@NonNull String packageName) {
            mVirtualDeviceInternal.addActivityPolicyPackageExemption(
                    Objects.requireNonNull(packageName));
        }

        /**
         * Makes the specified package name adhere to the default activity launch policy.
         *
         * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
         * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
         * then all activities from the specified package will be allowed to launch.
         * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
         * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then all
         * activities from the specified package will be blocked from launching.</p>
         *
         * <p>Package level exemptions are independent of component level exemptions added via
         * {@link #addActivityPolicyExemption(String)}, i.e. removing a package exemption will not
         * remove any existing component exemptions, even if the component belongs to that package.
         * </p>
         *
         * <p>Note that changing the activity launch policy will clear current set of exempt
         * packages.</p>
         *
         * @see #addActivityPolicyExemption(String)
         * @see #setDevicePolicy
         */
        @FlaggedApi(Flags.FLAG_DYNAMIC_POLICY)
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        public void removeActivityPolicyExemption(@NonNull String packageName) {
            mVirtualDeviceInternal.removeActivityPolicyPackageExemption(
                    Objects.requireNonNull(packageName));
        }

        /**
         * Specifies a policy for this virtual device to be applied on the given virtual display.
         * <p>
@@ -887,6 +943,79 @@ public final class VirtualDeviceManager {
                    displayId, Objects.requireNonNull(componentName));
        }

        /**
         * Specifies a package name to be exempt from the given display's activity launch policy.
         *
         * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
         * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
         * then all activities from the specified package will be blocked from launching.
         * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
         * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then all
         * activities from the specified package will be allowed to launch.</p>
         *
         * <p>Note that changing the activity launch policy will clear current set of exempt
         * packages.</p>
         * <p>Any change to the exemptions will only be applied for new activity launches.</p>
         *
         * <p>Package level exemptions are independent of component level exemptions added via
         * {@link #addActivityPolicyExemption(String, int)}, i.e. removing a package exemption will
         * not remove any existing component exemptions, even if the component belongs to that
         * package.</p>
         *
         * @param packageName the package name to be exempt from the activity launch policy. All
         *   activities from that package will be exempt.
         * @param displayId the ID of the display, for which to apply the exemption. The display
         *   must belong to the virtual device.
         * @throws IllegalArgumentException if the specified display does not belong to the virtual
         *   device.
         *
         * @see #removeActivityPolicyExemption(String, int)
         * @see #setDevicePolicy
         * @see Display#getDisplayId
         */
        @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        public void addActivityPolicyExemption(@NonNull String packageName, int displayId) {
            mVirtualDeviceInternal.addActivityPolicyPackageExemptionForDisplay(
                    displayId, Objects.requireNonNull(packageName));
        }

        /**
         * Makes the specified package name adhere to the given display's activity launch policy.
         *
         * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity
         * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}),
         * then all activities from the specified package will be allowed to launch.
         * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches
         * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then all
         * activities from the specified package will be blocked from launching.</p>
         *
         * <p>Note that changing the activity launch policy will clear current set of exempt
         * packages.</p>
         *
         * <p>Package level exemptions are independent of component level exemptions added via
         * {@link #addActivityPolicyExemption(String, int)}, i.e. removing a package exemption will
         * not remove any existing component exemptions, even if the component belongs to that
         * package.</p>
         *
         * @param packageName the package name to be removed from the exemption list. All activities
         *   from that package stop being exempt from the activity launch policy.
         * @param displayId the ID of the display, for which to apply the exemption. The display
         *   must belong to the virtual device.
         * @throws IllegalArgumentException if the specified display does not belong to the virtual
         *   device.
         *
         * @see #addActivityPolicyExemption(String, int)
         * @see #setDevicePolicy
         * @see Display#getDisplayId
         */
        @FlaggedApi(android.companion.virtualdevice.flags.Flags.FLAG_ACTIVITY_CONTROL_API)
        @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
        public void removeActivityPolicyExemption(@NonNull String packageName, int displayId) {
            mVirtualDeviceInternal.removeActivityPolicyPackageExemptionForDisplay(
                    displayId, Objects.requireNonNull(packageName));
        }

        /**
         * Creates a virtual dpad.
         *
+35 −8
Original line number Diff line number Diff line
@@ -110,10 +110,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
    @NonNull
    @GuardedBy("mGenericWindowPolicyControllerLock")
    private final ArraySet<ComponentName> mActivityPolicyExemptions;
    @NonNull
    @GuardedBy("mGenericWindowPolicyControllerLock")
    private final ArraySet<String> mActivityPolicyPackageExemptions;
    private final boolean mCrossTaskNavigationAllowedByDefault;
    @NonNull
    private final ArraySet<ComponentName> mCrossTaskNavigationExemptions;
    @Nullable
    @NonNull
    private final Object mGenericWindowPolicyControllerLock = new Object();
    @Nullable private final ActivityBlockedCallback mActivityBlockedCallback;

@@ -152,6 +155,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
     *   or blocked.
     * @param activityPolicyExemptions The set of activities explicitly exempt from the default
     *   activity policy.
     * @param activityPolicyPackageExemptions The set of packages whose activities are explicitly
     *   exempt from the default activity policy.
     * @param crossTaskNavigationAllowedByDefault Whether cross task navigations are allowed by
     *   default or not.
     * @param crossTaskNavigationExemptions The set of components explicitly exempt from the default
@@ -176,6 +181,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
            @NonNull ArraySet<UserHandle> allowedUsers,
            boolean activityLaunchAllowedByDefault,
            @NonNull Set<ComponentName> activityPolicyExemptions,
            @NonNull Set<String> activityPolicyPackageExemptions,
            boolean crossTaskNavigationAllowedByDefault,
            @NonNull Set<ComponentName> crossTaskNavigationExemptions,
            @Nullable ActivityListener activityListener,
@@ -190,6 +196,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
        mAllowedUsers = allowedUsers;
        mActivityLaunchAllowedByDefault = activityLaunchAllowedByDefault;
        mActivityPolicyExemptions = new ArraySet<>(activityPolicyExemptions);
        mActivityPolicyPackageExemptions = new ArraySet<>(activityPolicyPackageExemptions);
        mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault;
        mCrossTaskNavigationExemptions = new ArraySet<>(crossTaskNavigationExemptions);
        mActivityBlockedCallback = activityBlockedCallback;
@@ -250,6 +257,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
        synchronized (mGenericWindowPolicyControllerLock) {
            if (mActivityLaunchAllowedByDefault != activityLaunchDefaultAllowed) {
                mActivityPolicyExemptions.clear();
                mActivityPolicyPackageExemptions.clear();
            }
            mActivityLaunchAllowedByDefault = activityLaunchDefaultAllowed;
        }
@@ -267,6 +275,18 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
        }
    }

    void addActivityPolicyExemption(@NonNull String packageName) {
        synchronized (mGenericWindowPolicyControllerLock) {
            mActivityPolicyPackageExemptions.add(packageName);
        }
    }

    void removeActivityPolicyExemption(@NonNull String packageName) {
        synchronized (mGenericWindowPolicyControllerLock) {
            mActivityPolicyPackageExemptions.remove(packageName);
        }
    }

    /** Register a listener for running applications changes. */
    public void registerRunningAppsChangedListener(@NonNull RunningAppsChangedListener listener) {
        synchronized (mGenericWindowPolicyControllerLock) {
@@ -343,14 +363,11 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
                    + mDisplayCategories);
            return false;
        }
        synchronized (mGenericWindowPolicyControllerLock) {
            if (!isAllowedByPolicy(mActivityLaunchAllowedByDefault, mActivityPolicyExemptions,
                    activityComponent)) {
        if (!isAllowedByPolicy(activityComponent)) {
            logActivityLaunchBlocked("Activity launch disallowed by policy: "
                    + activityComponent);
            return false;
        }
        }
        if (isNewTask && launchingFromDisplayId != DEFAULT_DISPLAY
                && !isAllowedByPolicy(mCrossTaskNavigationAllowedByDefault,
                        mCrossTaskNavigationExemptions, activityComponent)) {
@@ -475,6 +492,16 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController
                mAttributionSource.getUid());
    }

    private boolean isAllowedByPolicy(ComponentName component) {
        synchronized (mGenericWindowPolicyControllerLock) {
            if (mActivityPolicyExemptions.contains(component)
                    || mActivityPolicyPackageExemptions.contains(component.getPackageName())) {
                return !mActivityLaunchAllowedByDefault;
            }
            return mActivityLaunchAllowedByDefault;
        }
    }

    private static boolean isAllowedByPolicy(boolean allowedByDefault,
            Set<ComponentName> exemptions, ComponentName component) {
        // Either allowed and the exemptions do not contain the component,
Loading