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

Commit 269fcb68 authored by Alex Johnston's avatar Alex Johnston
Browse files

Enforce DevicePolicyManager.setUserControlDisabledPackages in AppStandbyController

When deciding an app's standby bucket, check if the
app has its user control disabled by an IT admin. If so,
the app should be the exempted restricted bucket.

Bug: 272042183
Test: atest AppStandbyControllerTests
Change-Id: I4279dc37f0e17aedb1c2a87468478248443a253e
parent f2de79eb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -225,6 +225,8 @@ public interface AppStandbyInternal {

    void setActiveAdminApps(Set<String> adminPkgs, int userId);

    void setAdminProtectedPackages(Set<String> packageNames, int userId);

    /**
     * @return {@code true} if the given package is an active device admin app.
     */
+40 −0
Original line number Diff line number Diff line
@@ -268,6 +268,10 @@ public class AppStandbyController
    @GuardedBy("mActiveAdminApps")
    private final SparseArray<Set<String>> mActiveAdminApps = new SparseArray<>();

    /** List of admin protected packages. Can contain {@link android.os.UserHandle#USER_ALL}. */
    @GuardedBy("mAdminProtectedPackages")
    private final SparseArray<Set<String>> mAdminProtectedPackages = new SparseArray<>();

    /**
     * Set of system apps that are headless (don't have any "front door" activities, enabled or
     * disabled). Presence in this map indicates that the app is a headless system app.
@@ -1380,6 +1384,9 @@ public class AppStandbyController
            synchronized (mActiveAdminApps) {
                mActiveAdminApps.remove(userId);
            }
            synchronized (mAdminProtectedPackages) {
                mAdminProtectedPackages.remove(userId);
            }
        }
    }

@@ -1469,6 +1476,10 @@ public class AppStandbyController
                return STANDBY_BUCKET_EXEMPTED;
            }

            if (isAdminProtectedPackages(packageName, userId)) {
                return STANDBY_BUCKET_EXEMPTED;
            }

            if (isActiveNetworkScorer(packageName)) {
                return STANDBY_BUCKET_EXEMPTED;
            }
@@ -1948,6 +1959,17 @@ public class AppStandbyController
        }
    }

    private boolean isAdminProtectedPackages(String packageName, int userId) {
        synchronized (mAdminProtectedPackages) {
            if (mAdminProtectedPackages.contains(UserHandle.USER_ALL)
                    && mAdminProtectedPackages.get(UserHandle.USER_ALL).contains(packageName)) {
                return true;
            }
            return mAdminProtectedPackages.contains(userId)
                    && mAdminProtectedPackages.get(userId).contains(packageName);
        }
    }

    @Override
    public void addActiveDeviceAdmin(String adminPkg, int userId) {
        synchronized (mActiveAdminApps) {
@@ -1971,6 +1993,17 @@ public class AppStandbyController
        }
    }

    @Override
    public void setAdminProtectedPackages(Set<String> packageNames, int userId) {
        synchronized (mAdminProtectedPackages) {
            if (packageNames == null || packageNames.isEmpty()) {
                mAdminProtectedPackages.remove(userId);
            } else {
                mAdminProtectedPackages.put(userId, packageNames);
            }
        }
    }

    @Override
    public void onAdminDataAvailable() {
        mAdminDataAvailableLatch.countDown();
@@ -1993,6 +2026,13 @@ public class AppStandbyController
        }
    }

    @VisibleForTesting
    Set<String> getAdminProtectedPackagesForTest(int userId) {
        synchronized (mAdminProtectedPackages) {
            return mAdminProtectedPackages.get(userId);
        }
    }

    /**
     * Returns {@code true} if the supplied package is the device provisioning app. Otherwise,
     * returns {@code false}.
+2 −3
Original line number Diff line number Diff line
@@ -15818,9 +15818,8 @@ public class DevicePolicyManager {
     * Called by a device owner or a profile owner or holder of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_APPS_CONTROL} to disable user
     * control over apps. User will not be able to clear app data or force-stop packages. When
     * called by a device owner, applies to all users on the device. Starting from Android 13,
     * packages with user control disabled are exempted from being put in the "restricted" App
     * Standby Bucket.
     * called by a device owner, applies to all users on the device. Packages with user control
     * disabled are exempted from App Standby Buckets.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Null if the
     *               caller is not a device admin.
+10 −0
Original line number Diff line number Diff line
@@ -202,6 +202,16 @@ public abstract class UsageStatsManagerInternal {
     */
    public abstract void setActiveAdminApps(Set<String> adminApps, int userId);

    /**
     * Called by DevicePolicyManagerService to inform about the protected packages for a user.
     * User control will be disabled for protected packages.
     *
     * @param packageNames the set of protected packages for {@code userId}.
     * @param userId the userId to which the protected packages belong.
     */
    public abstract void setAdminProtectedPackages(@Nullable Set<String> packageNames,
            @UserIdInt int userId);

    /**
     * Called by DevicePolicyManagerService during boot to inform that admin data is loaded and
     * pushed to UsageStatsService.
+2 −0
Original line number Diff line number Diff line
@@ -3554,6 +3554,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        mInjector.binderWithCleanCallingIdentity(() ->
                mInjector.getPackageManagerInternal().setOwnerProtectedPackages(
                        targetUserId, protectedPackages));
        mUsageStatsManagerInternal.setAdminProtectedPackages(new ArraySet(protectedPackages),
                targetUserId);
    }
    void handleUnlockUser(int userId) {
Loading