1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.settings.biometrics; 18 19 import android.app.admin.DevicePolicyManager; 20 import android.app.settings.SettingsEnums; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.hardware.biometrics.BiometricManager; 24 import android.hardware.biometrics.BiometricManager.Authenticators; 25 import android.os.Bundle; 26 import android.os.UserHandle; 27 import android.provider.Settings; 28 import android.util.Log; 29 30 import com.android.settings.SetupWizardUtils; 31 import com.android.settings.biometrics.face.FaceEnrollIntroduction; 32 import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor; 33 import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction; 34 import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction; 35 import com.android.settings.core.InstrumentedActivity; 36 import com.android.settings.password.ChooseLockGeneric; 37 import com.android.settings.password.ChooseLockSettingsHelper; 38 39 import com.google.android.setupcompat.util.WizardManagerHelper; 40 41 /** 42 * Trampoline activity launched by the {@code android.settings.BIOMETRIC_ENROLL} action which 43 * shows the user an appropriate enrollment flow depending on the device's biometric hardware. 44 * This activity must only allow enrollment of biometrics that can be used by 45 * {@link android.hardware.biometrics.BiometricPrompt}. 46 */ 47 public class BiometricEnrollActivity extends InstrumentedActivity { 48 49 private static final String TAG = "BiometricEnrollActivity"; 50 51 public static final String EXTRA_SKIP_INTRO = "skip_intro"; 52 53 public static final class InternalActivity extends BiometricEnrollActivity {} 54 55 @Override onCreate(Bundle savedInstanceState)56 public void onCreate(Bundle savedInstanceState) { 57 super.onCreate(savedInstanceState); 58 59 // Default behavior is to enroll BIOMETRIC_WEAK or above. See ACTION_BIOMETRIC_ENROLL. 60 final int authenticators = getIntent().getIntExtra( 61 Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, Authenticators.BIOMETRIC_WEAK); 62 63 Log.d(TAG, "Authenticators: " + authenticators); 64 65 final BiometricManager bm = getSystemService(BiometricManager.class); 66 final PackageManager pm = getApplicationContext().getPackageManager(); 67 Intent intent = null; 68 69 final int result = bm.canAuthenticate(authenticators); 70 71 if (!WizardManagerHelper.isAnySetupWizard(getIntent())) { 72 if (result == BiometricManager.BIOMETRIC_SUCCESS 73 || result == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) { 74 Log.e(TAG, "Unexpected result: " + result); 75 finish(); 76 return; 77 } 78 } 79 80 if (authenticators == BiometricManager.Authenticators.DEVICE_CREDENTIAL) { 81 // If only device credential was specified, ask the user to only set that up. 82 intent = new Intent(this, ChooseLockGeneric.class); 83 intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, 84 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING); 85 } else if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 86 // This logic may have to be modified on devices with multiple biometrics. 87 // ChooseLockGeneric can request to start fingerprint enroll bypassing the intro screen. 88 if (getIntent().getBooleanExtra(EXTRA_SKIP_INTRO, false) 89 && this instanceof InternalActivity) { 90 intent = getFingerprintFindSensorIntent(); 91 } else { 92 intent = getFingerprintIntroIntent(); 93 } 94 } else if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { 95 intent = getFaceIntroIntent(); 96 } 97 98 if (intent != null) { 99 intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 100 101 if (this instanceof InternalActivity) { 102 // Propagate challenge and user Id from ChooseLockGeneric. 103 final byte[] token = getIntent() 104 .getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); 105 final int userId = getIntent() 106 .getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL); 107 108 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); 109 intent.putExtra(Intent.EXTRA_USER_ID, userId); 110 } 111 112 startActivity(intent); 113 finish(); 114 } else { 115 Log.e(TAG, "Intent was null, finishing"); 116 finish(); 117 } 118 } 119 getFingerprintFindSensorIntent()120 private Intent getFingerprintFindSensorIntent() { 121 Intent intent = new Intent(this, FingerprintEnrollFindSensor.class); 122 SetupWizardUtils.copySetupExtras(getIntent(), intent); 123 return intent; 124 } 125 getFingerprintIntroIntent()126 private Intent getFingerprintIntroIntent() { 127 if (WizardManagerHelper.isAnySetupWizard(getIntent())) { 128 Intent intent = new Intent(this, SetupFingerprintEnrollIntroduction.class); 129 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 130 return intent; 131 } else { 132 return new Intent(this, FingerprintEnrollIntroduction.class); 133 } 134 } 135 getFaceIntroIntent()136 private Intent getFaceIntroIntent() { 137 Intent intent = new Intent(this, FaceEnrollIntroduction.class); 138 WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent); 139 return intent; 140 } 141 142 @Override getMetricsCategory()143 public int getMetricsCategory() { 144 return SettingsEnums.BIOMETRIC_ENROLL_ACTIVITY; 145 } 146 } 147