Merge changes Ica472482,I32381136 into main am: f4c7c30b8f am: 3f1086d916 am: 1ff3c08bee

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2871534

Change-Id: I6c1e0f0611aa85ea62cd3595844b26853f29924c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index c88763c..18d5f6d 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -134,12 +134,12 @@
     }
 
     /**
-     * Creates a LockscreenCredential object representing a managed password for profile with
-     * unified challenge. This credentiall will have type {@code CREDENTIAL_TYPE_PASSWORD} for now.
-     * TODO: consider add a new credential type for this. This can then supersede the
-     * isLockTiedToParent argument in various places in LSS.
+     * Creates a LockscreenCredential object representing the system-generated, system-managed
+     * password for a profile with unified challenge. This credential has type {@code
+     * CREDENTIAL_TYPE_PASSWORD} for now. TODO: consider add a new credential type for this. This
+     * can then supersede the isLockTiedToParent argument in various places in LSS.
      */
-    public static LockscreenCredential createManagedPassword(@NonNull byte[] password) {
+    public static LockscreenCredential createUnifiedProfilePassword(@NonNull byte[] password) {
         return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,
                 Arrays.copyOf(password, password.length), /* hasInvalidChars= */ false);
     }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 42c2548..0c2eee5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -209,7 +209,7 @@
  *   <li>Protect each user's data using their SP.  For example, use the SP to encrypt/decrypt the
  *   user's credential-encrypted (CE) key for file-based encryption (FBE).</li>
  *
- *   <li>Generate, protect, and use profile passwords for managed profiles.</li>
+ *   <li>Generate, protect, and use unified profile passwords.</li>
  *
  *   <li>Support unlocking the SP by alternative means: resume-on-reboot (reboot escrow) for easier
  *   OTA updates, and escrow tokens when set up by the Device Policy Controller (DPC).</li>
@@ -287,7 +287,7 @@
 
     private final java.security.KeyStore mJavaKeyStore;
     private final RecoverableKeyStoreManager mRecoverableKeyStoreManager;
-    private ManagedProfilePasswordCache mManagedProfilePasswordCache;
+    private final UnifiedProfilePasswordCache mUnifiedProfilePasswordCache;
 
     private final RebootEscrowManager mRebootEscrowManager;
 
@@ -404,7 +404,8 @@
         for (int i = 0; i < newPasswordChars.length; i++) {
             newPassword[i] = (byte) newPasswordChars[i];
         }
-        LockscreenCredential credential = LockscreenCredential.createManagedPassword(newPassword);
+        LockscreenCredential credential =
+                LockscreenCredential.createUnifiedProfilePassword(newPassword);
         Arrays.fill(newPasswordChars, '\u0000');
         Arrays.fill(newPassword, (byte) 0);
         Arrays.fill(randomLockSeed, (byte) 0);
@@ -424,7 +425,7 @@
         if (!isCredentialSharableWithParent(profileUserId)) {
             return;
         }
-        // Do not tie profile when work challenge is enabled
+        // Do not tie profile when separate challenge is enabled
         if (getSeparateProfileChallengeEnabledInternal(profileUserId)) {
             return;
         }
@@ -462,7 +463,7 @@
             setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                     /* isLockTiedToParent= */ true);
             tieProfileLockToParent(profileUserId, parent.id, unifiedProfilePassword);
-            mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword,
+            mUnifiedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword,
                     parentSid);
         }
     }
@@ -620,9 +621,9 @@
             }
         }
 
