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.fingerprint; 18 19 import android.content.Intent; 20 import android.hardware.fingerprint.FingerprintManager; 21 import android.os.Bundle; 22 import android.os.UserHandle; 23 import android.support.annotation.Nullable; 24 import android.view.View; 25 import android.widget.Button; 26 27 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 28 import com.android.settings.R; 29 import com.android.settings.Utils; 30 import com.android.settings.fingerprint.FingerprintEnrollSidecar.Listener; 31 import com.android.settings.password.ChooseLockSettingsHelper; 32 33 /** 34 * Activity explaining the fingerprint sensor location for fingerprint enrollment. 35 */ 36 public class FingerprintEnrollFindSensor extends FingerprintEnrollBase { 37 38 private static final int CONFIRM_REQUEST = 1; 39 private static final int ENROLLING = 2; 40 public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock"; 41 42 @Nullable 43 private FingerprintFindSensorAnimation mAnimation; 44 private boolean mLaunchedConfirmLock; 45 private FingerprintEnrollSidecar mSidecar; 46 private boolean mNextClicked; 47 48 @Override 49 protected void onCreate(Bundle savedInstanceState) { 50 super.onCreate(savedInstanceState); 51 setContentView(getContentView()); 52 Button skipButton = findViewById(R.id.skip_button); 53 skipButton.setOnClickListener(this); 54 55 setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title); 56 if (savedInstanceState != null) { 57 mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM); 58 mToken = savedInstanceState.getByteArray( 59 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); 60 } 61 if (mToken == null && !mLaunchedConfirmLock) { 62 launchConfirmLock(); 63 } else if (mToken != null) { 64 startLookingForFingerprint(); // already confirmed, so start looking for fingerprint 65 } 66 View animationView = findViewById(R.id.fingerprint_sensor_location_animation); 67 if (animationView instanceof FingerprintFindSensorAnimation) { 68 mAnimation = (FingerprintFindSensorAnimation) animationView; 69 } else { 70 mAnimation = null; 71 } 72 } 73 74 protected int getContentView() { 75 return R.layout.fingerprint_enroll_find_sensor; 76 } 77 78 @Override 79 protected void onStart() { 80 super.onStart(); 81 if (mAnimation != null) { 82 mAnimation.startAnimation(); 83 } 84 } 85 86 private void startLookingForFingerprint() { 87 mSidecar = (FingerprintEnrollSidecar) getFragmentManager().findFragmentByTag( 88 FingerprintEnrollEnrolling.TAG_SIDECAR); 89 if (mSidecar == null) { 90 mSidecar = new FingerprintEnrollSidecar(); 91 getFragmentManager().beginTransaction() 92 .add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR).commit(); 93 } 94 mSidecar.setListener(new Listener() { 95 @Override 96 public void onEnrollmentProgressChange(int steps, int remaining) { 97 mNextClicked = true; 98 proceedToEnrolling(true /* cancelEnrollment */); 99 } 100 101 @Override 102 public void onEnrollmentHelp(CharSequence helpString) { 103 } 104 105 @Override 106 public void onEnrollmentError(int errMsgId, CharSequence errString) { 107 if (mNextClicked && errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { 108 mNextClicked = false; 109 proceedToEnrolling(false /* cancelEnrollment */); 110 } 111 } 112 }); 113 } 114 115 @Override 116 protected void onStop() { 117 super.onStop(); 118 if (mAnimation != null) { 119 mAnimation.pauseAnimation(); 120 } 121 } 122 123 @Override 124 protected void onDestroy() { 125 super.onDestroy(); 126 if (mAnimation != null) { 127 mAnimation.stopAnimation(); 128 } 129 } 130 131 @Override 132 public void onSaveInstanceState(Bundle outState) { 133 super.onSaveInstanceState(outState); 134 outState.putBoolean(EXTRA_KEY_LAUNCHED_CONFIRM, mLaunchedConfirmLock); 135 outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); 136 } 137 138 @Override 139 public void onClick(View v) { 140 switch (v.getId()) { 141 case R.id.skip_button: 142 onSkipButtonClick(); 143 break; 144 default: 145 super.onClick(v); 146 } 147 } 148 149 protected void onSkipButtonClick() { 150 setResult(RESULT_SKIP); 151 finish(); 152 } 153 154 private void proceedToEnrolling(boolean cancelEnrollment) { 155 if (mSidecar != null) { 156 if (cancelEnrollment) { 157 if (mSidecar.cancelEnrollment()) { 158 // Enrollment cancel requested. When the cancellation is successful, 159 // onEnrollmentError will be called with FINGERPRINT_ERROR_CANCELED, calling 160 // this again. 161 return; 162 } 163 } 164 getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss(); 165 mSidecar = null; 166 startActivityForResult(getEnrollingIntent(), ENROLLING); 167 } 168 } 169 170 @Override 171 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 172 if (requestCode == CONFIRM_REQUEST) { 173 if (resultCode == RESULT_OK) { 174 mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN); 175 overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out); 176 getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken); 177 startLookingForFingerprint(); 178 } else { 179 finish(); 180 } 181 } else if (requestCode == ENROLLING) { 182 if (resultCode == RESULT_FINISHED) { 183 setResult(RESULT_FINISHED); 184 finish(); 185 } else if (resultCode == RESULT_SKIP) { 186 setResult(RESULT_SKIP); 187 finish(); 188 } else if (resultCode == RESULT_TIMEOUT) { 189 setResult(RESULT_TIMEOUT); 190 finish(); 191 } else { 192 FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this); 193 int enrolled = fpm.getEnrolledFingerprints().size(); 194 int max = getResources().getInteger( 195 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 196 if (enrolled >= max) { 197 finish(); 198 } else { 199 // We came back from enrolling but it wasn't completed, start again. 200 startLookingForFingerprint(); 201 } 202 } 203 } else { 204 super.onActivityResult(requestCode, resultCode, data); 205 } 206 } 207 208 private void launchConfirmLock() { 209 long challenge = Utils.getFingerprintManagerOrNull(this).preEnroll(); 210 ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this); 211 boolean launchedConfirmationActivity = false; 212 if (mUserId == UserHandle.USER_NULL) { 213 launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST, 214 getString(R.string.security_settings_fingerprint_preference_title), 215 null, null, challenge); 216 } else { 217 launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST, 218 getString(R.string.security_settings_fingerprint_preference_title), 219 null, null, challenge, mUserId); 220 } 221 if (!launchedConfirmationActivity) { 222 // This shouldn't happen, as we should only end up at this step if a lock thingy is 223 // already set. 224 finish(); 225 } else { 226 mLaunchedConfirmLock = true; 227 } 228 } 229 230 @Override 231 public int getMetricsCategory() { 232 return MetricsEvent.FINGERPRINT_FIND_SENSOR; 233 } 234 } 235