OSDN Git Service

CDCA is plumbed through BP
authorKevin Chyn <kchyn@google.com>
Fri, 25 Jan 2019 03:42:05 +0000 (19:42 -0800)
committerKevin Chyn <kchyn@google.com>
Sat, 26 Jan 2019 02:13:38 +0000 (18:13 -0800)
CDCA can be invoked with a bundle extra originating from BiometricService.
This allows us to add/forward new BP builder options to CDCA without having
duplicate API each time.

Bug: 111461540
Test: test app, receives correct callbacks
Test: CDC still works

Change-Id: Ia2080d161abba87949338176b34cdf440ed4ed53

src/com/android/settings/password/BiometricFragment.java
src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
src/com/android/settings/password/ConfirmLockPassword.java
src/com/android/settings/password/ConfirmLockPattern.java

index 13ec543..3809a4a 100644 (file)
@@ -30,6 +30,7 @@ import android.os.Looper;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
 
 import java.util.concurrent.Executor;
@@ -39,11 +40,6 @@ import java.util.concurrent.Executor;
  */
 public class BiometricFragment extends InstrumentedFragment {
 
-    private static final String KEY_TITLE = "title";
-    private static final String KEY_SUBTITLE = "subtitle";
-    private static final String KEY_DESCRIPTION = "description";
-    private static final String KEY_NEGATIVE_TEXT = "negative_text";
-
     // Re-set by the application. Should be done upon orientation changes, etc
     private Executor mClientExecutor;
     private AuthenticationCallback mClientCallback;
@@ -53,7 +49,7 @@ public class BiometricFragment extends InstrumentedFragment {
 
     // Created/Initialized once and retained
     private final Handler mHandler = new Handler(Looper.getMainLooper());
-    private PromptInfo mPromptInfo;
+    private Bundle mBundle;
     private BiometricPrompt mBiometricPrompt;
     private CancellationSignal mCancellationSignal;
 
@@ -82,13 +78,17 @@ public class BiometricFragment extends InstrumentedFragment {
         public void onClick(DialogInterface dialog, int which) {
             mAuthenticationCallback.onAuthenticationError(
                     BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON,
-                    mPromptInfo.getNegativeButtonText());
+                    mBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT));
         }
     };
 
