1 /* 2 * Copyright (C) 2015 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.fingerprint; 18 19 import android.app.settings.SettingsEnums; 20 import android.content.ComponentName; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.hardware.fingerprint.FingerprintManager; 24 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 25 import android.os.Bundle; 26 import android.util.Log; 27 import android.view.View; 28 29 import androidx.annotation.VisibleForTesting; 30 31 import com.android.settings.R; 32 import com.android.settings.Utils; 33 import com.android.settings.biometrics.BiometricEnrollBase; 34 import com.android.settings.biometrics.BiometricUtils; 35 36 import com.google.android.setupcompat.template.FooterBarMixin; 37 import com.google.android.setupcompat.template.FooterButton; 38 import com.google.android.setupcompat.util.WizardManagerHelper; 39 40 import java.util.List; 41 /** 42 * Activity which concludes fingerprint enrollment. 43 */ 44 public class FingerprintEnrollFinish extends BiometricEnrollBase { 45 46 private static final String TAG = "FingerprintEnrollFinish"; 47 private static final String ACTION_FINGERPRINT_SETTINGS = 48 "android.settings.FINGERPRINT_SETTINGS"; 49 @VisibleForTesting 50 static final String FINGERPRINT_SUGGESTION_ACTIVITY = 51 "com.android.settings.SetupFingerprintSuggestionActivity"; 52 53 private FingerprintManager mFingerprintManager; 54 55 private boolean mCanAssumeSfps; 56 57 private boolean mIsAddAnotherOrFinish; 58 59 @Override onCreate(Bundle savedInstanceState)60 protected void onCreate(Bundle savedInstanceState) { 61 super.onCreate(savedInstanceState); 62 mFingerprintManager = getSystemService(FingerprintManager.class); 63 final List<FingerprintSensorPropertiesInternal> props = 64 mFingerprintManager.getSensorPropertiesInternal(); 65 mCanAssumeSfps = props != null && props.size() == 1 && props.get(0).isAnySidefpsType(); 66 if (mCanAssumeSfps) { 67 setContentView(R.layout.sfps_enroll_finish); 68 } else { 69 setContentView(R.layout.fingerprint_enroll_finish); 70 } 71 setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title); 72 setDescriptionText(R.string.security_settings_fingerprint_enroll_finish_v2_message); 73 if (mCanAssumeSfps) { 74 setDescriptionForSfps(); 75 } 76 77 mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class); 78 mFooterBarMixin.setSecondaryButton( 79 new FooterButton.Builder(this) 80 .setText(R.string.fingerprint_enroll_button_add) 81 .setButtonType(FooterButton.ButtonType.SKIP) 82 .setTheme(R.style.SudGlifButton_Secondary) 83 .build() 84 ); 85 86 mFooterBarMixin.setPrimaryButton( 87 new FooterButton.Builder(this) 88 .setText(R.string.security_settings_fingerprint_enroll_done) 89 .setListener(this::onNextButtonClick) 90 .setButtonType(FooterButton.ButtonType.NEXT) 91 .setTheme(R.style.SudGlifButton_Primary) 92 .build() 93 ); 94 } 95 setDescriptionForSfps()96 private void setDescriptionForSfps() { 97 final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); 98 if (fpm != null) { 99 final List<FingerprintSensorPropertiesInternal> props = 100 fpm.getSensorPropertiesInternal(); 101 final int maxEnrollments = props.get(0).maxEnrollmentsPerUser; 102 final int enrolled = fpm.getEnrolledFingerprints(mUserId).size(); 103 if (enrolled < maxEnrollments) { 104 setDescriptionText(R.string 105 .security_settings_fingerprint_enroll_finish_v2_add_fingerprint_message); 106 } 107 } 108 } 109 110 @Override onBackPressed()111 public void onBackPressed() { 112 updateFingerprintSuggestionEnableState(); 113 Intent intent = getIntent().putExtra(EXTRA_FINISHED_ENROLL_FINGERPRINT, true); 114 setResult(RESULT_CANCELED, intent); 115 finish(); 116 } 117 118 @Override onResume()119 protected void onResume() { 120 super.onResume(); 121 FooterButton addButton = mFooterBarMixin.getSecondaryButton(); 122 123 final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); 124 boolean hideAddAnother = false; 125 if (fpm != null) { 126 final List<FingerprintSensorPropertiesInternal> props = 127 fpm.getSensorPropertiesInternal(); 128 int maxEnrollments = props.get(0).maxEnrollmentsPerUser; 129 int enrolled = fpm.getEnrolledFingerprints(mUserId).size(); 130 hideAddAnother = enrolled >= maxEnrollments; 131 } 132 if (hideAddAnother) { 133 // Don't show "Add" button if too many fingerprints already added 134 addButton.setVisibility(View.INVISIBLE); 135 } else { 136 addButton.setOnClickListener(this::onAddAnotherButtonClick); 137 } 138 } 139 140 @Override onStart()141 protected void onStart() { 142 super.onStart(); 143 144 // Reset it to false every time activity back to fg because this flag is stateless between 145 // different life cycle. 146 mIsAddAnotherOrFinish = false; 147 } 148 149 @Override onNextButtonClick(View view)150 protected void onNextButtonClick(View view) { 151 updateFingerprintSuggestionEnableState(); 152 finishAndToNext(RESULT_FINISHED); 153 } 154 finishAndToNext(int resultCode)155 private void finishAndToNext(int resultCode) { 156 mIsAddAnotherOrFinish = true; 157 setResult(resultCode); 158 if (WizardManagerHelper.isAnySetupWizard(getIntent())) { 159 postEnroll(); 160 } 161 finish(); 162 } 163 updateFingerprintSuggestionEnableState()164 private void updateFingerprintSuggestionEnableState() { 165 final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); 166 if (fpm != null) { 167 int enrolled = fpm.getEnrolledFingerprints(mUserId).size(); 168 169 // Only show "Add another fingerprint" if the user already enrolled one. 170 // "Add fingerprint" will be shown in the main flow if the user hasn't enrolled any 171 // fingerprints. If the user already added more than one fingerprint, they already know 172 // to add multiple fingerprints so we don't show the suggestion. 173 int flag = (enrolled == 1) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED 174 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 175 176 ComponentName componentName = new ComponentName(getApplicationContext(), 177 FINGERPRINT_SUGGESTION_ACTIVITY); 178 getPackageManager().setComponentEnabledSetting( 179 componentName, flag, PackageManager.DONT_KILL_APP); 180 Log.d(TAG, FINGERPRINT_SUGGESTION_ACTIVITY + " enabled state = " + (enrolled == 1)); 181 } 182 } 183 postEnroll()184 private void postEnroll() { 185 final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); 186 if (fpm != null) { 187 fpm.revokeChallenge(mUserId, mChallenge); 188 } 189 } 190 onAddAnotherButtonClick(View view)191 private void onAddAnotherButtonClick(View view) { 192 mIsAddAnotherOrFinish = true; 193 startActivityForResult(getFingerprintEnrollingIntent(), BiometricUtils.REQUEST_ADD_ANOTHER); 194 } 195 196 @Override shouldFinishWhenBackgrounded()197 protected boolean shouldFinishWhenBackgrounded() { 198 return !mIsAddAnotherOrFinish && super.shouldFinishWhenBackgrounded(); 199 } 200 201 @Override onActivityResult(int requestCode, int resultCode, Intent data)202 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 203 updateFingerprintSuggestionEnableState(); 204 if (requestCode == BiometricUtils.REQUEST_ADD_ANOTHER && resultCode == RESULT_TIMEOUT) { 205 finishAndToNext(resultCode); 206 } else if (requestCode == BiometricUtils.REQUEST_ADD_ANOTHER 207 && resultCode != RESULT_CANCELED) { 208 // If user cancel during "Add another", just use similar flow on "Next" button 209 finishAndToNext(RESULT_FINISHED); 210 } else { 211 super.onActivityResult(requestCode, resultCode, data); 212 } 213 } 214 215 @Override getMetricsCategory()216 public int getMetricsCategory() { 217 return SettingsEnums.FINGERPRINT_ENROLL_FINISH; 218 } 219 } 220