Merge "Permission Check For DPM.isDeviceProvisioned" into pi-dev
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4b729ff..3015398 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8610,6 +8610,7 @@
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     @UserProvisioningState
     public int getUserProvisioningState() {
         throwIfParentInstance("getUserProvisioningState");
@@ -9419,7 +9420,21 @@
      * <p>This method may returns {@code -1} if {@code apnSetting} conflicts with an existing
      * override APN. Update the existing conflicted APN with
      * {@link #updateOverrideApn(ComponentName, int, ApnSetting)} instead of adding a new entry.
-     * <p>See {@link ApnSetting} for the definition of conflict.
+     * <p>Two override APNs are considered to conflict when all the following APIs return
+     * the same values on both override APNs:
+     * <ul>
+     *   <li>{@link ApnSetting#getOperatorNumeric()}</li>
+     *   <li>{@link ApnSetting#getApnName()}</li>
+     *   <li>{@link ApnSetting#getProxyAddress()}</li>
+     *   <li>{@link ApnSetting#getProxyPort()}</li>
+     *   <li>{@link ApnSetting#getMmsProxyAddress()}</li>
+     *   <li>{@link ApnSetting#getMmsProxyPort()}</li>
+     *   <li>{@link ApnSetting#getMmsc()}</li>
+     *   <li>{@link ApnSetting#isEnabled()}</li>
+     *   <li>{@link ApnSetting#getMvnoType()}</li>
+     *   <li>{@link ApnSetting#getProtocol()}</li>
+     *   <li>{@link ApnSetting#getRoamingProtocol()}</li>
+     * </ul>
      *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
      * @param apnSetting the override APN to insert
@@ -9448,7 +9463,7 @@
      * {@code apnId}.
      * <p>This method may also returns {@code false} if {@code apnSetting} conflicts with an
      * existing override APN. Update the existing conflicted APN instead.
-     * <p>See {@link ApnSetting} for the definition of conflict.
+     * <p>See {@link #addOverrideApn} for the definition of conflict.
      *
      * @param admin which {@link DeviceAdminReceiver} this request is associated with
      * @param apnId the {@code id} of the override APN to update
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 387a836..e85058d 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1101,6 +1101,58 @@
     /** @hide */
     public String[] splitClassLoaderNames;
 
+    /**
+     * Represents the default policy. The actual policy used will depend on other properties of
+     * the application, e.g. the target SDK version.
+     * @hide
+     */
+    public static final int HIDDEN_API_ENFORCEMENT_DEFAULT = -1;
+    /**
+     * No API enforcement; the app can access the entire internal private API. Only for use by
+     * system apps.
+     * @hide
+     */
+    public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+    /**
+     * Light grey list enforcement, the strictest option. Enforces the light grey, dark grey and
+     * black lists.
+     * @hide
+     * */
+    public static final int HIDDEN_API_ENFORCEMENT_ALL_LISTS = 1;
+    /**
+     * Dark grey list enforcement. Enforces the dark grey and black lists
+     * @hide
+     */
+    public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
+    /**
+     * Blacklist enforcement only.
+     * @hide
+     */
+    public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+
+    private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+
+    /**
+     * Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
+     * art/runtime/hidden_api.h
+     * @hide
+     */
+    @IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
+            HIDDEN_API_ENFORCEMENT_DEFAULT,
+            HIDDEN_API_ENFORCEMENT_NONE,
+            HIDDEN_API_ENFORCEMENT_ALL_LISTS,
+            HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
+            HIDDEN_API_ENFORCEMENT_BLACK,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface HiddenApiEnforcementPolicy {}
+
+    private boolean isValidHiddenApiEnforcementPolicy(int policy) {
+        return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+    }
+
+    private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
+
     public void dump(Printer pw, String prefix) {
         dump(pw, prefix, DUMP_FLAG_ALL);
     }
@@ -1188,7 +1240,7 @@
             if (category != CATEGORY_UNDEFINED) {
                 pw.println(prefix + "category=" + category);
             }
-            pw.println(prefix + "isAllowedToUseHiddenApi=" + isAllowedToUseHiddenApi());
+            pw.println(prefix + "HiddenApiEnforcementPolicy=" + getHiddenApiEnforcementPolicy());
         }
         super.dumpBack(pw, prefix);
     }
@@ -1386,6 +1438,7 @@
         appComponentFactory = orig.appComponentFactory;
         compileSdkVersion = orig.compileSdkVersion;
         compileSdkVersionCodename = orig.compileSdkVersionCodename;
+        mHiddenApiPolicy = orig.mHiddenApiPolicy;
     }
 
     public String toString() {
@@ -1459,6 +1512,7 @@
         dest.writeInt(compileSdkVersion);
         dest.writeString(compileSdkVersionCodename);
         dest.writeString(appComponentFactory);
+        dest.writeInt(mHiddenApiPolicy);
     }
 
     public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1529,6 +1583,7 @@
         compileSdkVersion = source.readInt();
         compileSdkVersionCodename = source.readString();
         appComponentFactory = source.readString();
+        mHiddenApiPolicy = source.readInt();
     }
 
     /**
@@ -1599,13 +1654,31 @@
         }
     }
 
+    private boolean isPackageWhitelistedForHiddenApis() {
+        return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
+    }
+
     /**
      * @hide
      */
-    public boolean isAllowedToUseHiddenApi() {
-        boolean whitelisted =
-                SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
-        return whitelisted && (isSystemApp() || isUpdatedSystemApp());
+    public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
+        if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
+            return mHiddenApiPolicy;
+        }
+        if (isPackageWhitelistedForHiddenApis() && (isSystemApp() || isUpdatedSystemApp())) {
+            return HIDDEN_API_ENFORCEMENT_NONE;
+        }
+        return HIDDEN_API_ENFORCEMENT_BLACK;
+    }
+
+    /**
+     * @hide
+     */
+    public void setHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
+        if (!isValidHiddenApiEnforcementPolicy(policy)) {
+            throw new IllegalArgumentException("Invalid API enforcement policy: " + policy);
+        }
+        mHiddenApiPolicy = policy;
     }
 
     /**
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 28a7c12..cbd3ad5 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -53,10 +53,21 @@
     public static final int DISABLE_VERIFIER = 1 << 9;
     /** Only use oat files located in /system. Otherwise use dex/jar/apk . */
     public static final int ONLY_USE_SYSTEM_OAT_FILES = 1 << 10;
-    /** Do enfore hidden API access restrictions. */
-    public static final int ENABLE_HIDDEN_API_CHECKS = 1 << 11;
     /** Force generation of native debugging information for backtraces. */
-    public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 12;
+    public static final int DEBUG_GENERATE_MINI_DEBUG_INFO = 1 << 11;
+    /**
+     * Hidden API access restrictions. This is a mask for bits representing the API enforcement
+     * policy, defined by {@code @ApplicationInfo.HiddenApiEnforcementPolicy}.
+     */
+    public static final int API_ENFORCEMENT_POLICY_MASK = (1 << 12) | (1 << 13);
+    /**
+     * Bit shift for use with {@link #API_ENFORCEMENT_POLICY_MASK}.
+     *
+     * (flags & API_ENFORCEMENT_POLICY_MASK) >> API_ENFORCEMENT_POLICY_SHIFT gives
+     * @ApplicationInfo.ApiEnforcementPolicy values.
+     */
+    public static final int API_ENFORCEMENT_POLICY_SHIFT =
+            Integer.numberOfTrailingZeros(API_ENFORCEMENT_POLICY_MASK);
 
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk
index 2daef0c..7949c77 100644
--- a/data/keyboards/Android.mk
+++ b/data/keyboards/Android.mk
@@ -28,7 +28,7 @@
 validatekeymaps := $(HOST_OUT_EXECUTABLES)/validatekeymaps$(HOST_EXECUTABLE_SUFFIX)
 $(LOCAL_BUILT_MODULE): PRIVATE_VALIDATEKEYMAPS := $(validatekeymaps)
 $(LOCAL_BUILT_MODULE) : $(framework_keylayouts) $(framework_keycharmaps) $(framework_keyconfigs) | $(validatekeymaps)
-	$(hide) -q $(PRIVATE_VALIDATEKEYMAPS) $^
+	$(hide) $(PRIVATE_VALIDATEKEYMAPS) -q $^
 	$(hide) mkdir -p $(dir $@) && touch $@
 
 # Run validatekeymaps uncondionally for platform build.
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 706bbcf..5131a93 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -281,6 +281,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageManager;
@@ -4185,12 +4186,14 @@
                 runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
             }
 
-            if (!app.info.isAllowedToUseHiddenApi() &&
-                    !disableHiddenApiChecks &&
-                    !mHiddenApiBlacklist.isDisabled()) {
-                // This app is not allowed to use undocumented and private APIs, or blacklisting is
-                // enabled. Set up its runtime with the appropriate flag.
-                runtimeFlags |= Zygote.ENABLE_HIDDEN_API_CHECKS;
+            if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {
+                @HiddenApiEnforcementPolicy int policy =
+                        app.info.getHiddenApiEnforcementPolicy();
+                int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
+                if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {
+                    throw new IllegalStateException("Invalid API policy: " + policy);
+                }
+                runtimeFlags |= policyBits;
             }
 
             String invokeWith = null;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 7c56f4d..f617964 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -21,6 +21,7 @@
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
@@ -524,6 +525,10 @@
 
     public void onCleanupUser(int userId) {
         hideEncryptionNotification(new UserHandle(userId));
+        // User is stopped with its CE key evicted. Require strong auth next time to be able to
+        // unlock the user's storage. Use STRONG_AUTH_REQUIRED_AFTER_BOOT since stopping and
+        // restarting a user later is equivalent to rebooting the device.
+        requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_BOOT, userId);
     }
 
     public void onStartUser(final int userId) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 9e7ad47..61c6be7 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -47,6 +47,8 @@
 
 import dalvik.system.DexFile;
 
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+
 import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
 import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
 import static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED;
@@ -532,7 +534,10 @@
         int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
-        int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+        // TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
+        int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+                ? 0
+                : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
         // Avoid generating CompactDex for modes that are latency critical.
         final int compilationReason = options.getCompilationReason();
         boolean generateCompactDex = true;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 39ae8bb..1e216a3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -566,9 +566,7 @@
     }
 
     public static class DevicePolicyData {
-        @NonNull PasswordMetrics mActivePasswordMetrics = new PasswordMetrics();
         int mFailedPasswordAttempts = 0;
-        boolean mPasswordStateHasBeenSetSinceBoot = false;
         boolean mPasswordValidAtLastCheckpoint = true;
 
         int mUserHandle;
@@ -628,6 +626,8 @@
     }
 
     final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
+    @GuardedBy("DevicePolicyManagerService.this")
+    final SparseArray<PasswordMetrics> mUserPasswordMetrics = new SparseArray<>();
 
     final Handler mHandler;
     final Handler mBackgroundHandler;
@@ -2158,6 +2158,16 @@
     }
 
     /**
+     * Provides PasswordMetrics object corresponding to the given user.
+     * @param userHandle the user for whom to provide metrics.
+     * @return the user password metrics, or {@code null} if none have been associated with
+     * the user yet (for example, if the device has booted but not been unlocked).
+     */
+    PasswordMetrics getUserPasswordMetricsLocked(int userHandle) {
+        return mUserPasswordMetrics.get(userHandle);
+    }
+
+    /**
      * Creates and loads the policy data from xml for data that is shared between
      * various profiles of a user. In contrast to {@link #getUserData(int)}
      * it allows access to data of users other than the calling user.
@@ -2191,6 +2201,10 @@
             if (policy != null) {
                 mUserData.remove(userHandle);
             }
+            if (mUserPasswordMetrics.get(userHandle) != null) {
+                mUserPasswordMetrics.remove(userHandle);
+            }
+
             File policyFile = new File(mInjector.environmentGetUserSystemDirectory(userHandle),
                     DEVICE_POLICIES_XML);
             policyFile.delete();
@@ -3907,9 +3921,15 @@
     private void updatePasswordValidityCheckpointLocked(int userHandle, boolean parent) {
         final int credentialOwner = getCredentialOwner(userHandle, parent);
         DevicePolicyData policy = getUserData(credentialOwner);
+        PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner);
+        if (metrics == null) {
+            Slog.wtf(LOG_TAG, "Should have had a valid password metrics for updating checkpoint " +
+                    "validity.");
+            metrics = new PasswordMetrics();
+        }
         policy.mPasswordValidAtLastCheckpoint =
                 isPasswordSufficientForUserWithoutCheckpointLocked(
-                        policy.mActivePasswordMetrics, userHandle, parent);
+                        metrics, userHandle, parent);
 
         saveSettingsLocked(credentialOwner);
     }
@@ -4532,8 +4552,11 @@
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
-            DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, parent));
-            return isActivePasswordSufficientForUserLocked(policy, userHandle, parent);
+            int credentialOwner = getCredentialOwner(userHandle, parent);
+            DevicePolicyData policy = getUserDataUnchecked(credentialOwner);
+            PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner);
+            return isActivePasswordSufficientForUserLocked(
+                    policy.mPasswordValidAtLastCheckpoint, metrics, userHandle, parent);
         }
     }
 
@@ -4559,25 +4582,31 @@
         synchronized (this) {
             final int targetUser = getProfileParentId(userHandle);
             enforceUserUnlocked(targetUser, false);
-            DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, false));
-            return isActivePasswordSufficientForUserLocked(policy, targetUser, false);
+            int credentialOwner = getCredentialOwner(userHandle, false);
+            DevicePolicyData policy = getUserDataUnchecked(credentialOwner);
+            PasswordMetrics metrics = getUserPasswordMetricsLocked(credentialOwner);
+            return isActivePasswordSufficientForUserLocked(
+                    policy.mPasswordValidAtLastCheckpoint, metrics, targetUser, false);
         }
     }
 
     private boolean isActivePasswordSufficientForUserLocked(
-            DevicePolicyData policy, int userHandle, boolean parent) {
-        if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()
-                && !policy.mPasswordStateHasBeenSetSinceBoot) {
+            boolean passwordValidAtLastCheckpoint, PasswordMetrics metrics, int userHandle,
+            boolean parent) {
+        if (!mInjector.storageManagerIsFileBasedEncryptionEnabled() && (metrics == null)) {
             // Before user enters their password for the first time after a reboot, return the
             // value of this flag, which tells us whether the password was valid the last time
             // settings were saved.  If DPC changes password requirements on boot so that the
             // current password no longer meets the requirements, this value will be stale until
             // the next time the password is entered.
-            return policy.mPasswordValidAtLastCheckpoint;
+            return passwordValidAtLastCheckpoint;
         }
 
-        return isPasswordSufficientForUserWithoutCheckpointLocked(
-                policy.mActivePasswordMetrics, userHandle, parent);
+        if (metrics == null) {
+            Slog.wtf(LOG_TAG, "FBE device, should have been unlocked and had valid metrics.");
+            metrics = new PasswordMetrics();
+        }
+        return isPasswordSufficientForUserWithoutCheckpointLocked(metrics, userHandle, parent);
     }
 
     /**
@@ -6123,10 +6152,8 @@
         }
 
         validateQualityConstant(metrics.quality);
-        DevicePolicyData policy = getUserData(userHandle);
         synchronized (this) {
-            policy.mActivePasswordMetrics = metrics;
-            policy.mPasswordStateHasBeenSetSinceBoot = true;
+            mUserPasswordMetrics.put(userHandle, metrics);
         }
     }
 
@@ -7640,6 +7667,7 @@
         if (!mHasFeature) {
             return DevicePolicyManager.STATE_USER_UNMANAGED;
         }
+        enforceManageUsers();
         int userHandle = mInjector.userHandleGetCallingUserId();
         return getUserProvisioningState(userHandle);
     }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 43490d3..a64efb7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2387,12 +2387,12 @@
     }
 
     public void testGetUserProvisioningState_defaultResult() {
+        mContext.callerPermissions.add(permission.MANAGE_USERS);
         assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
     }
 
     public void testSetUserProvisioningState_permission() throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(DpmMockContext.CALLER_USER_HANDLE,
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
@@ -2407,6 +2407,7 @@
 
     public void testSetUserProvisioningState_noManagement() {
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+        mContext.callerPermissions.add(permission.MANAGE_USERS);
         assertExpectException(IllegalStateException.class,
                 /* messageRegex= */ "change provisioning state unless a .* owner is set",
                 () -> dpm.setUserProvisioningState(DevicePolicyManager.STATE_USER_SETUP_FINALIZED,
@@ -2417,7 +2418,6 @@
     public void testSetUserProvisioningState_deviceOwnerFromSetupWizard() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(UserHandle.USER_SYSTEM,
                 DevicePolicyManager.STATE_USER_SETUP_COMPLETE,
@@ -2428,7 +2428,6 @@
             throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(UserHandle.USER_SYSTEM,
                 DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE,
@@ -2438,7 +2437,6 @@
     public void testSetUserProvisioningState_deviceOwnerWithoutSetupWizard() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(UserHandle.USER_SYSTEM,
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
@@ -2447,7 +2445,6 @@
     public void testSetUserProvisioningState_managedProfileFromSetupWizard_primaryUser()
             throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(DpmMockContext.CALLER_USER_HANDLE,
                 DevicePolicyManager.STATE_USER_PROFILE_COMPLETE,
@@ -2457,7 +2454,6 @@
     public void testSetUserProvisioningState_managedProfileFromSetupWizard_managedProfile()
             throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(DpmMockContext.CALLER_USER_HANDLE,
                 DevicePolicyManager.STATE_USER_SETUP_COMPLETE,
@@ -2466,7 +2462,6 @@
 
     public void testSetUserProvisioningState_managedProfileWithoutSetupWizard() throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         exerciseUserProvisioningTransitions(DpmMockContext.CALLER_USER_HANDLE,
                 DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
@@ -2474,7 +2469,6 @@
 
     public void testSetUserProvisioningState_illegalTransitionOutOfFinalized1() throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         assertExpectException(IllegalStateException.class,
                 /* messageRegex= */ "Cannot move to user provisioning state",
@@ -2486,7 +2480,6 @@
     public void testSetUserProvisioningState_illegalTransitionToAnotherInProgressState()
             throws Exception {
         setupProfileOwner();
-        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
 
         assertExpectException(IllegalStateException.class,
                 /* messageRegex= */ "Cannot move to user provisioning state",
@@ -2496,6 +2489,9 @@
     }
 
     private void exerciseUserProvisioningTransitions(int userId, int... states) {
+        mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+        mContext.callerPermissions.add(permission.MANAGE_USERS);
+
         assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
         for (int state : states) {
             dpm.setUserProvisioningState(state, userId);