Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62db4b3a authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add mandatory biometric prompt to platform surfaces (1/N)" into main

parents 90d327f0 049de84f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -934,7 +934,8 @@
    <string name="security_settings_fingerprint_single_face_watch_preference_summary">Face, fingerprint, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
    <!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face,  and active unlock settings or enrollment. [CHAR LIMIT=80]-->
    <string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
    <!-- Description for mandatory biometrics prompt-->
    <string name="mandatory_biometrics_prompt_description">This is needed since Identity Check is on</string>
    <!-- RemoteAuth unlock enrollment and settings --><skip />
    <!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
    <string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
+54 −0
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;

import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_AUTHENTICATORS;
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT;

import android.app.ActionBar;
import android.app.Activity;
import android.app.ActivityManager;
@@ -54,6 +57,7 @@ import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.SensorProperties;
import android.hardware.face.Face;
import android.hardware.face.FaceManager;
@@ -122,6 +126,7 @@ import com.android.settings.dashboard.profileselector.ProfileFragmentBridge;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settingslib.widget.ActionBarShadowController;
import com.android.settingslib.widget.AdaptiveIcon;

@@ -1478,6 +1483,55 @@ public final class Utils extends com.android.settingslib.Utils {
        disableComponent(pm, new ComponentName(context, Settings.CreateShortcutActivity.class));
    }

    /**
     * Request biometric authentication if all requirements for mandatory biometrics is satisfied.
     * @param context of the corresponding activity/fragment
     * @param biometricsSuccessfullyAuthenticated if the user has already authenticated using
     *                                            biometrics
     * @param biometricsAuthenticationRequested if the activity/fragment has already requested for
     *                                          biometric prompt
     * @return true if all requirements for mandatory biometrics is satisfied
     */
    public static boolean requestBiometricAuthenticationForMandatoryBiometrics(
            @NonNull Context context,
            boolean biometricsSuccessfullyAuthenticated,
            boolean biometricsAuthenticationRequested) {
        final BiometricManager biometricManager = context.getSystemService(BiometricManager.class);
        if (biometricManager == null) {
            Log.e(TAG, "Biometric Manager is null.");
            return false;
        }
        final int status = biometricManager.canAuthenticate(
                BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
        return android.hardware.biometrics.Flags.mandatoryBiometrics()
                && status == BiometricManager.BIOMETRIC_SUCCESS
                && !biometricsSuccessfullyAuthenticated
                && !biometricsAuthenticationRequested;
    }

    /**
     * Launch biometric prompt for mandatory biometrics. Call
     * {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, boolean)}
     * to check if all requirements for mandatory biometrics is satisfied
     * before launching biometric prompt.
     *
     * @param fragment corresponding fragment of the surface
     * @param requestCode for starting the new activity
     */
    public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Fragment fragment,
            int requestCode) {
        final Intent intent = new Intent();
        intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
                BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
        intent.putExtra(BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT,
                fragment.getString(R.string.cancel));
        intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION,
                fragment.getString(R.string.mandatory_biometrics_prompt_description));
        intent.setClassName(SETTINGS_PACKAGE_NAME,
                ConfirmDeviceCredentialActivity.class.getName());
        fragment.startActivityForResult(intent, requestCode);
    }

    private static void disableComponent(PackageManager pm, ComponentName componentName) {
        pm.setComponentEnabledSetting(componentName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+3 −0
Original line number Diff line number Diff line
@@ -68,6 +68,8 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
    public static final String EXTRA_FINISHED_ENROLL_FACE = "finished_enrolling_face";
    public static final String EXTRA_FINISHED_ENROLL_FINGERPRINT = "finished_enrolling_fingerprint";
    public static final String EXTRA_LAUNCHED_POSTURE_GUIDANCE = "launched_posture_guidance";
    public static final String EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
            "biometrics_authenticated_successfully";

    /**
     * Used by the choose fingerprint wizard to indicate the wizard is
@@ -115,6 +117,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
    public static final int LEARN_MORE_REQUEST = 3;
    public static final int CONFIRM_REQUEST = 4;
    public static final int ENROLL_REQUEST = 5;
    public static final int BIOMETRIC_AUTH_REQUEST = 6;

    /**
     * Request code when starting another biometric enrollment from within a biometric flow. For
+41 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
    static final int CONFIRM_REQUEST = 2001;
    private static final int CHOOSE_LOCK_REQUEST = 2002;
    protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
    private static final int BIOMETRIC_AUTH_REQUEST = 2004;

    private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
    private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";
@@ -72,10 +73,15 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
    static final String RETRY_PREFERENCE_KEY = "retry_preference_key";
    @VisibleForTesting
    static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
    private static final String BIOMETRICS_AUTH_REQUESTED = "biometrics_auth_requested";
    private static final String BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
            "biometrics_authenticated_successfully";

    protected int mUserId;
    protected long mGkPwHandle;
    private boolean mConfirmCredential;
    private boolean mBiometricsAuthenticationRequested;
    private boolean mBiometricsSuccessfullyAuthenticated;
    @Nullable private FaceManager mFaceManager;
    @Nullable private FingerprintManager mFingerprintManager;
    // Do not finish() if choosing/confirming credential, showing fp/face settings, or launching
@@ -113,6 +119,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
            mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent());
        }

        mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
                BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);

        if (savedInstanceState != null) {
            mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
            mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
@@ -123,11 +132,20 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
                mGkPwHandle = savedInstanceState.getLong(
                        ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE);
            }
            mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
                    BIOMETRICS_AUTH_REQUESTED);
            mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
                    BIOMETRICS_AUTHENTICATED_SUCCESSFULLY);
        }

        if (mGkPwHandle == 0L && !mConfirmCredential) {
            mConfirmCredential = true;
            launchChooseOrConfirmLock();
        } else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(
                getActivity(), mBiometricsSuccessfullyAuthenticated,
                mBiometricsAuthenticationRequested)) {
            mBiometricsAuthenticationRequested = true;
            Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
        }

        updateUnlockPhonePreferenceSummary();
@@ -141,6 +159,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
    @Override
    public void onResume() {
        super.onResume();
        if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
                mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)
                && mGkPwHandle != 0L) {
            mBiometricsAuthenticationRequested = true;
            Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
        }
        if (!mConfirmCredential) {
            mDoNotFinishActivity = false;
        }
@@ -177,6 +201,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
                    extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
                    extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
                    extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
                    extras.putBoolean(
                            BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
                            mBiometricsSuccessfullyAuthenticated);
                    onFaceOrFingerprintPreferenceTreeClick(preference);
                } catch (IllegalStateException e) {
                    if (retry) {
@@ -206,6 +233,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
                    final Bundle extras = preference.getExtras();
                    extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
                    extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
                    extras.putBoolean(
                            BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
                            mBiometricsSuccessfullyAuthenticated);
                    onFaceOrFingerprintPreferenceTreeClick(preference);
                } catch (IllegalStateException e) {
                    if (retry) {
@@ -288,6 +318,10 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
            outState.putString(RETRY_PREFERENCE_KEY, mRetryPreferenceKey);
            outState.putBundle(RETRY_PREFERENCE_BUNDLE, mRetryPreferenceExtra);
        }
        outState.putBoolean(BIOMETRICS_AUTH_REQUESTED,
                mBiometricsAuthenticationRequested);
        outState.putBoolean(BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
                mBiometricsSuccessfullyAuthenticated);
    }

    @Override
@@ -315,6 +349,13 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
            }
            mRetryPreferenceKey = null;
            mRetryPreferenceExtra = null;
        } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
            mBiometricsAuthenticationRequested = false;
            if (resultCode == RESULT_OK) {
                mBiometricsSuccessfullyAuthenticated = true;
            } else {
                finish();
            }
        }
    }

+23 −0
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@ import static android.app.Activity.RESULT_OK;
import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_SETTINGS_FOR_WORK_TITLE;

import static com.android.settings.Utils.isPrivateProfile;
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;

@@ -66,6 +68,8 @@ public class FaceSettings extends DashboardFragment {
    private static final String TAG = "FaceSettings";
    private static final String KEY_TOKEN = "hw_auth_token";
    private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
    private static final String KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED =
            "biometrics_successfully_authenticated";

    private static final String PREF_KEY_DELETE_FACE_DATA =
            "security_settings_face_delete_faces_container";
@@ -93,6 +97,8 @@ public class FaceSettings extends DashboardFragment {
    private FaceFeatureProvider mFaceFeatureProvider;

    private boolean mConfirmingPassword;
    private boolean mBiometricsAuthenticationRequested;
    private boolean mBiometricsSuccessfullyAuthenticated;

    private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {

@@ -144,6 +150,8 @@ public class FaceSettings extends DashboardFragment {
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putByteArray(KEY_TOKEN, mToken);
        outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
                mBiometricsSuccessfullyAuthenticated);
    }

    @Override
@@ -163,6 +171,8 @@ public class FaceSettings extends DashboardFragment {
        mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
        mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
        mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
        mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
                EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);

        mUserId = getActivity().getIntent().getIntExtra(
                Intent.EXTRA_USER_ID, UserHandle.myUserId());
@@ -231,6 +241,8 @@ public class FaceSettings extends DashboardFragment {

        if (savedInstanceState != null) {
            mToken = savedInstanceState.getByteArray(KEY_TOKEN);
            mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
                    KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
        }
    }

@@ -276,6 +288,10 @@ public class FaceSettings extends DashboardFragment {
                Log.e(TAG, "Password not set");
                finish();
            }
        } else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
                mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)) {
            mBiometricsAuthenticationRequested = true;
            Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
        } else {
            mAttentionController.setToken(mToken);
            mEnrollController.setToken(mToken);
@@ -318,6 +334,13 @@ public class FaceSettings extends DashboardFragment {
                setResult(resultCode, data);
                finish();
            }
        } else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
            mBiometricsAuthenticationRequested = false;
            if (resultCode == RESULT_OK) {
                mBiometricsSuccessfullyAuthenticated = true;
            } else {
                finish();
            }
        }
    }

Loading