-        public @NonNull ManagedProfilePasswordCache getManagedProfilePasswordCache(
+        public @NonNull UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(
                 java.security.KeyStore ks) {
-            return new ManagedProfilePasswordCache(ks);
+            return new UnifiedProfilePasswordCache(ks);
         }
 
         public boolean isHeadlessSystemUserMode() {
@@ -665,7 +666,7 @@
         mGatekeeperPasswords = new LongSparseArray<>();
 
         mSpManager = injector.getSyntheticPasswordManager(mStorage);
-        mManagedProfilePasswordCache = injector.getManagedProfilePasswordCache(mJavaKeyStore);
+        mUnifiedProfilePasswordCache = injector.getUnifiedProfilePasswordCache(mJavaKeyStore);
         mBiometricDeferredQueue = new BiometricDeferredQueue(mSpManager, mHandler);
 
         mRebootEscrowManager = injector.getRebootEscrowManager(new RebootEscrowCallbacks(),
@@ -689,8 +690,8 @@
     }
 
     /**
-     * If the account is credential-encrypted, show notification requesting the user to unlock the
-     * device.
+     * If the user is a managed profile whose credential-encrypted storage is locked, show a
+     * notification requesting the user to unlock the device.
      */
     private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId, String reason) {
         final UserInfo user = mUserManager.getUserInfo(userId);
@@ -846,7 +847,7 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                // Hide notification first, as tie managed profile lock takes time
+                // Hide notification first, as tie profile lock takes time
                 hideEncryptionNotification(new UserHandle(userId));
 
                 if (isCredentialSharableWithParent(userId)) {
@@ -1458,13 +1459,13 @@
 
         cipher.init(Cipher.DECRYPT_MODE, decryptionKey, new GCMParameterSpec(128, iv));
         decryptionResult = cipher.doFinal(encryptedPassword);
-        LockscreenCredential credential = LockscreenCredential.createManagedPassword(
+        LockscreenCredential credential = LockscreenCredential.createUnifiedProfilePassword(
                 decryptionResult);
         Arrays.fill(decryptionResult, (byte) 0);
         try {
             long parentSid = getGateKeeperService().getSecureUserId(
                     mUserManager.getProfileParent(userId).id);
-            mManagedProfilePasswordCache.storePassword(userId, credential, parentSid);
+            mUnifiedProfilePasswordCache.storePassword(userId, credential, parentSid);
         } catch (RemoteException e) {
             Slogf.w(TAG, "Failed to talk to GateKeeper service", e);
         }
@@ -1550,7 +1551,7 @@
                         // so it goes into the cache
                         getDecryptedPasswordForTiedProfile(profile.id);
                     } catch (GeneralSecurityException | IOException e) {
-                        Slog.d(TAG, "Cache work profile password failed", e);
+                        Slog.d(TAG, "Cache unified profile password failed", e);
                     }
                 }
             }
@@ -1604,19 +1605,19 @@
     }
 
     /**
-     * Synchronize all profile's work challenge of the given user if it's unified: tie or clear them
+     * Synchronize all profile's challenge of the given user if it's unified: tie or clear them
      * depending on the parent user's secure state.
      *
-     * When clearing tied work challenges, a pre-computed password table for profiles are required,
-     * since changing password for profiles requires existing password, and existing passwords can
-     * only be computed before the parent user's password is cleared.
+     * When clearing tied challenges, a pre-computed password table for profiles are required, since
+     * changing password for profiles requires existing password, and existing passwords can only be
+     * computed before the parent user's password is cleared.
      *
      * Strictly this is a recursive function, since setLockCredentialInternal ends up calling this
      * method again on profiles. However the recursion is guaranteed to terminate as this method
      * terminates when the user is a profile that shares lock credentials with parent.
      * (e.g. managed and clone profile).
      */
-    private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
+    private void synchronizeUnifiedChallengeForProfiles(int userId,
             Map<Integer, LockscreenCredential> profilePasswordMap) {
         if (isCredentialSharableWithParent(userId)) {
             return;
@@ -1635,7 +1636,7 @@
                     tieProfileLockIfNecessary(profileUserId,
                             LockscreenCredential.createNone());
                 } else {
-                    // We use cached work profile password computed before clearing the parent's
+                    // We use cached profile password computed before clearing the parent's
                     // credential, otherwise they get lost
                     if (profilePasswordMap != null
                             && profilePasswordMap.containsKey(profileUserId)) {
@@ -1777,7 +1778,7 @@
                 notifyPasswordChanged(credential, userId);
             }
             if (isCredentialSharableWithParent(userId)) {
-                // Make sure the profile doesn't get locked straight after setting work challenge.
+                // Make sure the profile doesn't get locked straight after setting challenge.
                 setDeviceUnlockedForUser(userId);
             }
             notifySeparateProfileChallengeChanged(userId);
@@ -2368,7 +2369,7 @@
         }
 
         try {
-            // Unlock work profile, and work profile with unified lock must use password only
+            // Unlock profile with unified lock
             return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
                     userId, null /* progressCallback */, flags);
         } catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
@@ -2492,7 +2493,7 @@
         mStrongAuth.removeUser(userId);
 
         AndroidKeyStoreMaintenance.onUserRemoved(userId);
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
 
         gateKeeperClearSecureUserId(userId);
         removeKeystoreProfileKey(userId);
@@ -2982,7 +2983,7 @@
                 credential, sp, userId);
         final Map<Integer, LockscreenCredential> profilePasswords;
         if (!credential.isNone()) {
-            // not needed by synchronizeUnifiedWorkChallengeForProfiles()
+            // not needed by synchronizeUnifiedChallengeForProfiles()
             profilePasswords = null;
 
             if (!mSpManager.hasSidForUser(userId)) {
@@ -2993,8 +2994,8 @@
                 }
             }
         } else {
-            // Cache all profile password if they use unified work challenge. This will later be
-            // used to clear the profile's password in synchronizeUnifiedWorkChallengeForProfiles()
+            // Cache all profile password if they use unified challenge. This will later be used to
+            // clear the profile's password in synchronizeUnifiedChallengeForProfiles().
             profilePasswords = getDecryptedPasswordsForAllTiedProfiles(userId);
 
             mSpManager.clearSidForUser(userId);
@@ -3010,10 +3011,10 @@
         }
         setCurrentLskfBasedProtectorId(newProtectorId, userId);
         LockPatternUtils.invalidateCredentialTypeCache();
-        synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
+        synchronizeUnifiedChallengeForProfiles(userId, profilePasswords);
 
         setUserPasswordMetrics(credential, userId);
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
         if (savedCredentialType != CREDENTIAL_TYPE_NONE) {
             mSpManager.destroyAllWeakTokenBasedProtectors(userId);
         }
