Fix ConfirmDeviceCredentials for work profiles

1) Fixed the theme for CDCA$InternalActivity to be transparent
2) CDCA only cares about biometrics, which are tied to userId
3) Moved shared methods to a util class

Fixes: 119296586

Test: Followed the steps in comment#1 of the bug linked above


Change-Id: Ie47fc7c3a53dfb7780087937e1ca83287cc52d71
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index eb3be0e..6ffc3b2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1463,7 +1463,7 @@
             android:exported="false"
             android:permission="android.permission.MANAGE_USERS"
             android:resizeableActivity="false"
-            android:theme="@android:style/Theme.NoDisplay">
+            android:theme="@android:style/Theme.Translucent.NoTitleBar">
             <intent-filter android:priority="1">
                 <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/src/com/android/settings/password/BiometricFragment.java b/src/com/android/settings/password/BiometricFragment.java
index 6e1ae10..3a12bac 100644
--- a/src/com/android/settings/password/BiometricFragment.java
+++ b/src/com/android/settings/password/BiometricFragment.java
@@ -50,6 +50,9 @@
     private Executor mClientExecutor;
     private AuthenticationCallback mClientCallback;
 
+    // Re-settable by the application.
+    private int mUserId;
+
     // Created/Initialized once and retained
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private PromptInfo mPromptInfo;
@@ -96,6 +99,10 @@
         mClientCallback = callback;
     }
 
+    public void setUser(int userId) {
+        mUserId = userId;
+    }
+
     public void cancel() {
         if (mCancellationSignal != null) {
             mCancellationSignal.cancel();
@@ -126,8 +133,8 @@
         mCancellationSignal = new CancellationSignal();
 
         // TODO: CC doesn't use crypto for now
-        mBiometricPrompt.authenticate(mCancellationSignal, mClientExecutor,
-                mAuthenticationCallback);
+        mBiometricPrompt.authenticateUser(mCancellationSignal, mClientExecutor,
+                mAuthenticationCallback, mUserId);
     }
 
     @Override
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index f68c04a..5eb1f32 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -20,9 +20,9 @@
 import android.app.Activity;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
 import android.content.Context;
 import android.content.Intent;
-import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
@@ -84,13 +84,13 @@
     private DevicePolicyManager mDevicePolicyManager;
     private LockPatternUtils mLockPatternUtils;
     private UserManager mUserManager;
+    private TrustManager mTrustManager;
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
     private Handler mHandler = new Handler(Looper.getMainLooper());
 
     private String mTitle;
     private String mDetails;
     private int mUserId;
-    private int mEffectiveUserId;
     private int mCredentialMode;
     private boolean mGoingToBackground;
 
@@ -108,10 +108,16 @@
                     showConfirmCredentials();
                 }
             }
-
         }
 
         public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
+            mTrustManager.setDeviceLockedForUser(mUserId, false);
+
+            ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, mUserManager,
+                    mUserId);
+            ConfirmDeviceCredentialUtils.checkForPendingIntent(
+                    ConfirmDeviceCredentialActivity.this);
+
             setResult(Activity.RESULT_OK);
             finish();
         }
@@ -124,6 +130,7 @@
         mBiometricManager = getSystemService(BiometricManager.class);
         mDevicePolicyManager = getSystemService(DevicePolicyManager.class);
         mUserManager = UserManager.get(this);
+        mTrustManager = getSystemService(TrustManager.class);
         mLockPatternUtils = new LockPatternUtils(this);
 
         Intent intent = getIntent();
@@ -134,7 +141,7 @@
         boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
 
         mUserId = UserHandle.myUserId();
