
QPR3 is delayed a week now Patches pulled from GrapheneOS and checked against CalyxOS Signed-off-by: Tad <tad@spotco.us>
253 lines
12 KiB
Diff
253 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Alex Johnston <acjohnston@google.com>
|
|
Date: Wed, 8 Mar 2023 22:28:28 +0000
|
|
Subject: [PATCH 08/10] 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
|
|
(cherry picked from commit 269fcb6873dee199dd8023831f882aafff1f6291)
|
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:99b199d1139f50dbecba4f4bdc8066c6d0c28b5b)
|
|
Merged-In: I4279dc37f0e17aedb1c2a87468478248443a253e
|
|
Change-Id: I4279dc37f0e17aedb1c2a87468478248443a253e
|
|
---
|
|
.../server/usage/AppStandbyInternal.java | 2 +
|
|
.../server/usage/AppStandbyController.java | 40 +++++++++++++++++++
|
|
.../app/admin/DevicePolicyManager.java | 3 +-
|
|
.../app/usage/UsageStatsManagerInternal.java | 10 +++++
|
|
.../DevicePolicyManagerService.java | 2 +
|
|
.../usage/AppStandbyControllerTests.java | 38 ++++++++++++++++++
|
|
.../server/usage/UsageStatsService.java | 5 +++
|
|
7 files changed, 99 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
|
|
index 9b64edf53d8c..f50a90248030 100644
|
|
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
|
|
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
|
|
@@ -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.
|
|
*/
|
|
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
|
|
index a6f47d4e4908..b27ff411dd58 100644
|
|
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
|
|
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
|
|
@@ -264,6 +264,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.
|
|
@@ -1335,6 +1339,9 @@ public class AppStandbyController
|
|
synchronized (mActiveAdminApps) {
|
|
mActiveAdminApps.remove(userId);
|
|
}
|
|
+ synchronized (mAdminProtectedPackages) {
|
|
+ mAdminProtectedPackages.remove(userId);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -1424,6 +1431,10 @@ public class AppStandbyController
|
|
return STANDBY_BUCKET_EXEMPTED;
|
|
}
|
|
|
|
+ if (isAdminProtectedPackages(packageName, userId)) {
|
|
+ return STANDBY_BUCKET_EXEMPTED;
|
|
+ }
|
|
+
|
|
if (isActiveNetworkScorer(packageName)) {
|
|
return STANDBY_BUCKET_EXEMPTED;
|
|
}
|
|
@@ -1871,6 +1882,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) {
|
|
@@ -1894,6 +1916,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();
|
|
@@ -1916,6 +1949,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}.
|
|
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
|
|
index f563fdb28953..af42dd3dfc76 100644
|
|
--- a/core/java/android/app/admin/DevicePolicyManager.java
|
|
+++ b/core/java/android/app/admin/DevicePolicyManager.java
|
|
@@ -14625,7 +14625,8 @@ public class DevicePolicyManager {
|
|
/**
|
|
* Called by a device owner or a profile owner 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.
|
|
+ * 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
|
|
* @param packages The package names for the apps.
|
|
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
|
|
index a35aa7c74ee5..ee70e2ff50ce 100644
|
|
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
|
|
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
|
|
@@ -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.
|
|
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
|
|
index 515d6dc9cab1..e95f827ff6f1 100644
|
|
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
|
|
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
|
|
@@ -3202,6 +3202,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|
mInjector.binderWithCleanCallingIdentity(() ->
|
|
mInjector.getPackageManagerInternal().setOwnerProtectedPackages(
|
|
targetUserId, protectedPackages));
|
|
+ mUsageStatsManagerInternal.setAdminProtectedPackages(new ArraySet(protectedPackages),
|
|
+ targetUserId);
|
|
}
|
|
|
|
@Override
|
|
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
|
|
index 308a4b67de24..e2db7584a2a6 100644
|
|
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
|
|
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
|
|
@@ -158,6 +158,9 @@ public class AppStandbyControllerTests {
|
|
private static final String ADMIN_PKG2 = "com.android.admin2";
|
|
private static final String ADMIN_PKG3 = "com.android.admin3";
|
|
|
|
+ private static final String ADMIN_PROTECTED_PKG = "com.android.admin.protected";
|
|
+ private static final String ADMIN_PROTECTED_PKG2 = "com.android.admin.protected2";
|
|
+
|
|
private static final long MINUTE_MS = 60 * 1000;
|
|
private static final long HOUR_MS = 60 * MINUTE_MS;
|
|
private static final long DAY_MS = 24 * HOUR_MS;
|
|
@@ -1750,6 +1753,19 @@ public class AppStandbyControllerTests {
|
|
assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
|
|
}
|
|
|
|
+ @Test
|
|
+ public void testSetAdminProtectedPackages() {
|
|
+ assertAdminProtectedPackagesForTest(USER_ID, (String[]) null);
|
|
+ assertAdminProtectedPackagesForTest(USER_ID2, (String[]) null);
|
|
+
|
|
+ setAdminProtectedPackages(USER_ID, ADMIN_PROTECTED_PKG, ADMIN_PROTECTED_PKG2);
|
|
+ assertAdminProtectedPackagesForTest(USER_ID, ADMIN_PROTECTED_PKG, ADMIN_PROTECTED_PKG2);
|
|
+ assertAdminProtectedPackagesForTest(USER_ID2, (String[]) null);
|
|
+
|
|
+ setAdminProtectedPackages(USER_ID, (String[]) null);
|
|
+ assertAdminProtectedPackagesForTest(USER_ID, (String[]) null);
|
|
+ }
|
|
+
|
|
@Test
|
|
@FlakyTest(bugId = 185169504)
|
|
public void testUserInteraction_CrossProfile() throws Exception {
|
|
@@ -2144,6 +2160,28 @@ public class AppStandbyControllerTests {
|
|
mController.setActiveAdminApps(new ArraySet<>(Arrays.asList(admins)), userId);
|
|
}
|
|
|
|
+ private void setAdminProtectedPackages(int userId, String... packageNames) {
|
|
+ Set<String> adminProtectedPackages = packageNames != null ? new ArraySet<>(
|
|
+ Arrays.asList(packageNames)) : null;
|
|
+ mController.setAdminProtectedPackages(adminProtectedPackages, userId);
|
|
+ }
|
|
+
|
|
+ private void assertAdminProtectedPackagesForTest(int userId, String... packageNames) {
|
|
+ final Set<String> actualAdminProtectedPackages =
|
|
+ mController.getAdminProtectedPackagesForTest(userId);
|
|
+ if (packageNames == null) {
|
|
+ if (actualAdminProtectedPackages != null && !actualAdminProtectedPackages.isEmpty()) {
|
|
+ fail("Admin protected packages should be null; " + getAdminAppsStr(userId,
|
|
+ actualAdminProtectedPackages));
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ assertEquals(packageNames.length, actualAdminProtectedPackages.size());
|
|
+ for (String adminProtectedPackage : packageNames) {
|
|
+ assertTrue(actualAdminProtectedPackages.contains(adminProtectedPackage));
|
|
+ }
|
|
+ }
|
|
+
|
|
private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception {
|
|
rearmLatch(pkg);
|
|
mController.setAppStandbyBucket(pkg, user, bucket, reason);
|
|
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
|
|
index ea40100227c4..71644d08e720 100644
|
|
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
|
|
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
|
|
@@ -3086,6 +3086,11 @@ public class UsageStatsService extends SystemService implements
|
|
mAppStandby.setActiveAdminApps(packageNames, userId);
|
|
}
|
|
|
|
+ @Override
|
|
+ public void setAdminProtectedPackages(Set<String> packageNames, int userId) {
|
|
+ mAppStandby.setAdminProtectedPackages(packageNames, userId);
|
|
+ }
|
|
+
|
|
@Override
|
|
public void onAdminDataAvailable() {
|
|
mAppStandby.onAdminDataAvailable();
|