@@ -3114,7 +3115,7 @@
                 try {
                     currentCredential = getDecryptedPasswordForTiedProfile(userId);
                 } catch (Exception e) {
-                    Slog.e(TAG, "Failed to get work profile credential", e);
+                    Slog.e(TAG, "Failed to get unified profile password", e);
                     return null;
                 }
             }
@@ -3284,7 +3285,7 @@
     @Override
     public boolean tryUnlockWithCachedUnifiedChallenge(int userId) {
         checkPasswordReadPermission();
-        try (LockscreenCredential cred = mManagedProfilePasswordCache.retrievePassword(userId)) {
+        try (LockscreenCredential cred = mUnifiedProfilePasswordCache.retrievePassword(userId)) {
             if (cred == null) {
                 return false;
             }
@@ -3296,7 +3297,7 @@
     @Override
     public void removeCachedUnifiedChallenge(int userId) {
         checkWritePermission();
-        mManagedProfilePasswordCache.removePassword(userId);
+        mUnifiedProfilePasswordCache.removePassword(userId);
     }
 
     static String timestampToString(long timestamp) {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 1e8b387..6d123cc 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -501,10 +501,10 @@
         final UserInfo parentInfo = um.getProfileParent(userId);
 
         if (parentInfo == null) {
-            // This user owns its lock settings files - safe to delete them
+            // Delete files specific to non-profile users.
             deleteFile(getRebootEscrowFile(userId));
         } else {
-            // Managed profile
+            // Delete files specific to profile users.
             removeChildProfileLock(userId);
         }
 
diff --git a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java b/services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
similarity index 84%
rename from services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
rename to services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
index 1298fe8f..21caf76 100644
--- a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
+++ b/services/core/java/com/android/server/locksettings/UnifiedProfilePasswordCache.java
@@ -43,30 +43,31 @@
 import javax.crypto.spec.GCMParameterSpec;
 
 /**
- * Caches *unified* work challenge for managed profiles. The cached credential is encrypted using
- * a keystore key auth-bound to the parent user's lockscreen credential, similar to how unified
- * work challenge is normally secured.
- *
- * <p> The cache is filled whenever the managed profile's unified challenge is created or derived
- * (as part of the parent user's credential verification flow). It's removed when the profile is
- * deleted or a (separate) lockscreen credential is explicitly set on the profile. There is also
- * an ADB command to evict the cache "cmd lock_settings remove-cache --user X", to assist
- * development and testing.
-
- * <p> The encrypted credential is stored in-memory only so the cache does not persist across
- * reboots.
+ * An in-memory cache for unified profile passwords.  A "unified profile password" is the random
+ * password that the system automatically generates and manages for each profile that uses a unified
+ * challenge and where the parent user has a secure lock screen.
+ * <p>
+ * Each password in this cache is encrypted by a Keystore key that is auth-bound to the parent user.
+ * This is very similar to how the password is protected on-disk, but the in-memory cache uses a
+ * much longer timeout on the keys: 7 days instead of 30 seconds.  This enables use cases like
+ * unpausing work apps without requiring authentication as frequently.
+ * <p>
+ * Unified profile passwords are cached when they are created, or when they are decrypted as part of
+ * the parent user's LSKF verification flow.  They are removed when the profile is deleted or when a
+ * separate challenge is explicitly set on the profile.  There is also an ADB command to evict a
+ * cached password, "locksettings remove-cache --user X", to assist development and testing.
  */
 @VisibleForTesting // public visibility is needed for Mockito
-public class ManagedProfilePasswordCache {
+public class UnifiedProfilePasswordCache {
 
-    private static final String TAG = "ManagedProfilePasswordCache";
+    private static final String TAG = "UnifiedProfilePasswordCache";
     private static final int KEY_LENGTH = 256;
     private static final int CACHE_TIMEOUT_SECONDS = (int) TimeUnit.DAYS.toSeconds(7);
 
     private final SparseArray<byte[]> mEncryptedPasswords = new SparseArray<>();
     private final KeyStore mKeyStore;
 
-    public ManagedProfilePasswordCache(KeyStore keyStore) {
+    public UnifiedProfilePasswordCache(KeyStore keyStore) {
         mKeyStore = keyStore;
     }
 
@@ -151,7 +152,8 @@
                 Slog.d(TAG, "Cannot decrypt", e);
                 return null;
             }
-            LockscreenCredential result = LockscreenCredential.createManagedPassword(credential);
+            LockscreenCredential result =
+                    LockscreenCredential.createUnifiedProfilePassword(credential);
             Arrays.fill(credential, (byte) 0);
             return result;
         }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 18961c0..ee076c6 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -140,9 +140,9 @@
         }
 
         @Override
-        public ManagedProfilePasswordCache getManagedProfilePasswordCache(
+        public UnifiedProfilePasswordCache getUnifiedProfilePasswordCache(
                 java.security.KeyStore ks) {
-            return mock(ManagedProfilePasswordCache.class);
+            return mock(UnifiedProfilePasswordCache.class);
         }
 
         @Override