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 static com.android.settings.Utils.SETTINGS_PACKAGE_NAME; 20 21 import android.annotation.Nullable; 22 import android.content.Intent; 23 import android.content.res.Resources; 24 import android.graphics.Color; 25 import android.os.Bundle; 26 import android.os.UserHandle; 27 import android.text.TextUtils; 28 import android.view.View; 29 import android.widget.TextView; 30 31 import com.android.settings.R; 32 import com.android.settings.SetupWizardUtils; 33 import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling; 34 import com.android.settings.core.InstrumentedActivity; 35 import com.android.settings.password.ChooseLockSettingsHelper; 36 37 import com.google.android.setupcompat.template.FooterBarMixin; 38 import com.google.android.setupcompat.template.FooterButton; 39 import com.google.android.setupcompat.util.WizardManagerHelper; 40 import com.google.android.setupdesign.GlifLayout; 41 42 /** 43 * Base activity for all biometric enrollment steps. 44 */ 45 public abstract class BiometricEnrollBase extends InstrumentedActivity { 46 47 public static final String EXTRA_FROM_SETTINGS_SUMMARY = "from_settings_summary"; 48 public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock"; 49 public static final String EXTRA_KEY_REQUIRE_VISION = "accessibility_vision"; 50 public static final String EXTRA_KEY_REQUIRE_DIVERSITY = "accessibility_diversity"; 51 52 /** 53 * Used by the choose fingerprint wizard to indicate the wizard is 54 * finished, and each activity in the wizard should finish. 55 * <p> 56 * Previously, each activity in the wizard would finish itself after 57 * starting the next activity. However, this leads to broken 'Back' 58 * behavior. So, now an activity does not finish itself until it gets this 59 * result. 60 */ 61 public static final int RESULT_FINISHED = RESULT_FIRST_USER; 62 63 /** 64 * Used by the enrolling screen during setup wizard to skip over setting up fingerprint, which 65 * will be useful if the user accidentally entered this flow. 66 */ 67 public static final int RESULT_SKIP = RESULT_FIRST_USER + 1; 68 69 /** 70 * Like {@link #RESULT_FINISHED} except this one indicates enrollment failed because the 71 * device was left idle. This is used to clear the credential token to require the user to 72 * re-enter their pin/pattern/password before continuing. 73 */ 74 public static final int RESULT_TIMEOUT = RESULT_FIRST_USER + 2; 75 76 public static final int CHOOSE_LOCK_GENERIC_REQUEST = 1; 77 public static final int BIOMETRIC_FIND_SENSOR_REQUEST = 2; 78 public static final int LEARN_MORE_REQUEST = 3; 79 public static final int CONFIRM_REQUEST = 4; 80 public static final int ENROLL_REQUEST = 5; 81 82 protected boolean mLaunchedConfirmLock; 83 protected byte[] mToken; 84 protected int mUserId; 85 protected boolean mFromSettingsSummary; 86 protected FooterBarMixin mFooterBarMixin; 87 88 @Override onCreate(Bundle savedInstanceState)89 protected void onCreate(Bundle savedInstanceState) { 90 super.onCreate(savedInstanceState); 91 mToken = getIntent().getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); 92 mFromSettingsSummary = getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false); 93 if (savedInstanceState != null && mToken == null) { 94 mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM); 95 mToken = savedInstanceState.getByteArray( 96 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); 97 mFromSettingsSummary = 98 savedInstanceState.getBoolean(EXTRA_FROM_SETTINGS_SUMMARY, false); 99 } 100 mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); 101 } 102 103 @Override onApplyThemeResource(Resources.Theme theme, int resid, boolean first)104 protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { 105 resid = SetupWizardUtils.getTheme(getIntent()); 106 theme.applyStyle(R.style.SetupWizardPartnerResource, true); 107 super.onApplyThemeResource(theme, resid, first); 108 } 109 110 @Override onSaveInstanceState(Bundle outState)111 protected void onSaveInstanceState(Bundle outState) { 112 super.onSaveInstanceState(outState); 113 outState.putBoolean(EXTRA_KEY_LAUNCHED_CONFIRM, mLaunchedConfirmLock); 114 outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); 115 outState.putBoolean(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary); 116 } 117 118 @Override onPostCreate(@ullable Bundle savedInstanceState)119 protected void onPostCreate(@Nullable Bundle savedInstanceState) { 120 super.onPostCreate(savedInstanceState); 121 initViews(); 122 } 123 124 @Override onStop()125 protected void onStop() { 126 super.onStop(); 127 if (!isChangingConfigurations() && shouldFinishWhenBackgrounded()) { 128 setResult(RESULT_TIMEOUT); 129 finish(); 130 } 131 } 132 shouldFinishWhenBackgrounded()133 protected boolean shouldFinishWhenBackgrounded() { 134 return !WizardManagerHelper.isAnySetupWizard(getIntent()); 135 } 136 initViews()137 protected void initViews() { 138 getWindow().setStatusBarColor(Color.TRANSPARENT); 139 } 140 getLayout()141 protected GlifLayout getLayout() { 142 return (GlifLayout) findViewById(R.id.setup_wizard_layout); 143 } 144 setHeaderText(int resId, boolean force)145 protected void setHeaderText(int resId, boolean force) { 146 TextView layoutTitle = getLayout().getHeaderTextView(); 147 CharSequence previousTitle = layoutTitle.getText(); 148 CharSequence title = getText(resId); 149 if (previousTitle != title || force) { 150 if (!TextUtils.isEmpty(previousTitle)) { 151 layoutTitle.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE); 152 } 153 getLayout().setHeaderText(title); 154 setTitle(title); 155 } 156 } 157 setHeaderText(int resId)158 protected void setHeaderText(int resId) { 159 setHeaderText(resId, false /* force */); 160 } 161 getNextButton()162 protected FooterButton getNextButton() { 163 if (mFooterBarMixin != null) { 164 return mFooterBarMixin.getPrimaryButton(); 165 } 166 return null; 167 } 168 onNextButtonClick(View view)169 protected void onNextButtonClick(View view) { 170 } 171 getFingerprintEnrollingIntent()172 protected Intent getFingerprintEnrollingIntent() { 173 Intent intent = new Intent(); 174 intent.setClassName(SETTINGS_PACKAGE_NAME, FingerprintEnrollEnrolling.class.getName()); 175 intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); 176 intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, mFromSettingsSummary); 177 if (mUserId != UserHandle.USER_NULL) { 178 intent.putExtra(Intent.EXTRA_USER_ID, mUserId); 179 } 180 return intent; 181 } 182 launchConfirmLock(int titleResId, long challenge)183 protected void launchConfirmLock(int titleResId, long challenge) { 184 ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this); 185 boolean launchedConfirmationActivity; 186 if (mUserId == UserHandle.USER_NULL) { 187 launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST, 188 getString(titleResId), 189 null, null, challenge, true /* foregroundOnly */); 190 } else { 191 launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST, 192 getString(titleResId), 193 null, null, challenge, mUserId, true /* foregroundOnly */); 194 } 195 if (!launchedConfirmationActivity) { 196 // This shouldn't happen, as we should only end up at this step if a lock thingy is 197 // already set. 198 finish(); 199 } else { 200 mLaunchedConfirmLock = true; 201 } 202 } 203 } 204