Added keep-uninstalled-packages DO policy
This policy allows DO to specify a list of apps to cache even without being
installed on any user.
Bug: 23938464
Change-Id: I2eeab7f148409739fc23a5c44e955ad12b63fd04
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index faed7a0..58f4c63 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3591,6 +3591,48 @@
}
/**
+ * Called by a device owner to get the list of apps to keep around as APKs even if no user has
+ * currently installed it.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ *
+ * @return List of package names to keep cached.
+ * @hide
+ */
+ public List<String> getKeepUninstalledPackages(@NonNull ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.getKeepUninstalledPackages(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Called by a device owner to set a list of apps to keep around as APKs even if no user has
+ * currently installed it.
+ *
+ * <p>Please note that setting this policy does not imply that specified apps will be
+ * automatically pre-cached.</p>
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageNames List of package names to keep cached.
+ * @hide
+ */
+ public void setKeepUninstalledPackages(@NonNull ComponentName admin,
+ @NonNull List<String> packageNames) {
+ if (mService != null) {
+ try {
+ mService.setKeepUninstalledPackages(admin, packageNames);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ }
+
+ /**
* Called by a device owner to create a user with the specified name. The UserHandle returned
* by this method should not be persisted as user handles are recycled as users are removed and
* created. If you need to persist an identifier for this user, use
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7601cf2..283bf14 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -231,4 +231,6 @@
String permission, int grantState);
int getPermissionGrantState(in ComponentName admin, String packageName, String permission);
boolean isProvisioningAllowed(String action);
+ void setKeepUninstalledPackages(in ComponentName admin,in List<String> packageList);
+ List<String> getKeepUninstalledPackages(in ComponentName admin);
}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index bf70d6c..905ac5e 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,7 +16,7 @@
package android.content.pm;
-import android.annotation.NonNull;
+import java.util.List;
/**
* Package manager local system service interface.
@@ -115,4 +115,11 @@
*/
public abstract void grantDefaultPermissionsToDefaultSimCallManager(String packageName,
int userId);
+
+ /**
+ * Sets a list of apps to keep in PM's internal data structures and as APKs even if no user has
+ * currently installed it. The apps are not preloaded.
+ * @param packageList List of package names to keep cached.
+ */
+ public abstract void setKeepUninstalledPackages(List<String> packageList);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4f3544b..21a4206 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -617,6 +617,9 @@
final DefaultPermissionGrantPolicy mDefaultPermissionPolicy =
new DefaultPermissionGrantPolicy(this);
+ // List of packages names to keep cached, even if they are uninstalled for all users
+ private List<String> mKeepUninstalledPackages;
+
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -13015,7 +13018,7 @@
final boolean deleteAllUsers = (flags & PackageManager.DELETE_ALL_USERS) != 0;
final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
- mContext.enforceCallingPermission(
+ mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"deletePackage for user " + userId);
}
@@ -13090,6 +13093,10 @@
return false;
}
+ private boolean shouldKeepUninstalledPackageLPr(String packageName) {
+ return mKeepUninstalledPackages != null && mKeepUninstalledPackages.contains(packageName);
+ }
+
/**
* This method is an internal method that could be get invoked either
* to delete an installed package or to clean up a failed installation.
@@ -13512,7 +13519,9 @@
false, // blockUninstall
ps.readUserState(userId).domainVerificationStatus, 0);
if (!isSystemApp(ps)) {
- if (ps.isAnyInstalled(sUserManager.getUserIds())) {
+ // Do not uninstall the APK if an app should be cached
+ boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
+ if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
// Other user still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
@@ -16686,15 +16695,21 @@
if (DEBUG_CLEAN_APKS) {
Slog.i(TAG, "Checking package " + packageName);
}
- boolean keep = false;
- for (int i = 0; i < users.length; i++) {
- if (users[i] != userHandle && ps.getInstalled(users[i])) {
- keep = true;
- if (DEBUG_CLEAN_APKS) {
- Slog.i(TAG, " Keeping package " + packageName + " for user "
- + users[i]);
+ boolean keep = shouldKeepUninstalledPackageLPr(packageName);
+ if (keep) {
+ if (DEBUG_CLEAN_APKS) {
+ Slog.i(TAG, " Keeping package " + packageName + " - requested by DO");
+ }
+ } else {
+ for (int i = 0; i < users.length; i++) {
+ if (users[i] != userHandle && ps.getInstalled(users[i])) {
+ keep = true;
+ if (DEBUG_CLEAN_APKS) {
+ Slog.i(TAG, " Keeping package " + packageName + " for user "
+ + users[i]);
+ }
+ break;
}
- break;
}
}
if (!keep) {
@@ -16896,6 +16911,23 @@
}
}
+ private void deletePackageIfUnusedLPr(final String packageName) {
+ PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
+ return;
+ }
+ if (!ps.isAnyInstalled(sUserManager.getUserIds())) {
+ // TODO Implement atomic delete if package is unused
+ // It is currently possible that the package will be deleted even if it is installed
+ // after this method returns.
+ mHandler.post(new Runnable() {
+ public void run() {
+ deletePackageX(packageName, 0, PackageManager.DELETE_ALL_USERS);
+ }
+ });
+ }
+ }
+
/**
* Check and throw if the given before/after packages would be considered a
* downgrade.
@@ -17133,6 +17165,34 @@
packageName, userId);
}
}
+
+ @Override
+ public void setKeepUninstalledPackages(final List<String> packageList) {
+ Preconditions.checkNotNull(packageList);
+ List<String> removedFromList = null;
+ synchronized (mPackages) {
+ if (mKeepUninstalledPackages != null) {
+ final int packagesCount = mKeepUninstalledPackages.size();
+ for (int i = 0; i < packagesCount; i++) {
+ String oldPackage = mKeepUninstalledPackages.get(i);
+ if (packageList != null && packageList.contains(oldPackage)) {
+ continue;
+ }
+ if (removedFromList == null) {
+ removedFromList = new ArrayList<>();
+ }
+ removedFromList.add(oldPackage);
+ }
+ }
+ mKeepUninstalledPackages = new ArrayList<>(packageList);
+ if (removedFromList != null) {
+ final int removedCount = removedFromList.size();
+ for (int i = 0; i < removedCount; i++) {
+ deletePackageIfUnusedLPr(removedFromList.get(i));
+ }
+ }
+ }
+ }
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e59c6f8..febfeb1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -416,7 +417,7 @@
"cross-profile-widget-providers";
private static final String TAG_PROVIDER = "provider";
private static final String TAG_PACKAGE_LIST_ITEM = "item";
-
+ private static final String TAG_KEEP_UNINSTALLED_PACKAGES = "keep-uninstalled-packages";
private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
final DeviceAdminInfo info;
@@ -489,6 +490,9 @@
// allowed.
List<String> permittedInputMethods;
+ // List of package names to keep cached.
+ List<String> keepUninstalledPackages;
+
// TODO: review implementation decisions with frameworks team
boolean specifiesGlobalProxy = false;
String globalProxySpec = null;
@@ -674,6 +678,7 @@
writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
permittedAccessiblityServices);
writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
+ writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
if (hasUserRestrictions()) {
UserRestrictionsUtils.writeRestrictions(
out, userRestrictions, TAG_USER_RESTRICTIONS);
@@ -787,6 +792,8 @@
permittedAccessiblityServices = readPackageList(parser, tag);
} else if (TAG_PERMITTED_IMES.equals(tag)) {
permittedInputMethods = readPackageList(parser, tag);
+ } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
+ keepUninstalledPackages = readPackageList(parser, tag);
} else if (TAG_USER_RESTRICTIONS.equals(tag)) {
UserRestrictionsUtils.readRestrictions(parser, ensureUserRestrictions());
} else {
@@ -981,13 +988,17 @@
pw.println(disabledKeyguardFeatures);
pw.print(prefix); pw.print("crossProfileWidgetProviders=");
pw.println(crossProfileWidgetProviders);
- if (!(permittedAccessiblityServices == null)) {
+ if (permittedAccessiblityServices != null) {
pw.print(prefix); pw.print("permittedAccessibilityServices=");
- pw.println(permittedAccessiblityServices.toString());
+ pw.println(permittedAccessiblityServices);
}
- if (!(permittedInputMethods == null)) {
+ if (permittedInputMethods != null) {
pw.print(prefix); pw.print("permittedInputMethods=");
- pw.println(permittedInputMethods.toString());
+ pw.println(permittedInputMethods);
+ }
+ if (keepUninstalledPackages != null) {
+ pw.print(prefix); pw.print("keepUninstalledPackages=");
+ pw.println(keepUninstalledPackages);
}
pw.print(prefix); pw.println("userRestrictions:");
UserRestrictionsUtils.dumpRestrictions(pw, prefix + " ", userRestrictions);
@@ -1068,6 +1079,10 @@
return LocalServices.getService(UserManagerInternal.class);
}
+ PackageManagerInternal getPackageManagerInternal() {
+ return LocalServices.getService(PackageManagerInternal.class);
+ }
+
NotificationManager getNotificationManager() {
return mContext.getSystemService(NotificationManager.class);
}
@@ -2101,6 +2116,14 @@
new SetupContentObserver(mHandler).register(mContext.getContentResolver());
// Initialize the user setup state, to handle the upgrade case.
updateUserSetupComplete();
+
+ List<String> packageList;
+ synchronized (this) {
+ packageList = getKeepUninstalledPackagesLocked();
+ }
+ if (packageList != null) {
+ mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
+ }
}
private void ensureDeviceOwnerUserStarted() {
@@ -4490,6 +4513,42 @@
}
@Override
+ public void setKeepUninstalledPackages(ComponentName who, List<String> packageList) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ Preconditions.checkNotNull(packageList, "packageList is null");
+ final int userHandle = UserHandle.getCallingUserId();
+ synchronized (this) {
+ ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ admin.keepUninstalledPackages = packageList;
+ saveSettingsLocked(userHandle);
+ mInjector.getPackageManagerInternal().setKeepUninstalledPackages(packageList);
+ }
+ }
+
+ @Override
+ public List<String> getKeepUninstalledPackages(ComponentName who) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ if (!mHasFeature) {
+ return null;
+ }
+ // TODO In split system user mode, allow apps on user 0 to query the list
+ synchronized (this) {
+ // Check if this is the device owner who is calling
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ return getKeepUninstalledPackagesLocked();
+ }
+ }
+
+ private List<String> getKeepUninstalledPackagesLocked() {
+ ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
+ return (deviceOwner != null) ? deviceOwner.keepUninstalledPackages : null;
+ }
+
+ @Override
public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) {
if (!mHasFeature) {
return false;
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 2c01b8a..56d6fc0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -20,8 +20,8 @@
import android.app.IActivityManager;
import android.app.NotificationManager;
import android.app.backup.IBackupManager;
-import android.content.Context;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
import android.media.IAudioService;
import android.os.Looper;
import android.os.PowerManagerInternal;
@@ -113,6 +113,11 @@
}
@Override
+ PackageManagerInternal getPackageManagerInternal() {
+ return context.packageManagerInternal;
+ }
+
+ @Override
PowerManagerInternal getPowerManagerInternal() {
return context.powerManagerInternal;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index f4fdc95..bb1e06d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -28,6 +28,7 @@
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
import android.media.IAudioService;
import android.os.Bundle;
@@ -205,6 +206,7 @@
public final SystemPropertiesForMock systemProperties;
public final UserManager userManager;
public final UserManagerInternal userManagerInternal;
+ public final PackageManagerInternal packageManagerInternal;
public final UserManagerForMock userManagerForMock;
public final PowerManagerForMock powerManager;
public final PowerManagerInternal powerManagerInternal;
@@ -237,6 +239,7 @@
userManager = mock(UserManager.class);
userManagerInternal = mock(UserManagerInternal.class);
userManagerForMock = mock(UserManagerForMock.class);
+ packageManagerInternal = mock(PackageManagerInternal.class);
powerManager = mock(PowerManagerForMock.class);
powerManagerInternal = mock(PowerManagerInternal.class);
notificationManager = mock(NotificationManager.class);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
deleted file mode 100644
index 56fd351..0000000
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm;
-
-import com.android.server.devicepolicy.DpmTestUtils;
-
-import android.os.Bundle;
-import android.os.UserManager;
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-
-/**
- * Tests for {@link com.android.server.pm.UserRestrictionsUtils}.
- *
- * <p>Run with:<pre>
- m FrameworksServicesTests &&
- adb install \
- -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.pm.UserRestrictionsUtilsTest \
- -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
- * </pre>
- */
-public class UserRestrictionsUtilsTest extends AndroidTestCase {
- public void testNonNull() {
- Bundle out = UserRestrictionsUtils.nonNull(null);
- assertNotNull(out);
- out.putBoolean("a", true); // Should not be Bundle.EMPTY.
-
- Bundle in = new Bundle();
- assertSame(in, UserRestrictionsUtils.nonNull(in));
- }
-
- public void testIsEmpty() {
- assertTrue(UserRestrictionsUtils.isEmpty(null));
- assertTrue(UserRestrictionsUtils.isEmpty(new Bundle()));
- assertFalse(UserRestrictionsUtils.isEmpty(DpmTestUtils.newRestrictions("a")));
- }
-
- public void testClone() {
- Bundle in = new Bundle();
- Bundle out = UserRestrictionsUtils.clone(in);
- assertNotSame(in, out);
- DpmTestUtils.assertRestrictions(out, new Bundle());
-
- out = UserRestrictionsUtils.clone(null);
- assertNotNull(out);
- out.putBoolean("a", true); // Should not be Bundle.EMPTY.
- }
-
- public void testMerge() {
- Bundle a = DpmTestUtils.newRestrictions("a", "d");
- Bundle b = DpmTestUtils.newRestrictions("b", "d", "e");
-
- UserRestrictionsUtils.merge(a, b);
-
- DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions("a", "b", "d", "e"), a);
-
- UserRestrictionsUtils.merge(a, null);
-
- DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions("a", "b", "d", "e"), a);
-
- try {
- UserRestrictionsUtils.merge(a, a);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testIsSystemControlled() {
- assertTrue(UserRestrictionsUtils.isSystemControlled(UserManager.DISALLOW_RECORD_AUDIO));
- assertFalse(UserRestrictionsUtils.isSystemControlled(UserManager.DISALLOW_FUN));
- }
-
- public void testCanDeviceOwnerChange() {
- assertFalse(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_RECORD_AUDIO));
- assertFalse(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_WALLPAPER));
- assertTrue(UserRestrictionsUtils.canDeviceOwnerChange(UserManager.DISALLOW_ADD_USER));
- }
-
- public void testCanProfileOwnerChange() {
- assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_RECORD_AUDIO));
- assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_WALLPAPER));
- assertFalse(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_ADD_USER));
- assertTrue(UserRestrictionsUtils.canProfileOwnerChange(UserManager.DISALLOW_ADJUST_VOLUME));
- }
-
- public void testSortToGlobalAndLocal() {
- final Bundle local = new Bundle();
- final Bundle global = new Bundle();
-
- UserRestrictionsUtils.sortToGlobalAndLocal(null, global, local);
- assertEquals(0, global.size());
- assertEquals(0, local.size());
-
- UserRestrictionsUtils.sortToGlobalAndLocal(Bundle.EMPTY, global, local);
- assertEquals(0, global.size());
- assertEquals(0, local.size());
-
- UserRestrictionsUtils.sortToGlobalAndLocal(DpmTestUtils.newRestrictions(
- UserManager.DISALLOW_ADJUST_VOLUME,
- UserManager.DISALLOW_UNMUTE_MICROPHONE,
- UserManager.DISALLOW_USB_FILE_TRANSFER,
- UserManager.DISALLOW_CONFIG_TETHERING,
- UserManager.DISALLOW_OUTGOING_BEAM,
- UserManager.DISALLOW_APPS_CONTROL
- ), global, local);
-
-
- DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions(
- // These can be set by PO too, but when DO sets them, they're global.
- UserManager.DISALLOW_ADJUST_VOLUME,
- UserManager.DISALLOW_UNMUTE_MICROPHONE,
-
- // These can only be set by DO.
- UserManager.DISALLOW_USB_FILE_TRANSFER,
- UserManager.DISALLOW_CONFIG_TETHERING
- ), global);
-
- DpmTestUtils.assertRestrictions(DpmTestUtils.newRestrictions(
- // They can be set by both DO/PO.
- UserManager.DISALLOW_OUTGOING_BEAM,
- UserManager.DISALLOW_APPS_CONTROL
- ), local);
- }
-
- public void testAreEqual() {
- assertTrue(UserRestrictionsUtils.areEqual(
- null,
- null));
-
- assertTrue(UserRestrictionsUtils.areEqual(
- null,
- Bundle.EMPTY));
-
- assertTrue(UserRestrictionsUtils.areEqual(
- Bundle.EMPTY,
- null));
-
- assertTrue(UserRestrictionsUtils.areEqual(
- Bundle.EMPTY,
- Bundle.EMPTY));
-
- assertTrue(UserRestrictionsUtils.areEqual(
- new Bundle(),
- Bundle.EMPTY));
-
- assertFalse(UserRestrictionsUtils.areEqual(
- null,
- DpmTestUtils.newRestrictions("a")));
-
- assertFalse(UserRestrictionsUtils.areEqual(
- DpmTestUtils.newRestrictions("a"),
- null));
-
- assertTrue(UserRestrictionsUtils.areEqual(
- DpmTestUtils.newRestrictions("a"),
- DpmTestUtils.newRestrictions("a")));
-
- assertFalse(UserRestrictionsUtils.areEqual(
- DpmTestUtils.newRestrictions("a"),
- DpmTestUtils.newRestrictions("a", "b")));
-
- assertFalse(UserRestrictionsUtils.areEqual(
- DpmTestUtils.newRestrictions("a", "b"),
- DpmTestUtils.newRestrictions("a")));
-
- assertFalse(UserRestrictionsUtils.areEqual(
- DpmTestUtils.newRestrictions("b", "a"),
- DpmTestUtils.newRestrictions("a", "a")));
-
- // Make sure false restrictions are handled correctly.
- final Bundle a = DpmTestUtils.newRestrictions("a");
- a.putBoolean("b", true);
-
- final Bundle b = DpmTestUtils.newRestrictions("a");
- b.putBoolean("b", false);
-
- assertFalse(UserRestrictionsUtils.areEqual(a, b));
- assertFalse(UserRestrictionsUtils.areEqual(b, a));
- }
-}