-        mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
+        final int effectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
         if (isInternalActivity()) {
             try {
                 mUserId = Utils.getUserIdFromBundle(this, intent.getExtras());
@@ -162,21 +169,23 @@
         } else if (isManagedProfile && isInternalActivity()
                 && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
             mCredentialMode = CREDENTIAL_MANAGED;
-            if (isBiometricAllowed()) {
+            if (isBiometricAllowed(effectiveUserId)) {
                 showBiometricPrompt();
                 launchedBiometric = true;
             } else {
                 showConfirmCredentials();
+                launchedCDC = true;
             }
         } else {
             mCredentialMode = CREDENTIAL_NORMAL;
-            if (isBiometricAllowed()) {
+            if (isBiometricAllowed(effectiveUserId)) {
                 // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
                 // onAuthenticationError and do the right thing automatically.
                 showBiometricPrompt();
                 launchedBiometric = true;
             } else {
                 showConfirmCredentials();
+                launchedCDC = true;
             }
         }
 
@@ -217,19 +226,20 @@
     // credential. Otherwise, biometric can't unlock fbe/keystore through
     // verifyTiedProfileChallenge. In such case, we also wanna show the user message that
     // biometric is disabled due to device restart.
-    private boolean isStrongAuthRequired() {
-        return !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId)
+    private boolean isStrongAuthRequired(int effectiveUserId) {
+        return !mLockPatternUtils.isBiometricAllowedForUser(effectiveUserId)
                 || !mUserManager.isUserUnlocked(mUserId);
     }
 
-    private boolean isBiometricDisabledByAdmin() {
+    private boolean isBiometricDisabledByAdmin(int effectiveUserId) {
         final int disabledFeatures =
-                mDevicePolicyManager.getKeyguardDisabledFeatures(null, mEffectiveUserId);
+                mDevicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId);
         return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0;
     }
 
-    private boolean isBiometricAllowed() {
-        return !isStrongAuthRequired() && !isBiometricDisabledByAdmin();
+    private boolean isBiometricAllowed(int effectiveUserId) {
+        return !isStrongAuthRequired(effectiveUserId)
+                && !isBiometricDisabledByAdmin(effectiveUserId);
     }
 
     private void showBiometricPrompt() {
@@ -250,6 +260,7 @@
             newFragment = true;
         }
         mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
+        mBiometricFragment.setUser(mUserId);
 
         if (newFragment) {
             getSupportFragmentManager().beginTransaction()
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
index 9b677aa..2de7625 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
@@ -18,17 +18,12 @@
 package com.android.settings.password;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
 import android.app.Dialog;
-import android.app.IActivityManager;
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
-import android.app.trust.TrustManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentSender;
 import android.content.pm.UserInfo;
 import android.graphics.Point;
 import android.graphics.PorterDuff;
@@ -36,7 +31,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.view.View;
@@ -199,29 +193,6 @@
     public void startEnterAnimation() {
     }
 
-    protected void checkForPendingIntent() {
-        int taskId = getActivity().getIntent().getIntExtra(Intent.EXTRA_TASK_ID, -1);
-        if (taskId != -1) {
-            try {
-                IActivityManager activityManager = ActivityManager.getService();
-                final ActivityOptions options = ActivityOptions.makeBasic();
-                activityManager.startActivityFromRecents(taskId, options.toBundle());
-                return;
-            } catch (RemoteException e) {
-                // Do nothing.
-            }
-        }
-        IntentSender intentSender = getActivity().getIntent()
-                .getParcelableExtra(Intent.EXTRA_INTENT);
-        if (intentSender != null) {
-            try {
-                getActivity().startIntentSenderForResult(intentSender, -1, null, 0, 0, 0);
-            } catch (IntentSender.SendIntentException e) {
-                /* ignore */
-            }
-        }
-    }
-
     private void setWorkChallengeBackground(View baseView, int userId) {
         View mainContent = getActivity().findViewById(com.android.settings.R.id.main_content);
         if (mainContent != null) {
@@ -246,15 +217,6 @@
         }
     }
 
-    protected void reportSuccessfulAttempt() {
-        mLockPatternUtils.reportSuccessfulPasswordAttempt(mEffectiveUserId);
-        if (mUserManager.isManagedProfile(mEffectiveUserId)) {
-            // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth
-            // for work challenge only here.
-            mLockPatternUtils.userPresent(mEffectiveUserId);
-        }
-    }
-
     protected void reportFailedAttempt() {
         updateErrorMessage(
                 mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId) + 1);
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java
new file mode 100644
index 0000000..11d6924
--- /dev/null
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 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.settings.password;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.IActivityManager;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.RemoteException;
+import android.os.UserManager;
+
+import com.android.internal.widget.LockPatternUtils;
+
+/** Class containing methods shared between CDCA and CDCBA */
+public class ConfirmDeviceCredentialUtils {
+
+    public static void checkForPendingIntent(Activity activity) {
+        // See Change-Id I52c203735fa9b53fd2f7df971824747eeb930f36 for context
+        int taskId = activity.getIntent().getIntExtra(Intent.EXTRA_TASK_ID, -1);
+        if (taskId != -1) {
+            try {
+                IActivityManager activityManager = ActivityManager.getService();
+                final ActivityOptions options = ActivityOptions.makeBasic();
+                activityManager.startActivityFromRecents(taskId, options.toBundle());
+                return;
+            } catch (RemoteException e) {
+                // Do nothing.
+            }
+        }
+        IntentSender intentSender = activity.getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
+        if (intentSender != null) {
+            try {
+                activity.startIntentSenderForResult(intentSender, -1, null, 0, 0, 0);
+            } catch (IntentSender.SendIntentException e) {
+                /* ignore */
+            }
+        }
+    }
+
+    public static void reportSuccessfulAttempt(LockPatternUtils utils, UserManager userManager,
+            int userId) {
+        utils.reportSuccessfulPasswordAttempt(userId);
+        if (userManager.isManagedProfile(userId)) {
+            // Keyguard is responsible to disable StrongAuth for primary user. Disable StrongAuth
+            // for work challenge only here.
+            utils.userPresent(userId);
+        }
+    }
+}
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index d380fc9..45b8129 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -434,10 +434,11 @@
             mPasswordEntryInputDisabler.setInputEnabled(true);
             if (matched) {
                 if (newResult) {
-                    reportSuccessfulAttempt();
+                    ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
+                            mUserManager, mEffectiveUserId);
                 }
                 startDisappearAnimation(intent);
-                checkForPendingIntent();
+                ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
             } else {
                 if (timeoutMs > 0) {
                     refreshLockScreen();
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 95a0aca..83141ea 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -487,10 +487,11 @@
             mLockPatternView.setEnabled(true);
             if (matched) {
                 if (newResult) {
-                    reportSuccessfulAttempt();
+                    ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
+                            mUserManager, mEffectiveUserId);
                 }
                 startDisappearAnimation(intent);
-                checkForPendingIntent();
+                ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
             } else {
                 if (timeoutMs > 0) {
                     refreshLockScreen();