-    public static BiometricFragment newInstance(PromptInfo info) {
+    /**
+     * @param bundle Bundle passed from {@link BiometricPrompt.Builder#buildIntent()}
+     * @return
+     */
+    public static BiometricFragment newInstance(Bundle bundle) {
         BiometricFragment biometricFragment = new BiometricFragment();
-        biometricFragment.setArguments(info.getBundle());
+        biometricFragment.setArguments(bundle);
         return biometricFragment;
     }
 
@@ -119,14 +119,16 @@ public class BiometricFragment extends InstrumentedFragment {
         super.onCreate(savedInstanceState);
         setRetainInstance(true);
 
-        mPromptInfo = new PromptInfo(getArguments());
+        mBundle = getArguments();
         mBiometricPrompt = new BiometricPrompt.Builder(getContext())
-            .setTitle(mPromptInfo.getTitle())
+            .setTitle(mBundle.getString(BiometricPrompt.KEY_TITLE))
             .setUseDefaultTitle() // use default title if title is null/empty
-            .setSubtitle(mPromptInfo.getSubtitle())
-            .setDescription(mPromptInfo.getDescription())
-            .setNegativeButton(mPromptInfo.getNegativeButtonText(), mClientExecutor,
-                    mNegativeButtonListener)
+            .setSubtitle(mBundle.getString(BiometricPrompt.KEY_SUBTITLE))
+            .setDescription(mBundle.getString(BiometricPrompt.KEY_DESCRIPTION))
+            .setRequireConfirmation(mBundle.getBoolean(BiometricPrompt.KEY_REQUIRE_CONFIRMATION))
+            .setNegativeButton(getResources().getString(
+                    R.string.confirm_device_credential_use_alternate_method),
+                    mClientExecutor, mNegativeButtonListener)
             .build();
         mCancellationSignal = new CancellationSignal();
 
@@ -139,65 +141,5 @@ public class BiometricFragment extends InstrumentedFragment {
     public int getMetricsCategory() {
         return SettingsEnums.BIOMETRIC_FRAGMENT;
     }
-
-    /**
-     * A simple wrapper for BiometricPrompt.PromptInfo. Since we want to manage the lifecycle
-     * of BiometricPrompt correctly, the information needs to be stored in here.
-     */
-    static class PromptInfo {
-        private final Bundle mBundle;
-
-        private PromptInfo(Bundle bundle) {
-            mBundle = bundle;
-        }
-
-        Bundle getBundle() {
-            return mBundle;
-        }
-
-        public CharSequence getTitle() {
-            return mBundle.getCharSequence(KEY_TITLE);
-        }
-
-        public CharSequence getSubtitle() {
-            return mBundle.getCharSequence(KEY_SUBTITLE);
-        }
-
-        public CharSequence getDescription() {
-            return mBundle.getCharSequence(KEY_DESCRIPTION);
-        }
-
-        public CharSequence getNegativeButtonText() {
-            return mBundle.getCharSequence(KEY_NEGATIVE_TEXT);
-        }
-
-        public static class Builder {
-            private final Bundle mBundle = new Bundle();
-
-            public Builder setTitle(@NonNull CharSequence title) {
-                mBundle.putCharSequence(KEY_TITLE, title);
-                return this;
-            }
-
-            public Builder setSubtitle(@Nullable CharSequence subtitle) {
-                mBundle.putCharSequence(KEY_SUBTITLE, subtitle);
-                return this;
-            }
-
-            public Builder setDescription(@Nullable CharSequence description) {
-                mBundle.putCharSequence(KEY_DESCRIPTION, description);
-                return this;
-            }
-
-            public Builder setNegativeButtonText(@NonNull CharSequence text) {
-                mBundle.putCharSequence(KEY_NEGATIVE_TEXT, text);
-                return this;
-            }
-
-            public PromptInfo build() {
-                return new PromptInfo(mBundle);
-            }
-        }
-    }
 }
 
index 5eb1f32..3fa2f6a 100644 (file)
@@ -23,6 +23,7 @@ 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;
@@ -87,6 +88,8 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
     private TrustManager mTrustManager;
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
     private Handler mHandler = new Handler(Looper.getMainLooper());
+    private boolean mIsFallback; // BiometricPrompt fallback
+    private boolean mCCLaunched;
 
     private String mTitle;
     private String mDetails;
@@ -102,6 +105,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
         public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
             if (!mGoingToBackground) {
                 if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) {
+                    if (mIsFallback) {
+                        mBiometricManager.onConfirmDeviceCredentialError(
+                                BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+                                getString(
+                                        com.android.internal.R.string
+                                                .biometric_error_user_canceled));
+                    }
                     finish();
                 } else {
                     // All other errors go to some version of CC
@@ -118,6 +128,10 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
             ConfirmDeviceCredentialUtils.checkForPendingIntent(
                     ConfirmDeviceCredentialActivity.this);
 
+            if (mIsFallback) {
+                mBiometricManager.onConfirmDeviceCredentialSuccess();
+            }
+
             setResult(Activity.RESULT_OK);
             finish();
         }
@@ -158,6 +172,19 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
         final LockPatternUtils lockPatternUtils = new LockPatternUtils(this);
 
+        Bundle bpBundle =
+                intent.getBundleExtra(KeyguardManager.EXTRA_BIOMETRIC_PROMPT_BUNDLE);
+        if (bpBundle != null) {
+            mIsFallback = true;
+            // TODO: CDC maybe should show description as well.
+            mTitle = bpBundle.getString(BiometricPrompt.KEY_TITLE);
+            mDetails = bpBundle.getString(BiometricPrompt.KEY_SUBTITLE);
+        } else {
+            bpBundle = new Bundle();
+            bpBundle.putString(BiometricPrompt.KEY_TITLE, mTitle);
+            bpBundle.putString(BiometricPrompt.KEY_SUBTITLE, mDetails);
+        }
+
         boolean launchedBiometric = false;
         boolean launchedCDC = false;
         // If the target is a managed user and user key not unlocked yet, we will force unlock
@@ -170,7 +197,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
                 && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
             mCredentialMode = CREDENTIAL_MANAGED;
             if (isBiometricAllowed(effectiveUserId)) {
-                showBiometricPrompt();
+                showBiometricPrompt(bpBundle);
                 launchedBiometric = true;
             } else {
                 showConfirmCredentials();
@@ -181,7 +208,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
             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();
+                showBiometricPrompt(bpBundle);
                 launchedBiometric = true;
             } else {
                 showConfirmCredentials();
@@ -216,6 +243,13 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
             if (mBiometricFragment != null) {
                 mBiometricFragment.cancel();
             }
+
+            if (mIsFallback && !mCCLaunched) {
+                mBiometricManager.onConfirmDeviceCredentialError(
+                        BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+                        getString(com.android.internal.R.string.biometric_error_user_canceled));
+            }
+
             finish();
         } else {
             mGoingToBackground = false;
@@ -242,7 +276,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
                 && !isBiometricDisabledByAdmin(effectiveUserId);
     }
 
-    private void showBiometricPrompt() {
+    private void showBiometricPrompt(Bundle bundle) {
         mBiometricManager.setActiveUser(mUserId);
 
         mBiometricFragment = (BiometricFragment) getSupportFragmentManager()
@@ -250,13 +284,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
         boolean newFragment = false;
 
         if (mBiometricFragment == null) {
-            final BiometricFragment.PromptInfo info = new BiometricFragment.PromptInfo.Builder()
-                    .setTitle(mTitle)
-                    .setSubtitle(mDetails)
-                    .setNegativeButtonText(getResources()
-                            .getString(R.string.confirm_device_credential_use_alternate_method))
-                    .build();
-            mBiometricFragment = BiometricFragment.newInstance(info);
+            mBiometricFragment = BiometricFragment.newInstance(bundle);
             newFragment = true;
         }
         mBiometricFragment.setCallbacks(mExecutor, mAuthenticationCallback);
@@ -272,6 +300,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
      * Shows ConfirmDeviceCredentials for normal apps.
      */
     private void showConfirmCredentials() {
+        mCCLaunched = true;
         boolean launched = false;
         if (mCredentialMode == CREDENTIAL_MANAGED) {
             // We set the challenge as 0L, so it will force to unlock managed profile when it
index c00f9ab..56e6573 100644 (file)
@@ -17,6 +17,8 @@
 package com.android.settings.password;
 
 import android.app.KeyguardManager;
+import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricManager;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.view.MenuItem;
@@ -45,6 +47,7 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
     private boolean mFirstTimeVisible = true;
     private boolean mIsKeyguardLocked = false;
     private ConfirmCredentialTheme mConfirmCredentialTheme;
+    private BiometricManager mBiometricManager;
 
     private boolean isInternalActivity() {
         return (this instanceof ConfirmLockPassword.InternalActivity)
@@ -68,6 +71,8 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
         }
         super.onCreate(savedState);
 
+        mBiometricManager = getSystemService(BiometricManager.class);
+
         if (mConfirmCredentialTheme == ConfirmCredentialTheme.NORMAL) {
             // Prevent the content parent from consuming the window insets because GlifLayout uses
             // it to show the status bar background.
@@ -141,6 +146,17 @@ public abstract class ConfirmDeviceCredentialBaseActivity extends SettingsActivi
     }
 
     @Override
+    public void onStop() {
+        super.onStop();
+        // TODO(b/123378871): Remove when moved.
+        if (!isChangingConfigurations()) {
+            mBiometricManager.onConfirmDeviceCredentialError(
+                    BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+                    getString(com.android.internal.R.string.biometric_error_user_canceled));
+        }
+    }
+
+    @Override
     public void finish() {
         super.finish();
         if (getIntent().getBooleanExtra(
index 2de7625..e14ec81 100644 (file)
@@ -29,6 +29,7 @@ import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserManager;
@@ -84,6 +85,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
     protected final Handler mHandler = new Handler();
     protected boolean mFrp;
     private CharSequence mFrpAlternateButtonText;
+    protected BiometricManager mBiometricManager;
 
     private boolean isInternalActivity() {
         return (getActivity() instanceof ConfirmLockPassword.InternalActivity)
@@ -107,6 +109,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
         mLockPatternUtils = new LockPatternUtils(getActivity());
         mDevicePolicyManager = (DevicePolicyManager) getActivity().getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
+        mBiometricManager = getActivity().getSystemService(BiometricManager.class);
     }
 
     @Override
index 7344077..f893870 100644 (file)
@@ -437,6 +437,7 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
                     ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
                             mUserManager, mEffectiveUserId);
                 }
+                mBiometricManager.onConfirmDeviceCredentialSuccess();
                 startDisappearAnimation(intent);
                 ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
             } else {
index 5645193..29cdfef 100644 (file)
@@ -490,6 +490,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
                     ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils,
                             mUserManager, mEffectiveUserId);
                 }
+                mBiometricManager.onConfirmDeviceCredentialSuccess();
                 startDisappearAnimation(intent);
                 ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity());
             } else {