Merge "[RESTRICT AUTOMERGE] Add BubbleMetadata detection to block FSI" into sc-dev
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 8c06338..4be7b3f 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -157,6 +157,8 @@
void setActiveAdminApps(Set<String> adminPkgs, int userId);
+ void setAdminProtectedPackages(Set<String> packageNames, int userId);
+
void onAdminDataAvailable();
void clearCarrierPrivilegedApps();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 7a28407..7799c2f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -733,6 +733,10 @@
}
} catch (XmlPullParserException | IOException e) {
Slog.wtf(TAG, "Error jobstore xml.", e);
+ } catch (Exception e) {
+ // Crashing at this point would result in a boot loop, so live with a general
+ // Exception for system stability's sake.
+ Slog.wtf(TAG, "Unexpected exception", e);
} finally {
if (mPersistInfo.countAllJobsLoaded < 0) { // Only set them once.
mPersistInfo.countAllJobsLoaded = numJobs;
@@ -869,6 +873,9 @@
} catch (IOException e) {
Slog.d(TAG, "Error I/O Exception.", e);
return null;
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Constraints contained invalid data", e);
+ return null;
}
parser.next(); // Consume </constraints>
@@ -965,8 +972,14 @@
return null;
}
- PersistableBundle extras = PersistableBundle.restoreFromXml(parser);
- jobBuilder.setExtras(extras);
+ final PersistableBundle extras;
+ try {
+ extras = PersistableBundle.restoreFromXml(parser);
+ jobBuilder.setExtras(extras);
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "Persisted extras contained invalid data", e);
+ return null;
+ }
parser.nextTag(); // Consume </extras>
final JobInfo builtJob;
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 4b081d2..d23bef4 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -247,6 +247,10 @@
@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 declared activities, enabled or
* disabled). Presence in this map indicates that the app is a headless system app.
@@ -1088,6 +1092,9 @@
synchronized (mActiveAdminApps) {
mActiveAdminApps.remove(userId);
}
+ synchronized (mAdminProtectedPackages) {
+ mAdminProtectedPackages.remove(userId);
+ }
}
}
@@ -1177,6 +1184,10 @@
return STANDBY_BUCKET_EXEMPTED;
}
+ if (isAdminProtectedPackages(packageName, userId)) {
+ return STANDBY_BUCKET_EXEMPTED;
+ }
+
if (isActiveNetworkScorer(packageName)) {
return STANDBY_BUCKET_EXEMPTED;
}
@@ -1583,6 +1594,17 @@
}
}
+ 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) {
@@ -1607,6 +1629,17 @@
}
@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();
}
@@ -1628,6 +1661,13 @@
}
}
+ @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 1abbfa3..2d64126 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -13424,7 +13424,8 @@
/**
* Called by Device owner to disable user control over apps. User will not be able to clear
- * app data or force-stop packages.
+ * app data or force-stop packages. 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/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index ec56f9a..2f61fee 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -30,7 +30,6 @@
import android.os.Process;
import android.permission.PermissionManager;
import android.util.ArraySet;
-import android.util.Log;
import com.android.internal.annotations.Immutable;
@@ -87,8 +86,6 @@
*/
@Immutable
public final class AttributionSource implements Parcelable {
- private static final String TAG = "AttributionSource";
-
private static final String DESCRIPTOR = "android.content.AttributionSource";
private static final Binder sDefaultToken = new Binder(DESCRIPTOR);
@@ -156,20 +153,9 @@
AttributionSource(@NonNull Parcel in) {
this(AttributionSourceState.CREATOR.createFromParcel(in));
- if (!Binder.isHandlingTransaction()) {
- Log.e(TAG, "Unable to verify calling UID #" + mAttributionSourceState.uid + " PID #"
- + mAttributionSourceState.pid + " when not handling Binder transaction; "
- + "clearing.");
- mAttributionSourceState.pid = -1;
- mAttributionSourceState.uid = -1;
- mAttributionSourceState.packageName = null;
- mAttributionSourceState.attributionTag = null;
- mAttributionSourceState.next = null;
- } else {
- // Since we just unpacked this object as part of it transiting a Binder
- // call, this is the perfect time to enforce that its UID and PID can be trusted
- enforceCallingUidAndPid();
- }
+ // Since we just unpacked this object as part of it transiting a Binder
+ // call, this is the perfect time to enforce that its UID and PID can be trusted
+ enforceCallingUidAndPid();
}
/** @hide */
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
index bd9e760..c8bcabf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ServiceListing.java
@@ -35,6 +35,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Predicate;
/**
* Class for managing services matching a given intent and requesting a given permission.
@@ -51,12 +52,13 @@
private final HashSet<ComponentName> mEnabledServices = new HashSet<>();
private final List<ServiceInfo> mServices = new ArrayList<>();
private final List<Callback> mCallbacks = new ArrayList<>();
+ private final Predicate mValidator;
private boolean mListening;
private ServiceListing(Context context, String tag,
String setting, String intentAction, String permission, String noun,
- boolean addDeviceLockedFlags) {
+ boolean addDeviceLockedFlags, Predicate validator) {
mContentResolver = context.getContentResolver();
mContext = context;
mTag = tag;
@@ -65,6 +67,7 @@
mPermission = permission;
mNoun = noun;
mAddDeviceLockedFlags = addDeviceLockedFlags;
+ mValidator = validator;
}
public void addCallback(Callback callback) {
@@ -137,7 +140,6 @@
final PackageManager pmWrapper = mContext.getPackageManager();
List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser(
new Intent(mIntentAction), flags, user);
-
for (ResolveInfo resolveInfo : installedServices) {
ServiceInfo info = resolveInfo.serviceInfo;
@@ -148,6 +150,9 @@
+ mPermission);
continue;
}
+ if (mValidator != null && !mValidator.test(info)) {
+ continue;
+ }
mServices.add(info);
}
for (Callback callback : mCallbacks) {
@@ -194,6 +199,7 @@
private String mPermission;
private String mNoun;
private boolean mAddDeviceLockedFlags = false;
+ private Predicate mValidator;
public Builder(Context context) {
mContext = context;
@@ -224,6 +230,11 @@
return this;
}
+ public Builder setValidator(Predicate<ServiceInfo> validator) {
+ mValidator = validator;
+ return this;
+ }
+
/**
* Set to true to add support for both MATCH_DIRECT_BOOT_AWARE and
* MATCH_DIRECT_BOOT_UNAWARE flags when querying PackageManager. Required to get results
@@ -236,7 +247,7 @@
public ServiceListing build() {
return new ServiceListing(mContext, mTag, mSetting, mIntentAction, mPermission, mNoun,
- mAddDeviceLockedFlags);
+ mAddDeviceLockedFlags, mValidator);
}
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index f7fd25b..7ff0988 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -18,20 +18,35 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.provider.Settings;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.collect.ImmutableList;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ServiceListingTest {
@@ -39,10 +54,16 @@
private static final String TEST_INTENT = "com.example.intent";
private ServiceListing mServiceListing;
+ private Context mContext;
+ private PackageManager mPm;
@Before
public void setUp() {
- mServiceListing = new ServiceListing.Builder(RuntimeEnvironment.application)
+ mPm = mock(PackageManager.class);
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getPackageManager()).thenReturn(mPm);
+
+ mServiceListing = new ServiceListing.Builder(mContext)
.setTag("testTag")
.setSetting(TEST_SETTING)
.setNoun("testNoun")
@@ -52,6 +73,81 @@
}
@Test
+ public void testValidator() {
+ ServiceInfo s1 = new ServiceInfo();
+ s1.permission = "testPermission";
+ s1.packageName = "pkg";
+ ServiceInfo s2 = new ServiceInfo();
+ s2.permission = "testPermission";
+ s2.packageName = "pkg2";
+ ResolveInfo r1 = new ResolveInfo();
+ r1.serviceInfo = s1;
+ ResolveInfo r2 = new ResolveInfo();
+ r2.serviceInfo = s2;
+
+ when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ ImmutableList.of(r1, r2));
+
+ mServiceListing = new ServiceListing.Builder(mContext)
+ .setTag("testTag")
+ .setSetting(TEST_SETTING)
+ .setNoun("testNoun")
+ .setIntentAction(TEST_INTENT)
+ .setValidator(info -> {
+ if (info.packageName.equals("pkg")) {
+ return true;
+ }
+ return false;
+ })
+ .setPermission("testPermission")
+ .build();
+ ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+ mServiceListing.addCallback(callback);
+ mServiceListing.reload();
+
+ verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+ verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+ assertThat(captor.getValue().size()).isEqualTo(1);
+ assertThat(captor.getValue().get(0)).isEqualTo(s1);
+ }
+
+ @Test
+ public void testNoValidator() {
+ ServiceInfo s1 = new ServiceInfo();
+ s1.permission = "testPermission";
+ s1.packageName = "pkg";
+ ServiceInfo s2 = new ServiceInfo();
+ s2.permission = "testPermission";
+ s2.packageName = "pkg2";
+ ResolveInfo r1 = new ResolveInfo();
+ r1.serviceInfo = s1;
+ ResolveInfo r2 = new ResolveInfo();
+ r2.serviceInfo = s2;
+
+ when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
+ ImmutableList.of(r1, r2));
+
+ mServiceListing = new ServiceListing.Builder(mContext)
+ .setTag("testTag")
+ .setSetting(TEST_SETTING)
+ .setNoun("testNoun")
+ .setIntentAction(TEST_INTENT)
+ .setPermission("testPermission")
+ .build();
+ ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
+ mServiceListing.addCallback(callback);
+ mServiceListing.reload();
+
+ verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
+ ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
+ verify(callback, times(1)).onServicesReloaded(captor.capture());
+
+ assertThat(captor.getValue().size()).isEqualTo(2);
+ }
+
+ @Test
public void testCallback() {
ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
mServiceListing.addCallback(callback);
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
index b2226d1..b559718 100644
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -199,6 +199,16 @@
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 dc67d6f..8e36a7c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1306,7 +1306,7 @@
Owners newOwners() {
return new Owners(getUserManager(), getUserManagerInternal(),
getPackageManagerInternal(), getActivityTaskManagerInternal(),
- getActivityManagerInternal());
+ getActivityManagerInternal(), getUsageStatsManagerInternal());
}
UserManager getUserManager() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index fd09e3f..2aa7dcd 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -25,6 +25,7 @@
import android.app.admin.DevicePolicyManager.DeviceOwnerType;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
+import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -124,6 +125,7 @@
private final PackageManagerInternal mPackageManagerInternal;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
+ private final UsageStatsManagerInternal mUsageStatsManagerInternal;
private boolean mSystemReady;
@@ -156,9 +158,11 @@
UserManagerInternal userManagerInternal,
PackageManagerInternal packageManagerInternal,
ActivityTaskManagerInternal activityTaskManagerInternal,
- ActivityManagerInternal activitykManagerInternal) {
+ ActivityManagerInternal activitykManagerInternal,
+ UsageStatsManagerInternal usageStatsManagerInternal) {
this(userManager, userManagerInternal, packageManagerInternal,
- activityTaskManagerInternal, activitykManagerInternal, new Injector());
+ activityTaskManagerInternal, activitykManagerInternal,
+ usageStatsManagerInternal, new Injector());
}
@VisibleForTesting
@@ -167,12 +171,14 @@
PackageManagerInternal packageManagerInternal,
ActivityTaskManagerInternal activityTaskManagerInternal,
ActivityManagerInternal activityManagerInternal,
+ UsageStatsManagerInternal usageStatsManagerInternal,
Injector injector) {
mUserManager = userManager;
mUserManagerInternal = userManagerInternal;
mPackageManagerInternal = packageManagerInternal;
mActivityTaskManagerInternal = activityTaskManagerInternal;
mActivityManagerInternal = activityManagerInternal;
+ mUsageStatsManagerInternal = usageStatsManagerInternal;
mInjector = injector;
}
@@ -227,6 +233,8 @@
mDeviceOwnerProtectedPackages.entrySet()) {
mPackageManagerInternal.setDeviceOwnerProtectedPackages(
entry.getKey(), entry.getValue());
+ mUsageStatsManagerInternal.setAdminProtectedPackages(
+ new ArraySet(entry.getValue()), UserHandle.USER_ALL);
}
}
}
@@ -360,6 +368,8 @@
if (protectedPackages != null) {
mPackageManagerInternal.setDeviceOwnerProtectedPackages(
mDeviceOwner.packageName, new ArrayList<>());
+ mUsageStatsManagerInternal.setAdminProtectedPackages(
+ Collections.emptySet(), UserHandle.USER_ALL);
}
mDeviceOwner = null;
mDeviceOwnerUserId = UserHandle.USER_NULL;
@@ -417,6 +427,8 @@
if (previousProtectedPackages != null) {
mPackageManagerInternal.setDeviceOwnerProtectedPackages(
mDeviceOwner.packageName, new ArrayList<>());
+ mUsageStatsManagerInternal.setAdminProtectedPackages(
+ Collections.emptySet(), UserHandle.USER_ALL);
}
// We don't set a name because it's not used anyway.
// See DevicePolicyManagerService#getDeviceOwnerName
@@ -686,6 +698,8 @@
mDeviceOwnerProtectedPackages.put(packageName, protectedPackages);
mPackageManagerInternal.setDeviceOwnerProtectedPackages(packageName, protectedPackages);
+ mUsageStatsManagerInternal.setAdminProtectedPackages(
+ new ArraySet(protectedPackages), UserHandle.USER_ALL);
writeDeviceOwner();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 61d7ede..b509630 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -69,7 +69,8 @@
public OwnersTestable(MockSystemServices services) {
super(services.userManager, services.userManagerInternal,
services.packageManagerInternal, services.activityTaskManagerInternal,
- services.activityManagerInternal, new MockInjector(services));
+ services.activityManagerInternal, services.usageStatsManagerInternal,
+ new MockInjector(services));
}
static class MockInjector extends Injector {
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 9e46e1f..955f7f2 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -152,6 +152,9 @@
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;
@@ -1632,6 +1635,19 @@
}
@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 {
mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3};
@@ -2025,6 +2041,28 @@
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 ac1fcce..8872e1a 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -2495,6 +2495,11 @@
}
@Override
+ public void setAdminProtectedPackages(Set<String> packageNames, int userId) {
+ mAppStandby.setAdminProtectedPackages(packageNames, userId);
+ }
+
+ @Override
public void onAdminDataAvailable() {
mAppStandby.onAdminDataAvailable();
}