The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2008 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 | |
Maurice Lam | 2eb170c | 2017-04-28 16:18:47 -0700 | [diff] [blame] | 17 | package com.android.settings.password; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 18 | |
Jason Monk | 39b4674 | 2015-09-10 15:52:51 -0400 | [diff] [blame] | 19 | import android.app.Activity; |
Fan Zhang | 31b2100 | 2019-01-16 13:49:47 -0800 | [diff] [blame] | 20 | import android.app.settings.SettingsEnums; |
Jason Monk | 39b4674 | 2015-09-10 15:52:51 -0400 | [diff] [blame] | 21 | import android.content.Intent; |
| 22 | import android.os.AsyncTask; |
| 23 | import android.os.Bundle; |
| 24 | import android.os.CountDownTimer; |
| 25 | import android.os.SystemClock; |
Clara Bayarri | 34ec5f9 | 2016-01-22 14:59:24 +0000 | [diff] [blame] | 26 | import android.os.UserManager; |
Jason Monk | 39b4674 | 2015-09-10 15:52:51 -0400 | [diff] [blame] | 27 | import android.os.storage.StorageManager; |
| 28 | import android.view.LayoutInflater; |
| 29 | import android.view.View; |
| 30 | import android.view.ViewGroup; |
| 31 | import android.view.animation.AnimationUtils; |
| 32 | import android.view.animation.Interpolator; |
| 33 | import android.widget.TextView; |
| 34 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 35 | import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient; |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 36 | import com.android.internal.widget.LockPatternChecker; |
Jason Monk | 39b4674 | 2015-09-10 15:52:51 -0400 | [diff] [blame] | 37 | import com.android.internal.widget.LockPatternUtils; |
| 38 | import com.android.internal.widget.LockPatternView; |
Jim Miller | 56544d0 | 2009-09-29 14:16:53 -0700 | [diff] [blame] | 39 | import com.android.internal.widget.LockPatternView.Cell; |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 40 | import com.android.internal.widget.LockscreenCredential; |
Maurice Lam | 2eb170c | 2017-04-28 16:18:47 -0700 | [diff] [blame] | 41 | import com.android.settings.R; |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 42 | import com.android.settingslib.animation.AppearAnimationCreator; |
| 43 | import com.android.settingslib.animation.AppearAnimationUtils; |
| 44 | import com.android.settingslib.animation.DisappearAnimationUtils; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 45 | |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 46 | import java.util.ArrayList; |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 47 | import java.util.Collections; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 48 | import java.util.List; |
| 49 | |
| 50 | /** |
| 51 | * Launch this when you want the user to confirm their lock pattern. |
| 52 | * |
| 53 | * Sets an activity result of {@link Activity#RESULT_OK} when the user |
| 54 | * successfully confirmed their pattern. |
| 55 | */ |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 56 | public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity { |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 57 | |
Paul Lawrence | 2044404 | 2014-07-07 13:10:16 -0700 | [diff] [blame] | 58 | public static class InternalActivity extends ConfirmLockPattern { |
| 59 | } |
| 60 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 61 | private enum Stage { |
| 62 | NeedToUnlock, |
| 63 | NeedToUnlockWrong, |
| 64 | LockedOut |
| 65 | } |
| 66 | |
| 67 | @Override |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 68 | public Intent getIntent() { |
| 69 | Intent modIntent = new Intent(super.getIntent()); |
| 70 | modIntent.putExtra(EXTRA_SHOW_FRAGMENT, ConfirmLockPatternFragment.class.getName()); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 71 | return modIntent; |
| 72 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 73 | |
Amith Yamasani | a677ee2 | 2013-07-26 13:38:41 -0700 | [diff] [blame] | 74 | @Override |
| 75 | protected boolean isValidFragment(String fragmentName) { |
| 76 | if (ConfirmLockPatternFragment.class.getName().equals(fragmentName)) return true; |
| 77 | return false; |
| 78 | } |
| 79 | |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 80 | public static class ConfirmLockPatternFragment extends ConfirmDeviceCredentialBaseFragment |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 81 | implements AppearAnimationCreator<Object>, CredentialCheckResultTracker.Listener { |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 82 | |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 83 | private static final String FRAGMENT_TAG_CHECK_LOCK_RESULT = "check_lock_result"; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 84 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 85 | private LockPatternView mLockPatternView; |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 86 | private AsyncTask<?, ?, ?> mPendingLockCheck; |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 87 | private CredentialCheckResultTracker mCredentialCheckResultTracker; |
| 88 | private boolean mDisappearing = false; |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 89 | private CountDownTimer mCountdownTimer; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 90 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 91 | private TextView mHeaderTextView; |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 92 | private TextView mDetailsTextView; |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 93 | |
| 94 | // caller-supplied text for various prompts |
| 95 | private CharSequence mHeaderText; |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 96 | private CharSequence mDetailsText; |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 97 | |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 98 | private AppearAnimationUtils mAppearAnimationUtils; |
| 99 | private DisappearAnimationUtils mDisappearAnimationUtils; |
| 100 | |
Alex Johnston | 7868acf | 2019-12-09 12:52:14 +0000 | [diff] [blame] | 101 | private boolean mIsManagedProfile; |
| 102 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 103 | // required constructor for fragments |
| 104 | public ConfirmLockPatternFragment() { |
| 105 | |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 106 | } |
| 107 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 108 | @Override |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 109 | public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| 110 | Bundle savedInstanceState) { |
Maurice Lam | daaf8f8 | 2017-03-10 15:31:30 -0800 | [diff] [blame] | 111 | ConfirmLockPattern activity = (ConfirmLockPattern) getActivity(); |
| 112 | View view = inflater.inflate( |
Maurice Lam | 3e3b8a9 | 2018-03-21 18:21:04 -0700 | [diff] [blame] | 113 | activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.NORMAL |
| 114 | ? R.layout.confirm_lock_pattern_normal |
Maurice Lam | daaf8f8 | 2017-03-10 15:31:30 -0800 | [diff] [blame] | 115 | : R.layout.confirm_lock_pattern, |
| 116 | container, |
| 117 | false); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 118 | mHeaderTextView = (TextView) view.findViewById(R.id.headerText); |
| 119 | mLockPatternView = (LockPatternView) view.findViewById(R.id.lockPattern); |
pastychang | fa68ec4 | 2019-04-12 16:22:17 +0800 | [diff] [blame] | 120 | mDetailsTextView = (TextView) view.findViewById(R.id.sud_layout_description); |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 121 | mErrorTextView = (TextView) view.findViewById(R.id.errorText); |
Alex Johnston | 7868acf | 2019-12-09 12:52:14 +0000 | [diff] [blame] | 122 | |
| 123 | mIsManagedProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 124 | |
| 125 | // make it so unhandled touch events within the unlock screen go to the |
| 126 | // lock pattern view. |
| 127 | final LinearLayoutWithDefaultTouchRecepient topLayout |
| 128 | = (LinearLayoutWithDefaultTouchRecepient) view.findViewById(R.id.topLayout); |
| 129 | topLayout.setDefaultTouchRecepient(mLockPatternView); |
| 130 | |
| 131 | Intent intent = getActivity().getIntent(); |
| 132 | if (intent != null) { |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 133 | mHeaderText = intent.getCharSequenceExtra( |
| 134 | ConfirmDeviceCredentialBaseFragment.HEADER_TEXT); |
| 135 | mDetailsText = intent.getCharSequenceExtra( |
| 136 | ConfirmDeviceCredentialBaseFragment.DETAILS_TEXT); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 137 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 138 | |
Julia Reynolds | 36a38c9 | 2015-07-28 09:44:59 -0400 | [diff] [blame] | 139 | mLockPatternView.setTactileFeedbackEnabled( |
| 140 | mLockPatternUtils.isTactileFeedbackEnabled()); |
| 141 | mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled( |
Andres Morales | b56324b | 2015-08-11 16:12:50 -0700 | [diff] [blame] | 142 | mEffectiveUserId)); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 143 | mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener); |
Konstantin Lopyrev | 9aaf40d | 2010-05-13 16:33:13 -0700 | [diff] [blame] | 144 | updateStage(Stage.NeedToUnlock); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 145 | |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 146 | if (savedInstanceState == null) { |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 147 | // on first launch, if no lock pattern is set, then finish with |
| 148 | // success (don't want user to get stuck confirming something that |
| 149 | // doesn't exist). |
Adrian Roos | 5a9a3cd | 2017-03-30 18:02:25 -0700 | [diff] [blame] | 150 | // Don't do this check for FRP though, because the pattern is not stored |
| 151 | // in a way that isLockPatternEnabled is aware of for that case. |
| 152 | // TODO(roosa): This block should no longer be needed since we removed the |
| 153 | // ability to disable the pattern in L. Remove this block after |
| 154 | // ensuring it's safe to do so. (Note that ConfirmLockPassword |
| 155 | // doesn't have this). |
| 156 | if (!mFrp && !mLockPatternUtils.isLockPatternEnabled(mEffectiveUserId)) { |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 157 | getActivity().setResult(Activity.RESULT_OK); |
| 158 | getActivity().finish(); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 159 | } |
| 160 | } |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 161 | mAppearAnimationUtils = new AppearAnimationUtils(getContext(), |
| 162 | AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 2f /* translationScale */, |
| 163 | 1.3f /* delayScale */, AnimationUtils.loadInterpolator( |
| 164 | getContext(), android.R.interpolator.linear_out_slow_in)); |
| 165 | mDisappearAnimationUtils = new DisappearAnimationUtils(getContext(), |
| 166 | 125, 4f /* translationScale */, |
| 167 | 0.3f /* delayScale */, AnimationUtils.loadInterpolator( |
| 168 | getContext(), android.R.interpolator.fast_out_linear_in), |
| 169 | new AppearAnimationUtils.RowTranslationScaler() { |
| 170 | @Override |
| 171 | public float getRowTranslationScale(int row, int numRows) { |
| 172 | return (float)(numRows - row) / numRows; |
| 173 | } |
| 174 | }); |
Julia Reynolds | ce25af4 | 2015-07-08 16:56:31 -0400 | [diff] [blame] | 175 | setAccessibilityTitle(mHeaderTextView.getText()); |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 176 | |
| 177 | mCredentialCheckResultTracker = (CredentialCheckResultTracker) getFragmentManager() |
| 178 | .findFragmentByTag(FRAGMENT_TAG_CHECK_LOCK_RESULT); |
| 179 | if (mCredentialCheckResultTracker == null) { |
| 180 | mCredentialCheckResultTracker = new CredentialCheckResultTracker(); |
| 181 | getFragmentManager().beginTransaction().add(mCredentialCheckResultTracker, |
| 182 | FRAGMENT_TAG_CHECK_LOCK_RESULT).commit(); |
| 183 | } |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 184 | return view; |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 185 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 186 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 187 | @Override |
| 188 | public void onSaveInstanceState(Bundle outState) { |
| 189 | // deliberately not calling super since we are managing this in full |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 190 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 191 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 192 | @Override |
| 193 | public void onPause() { |
| 194 | super.onPause(); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 195 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 196 | if (mCountdownTimer != null) { |
| 197 | mCountdownTimer.cancel(); |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 198 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 199 | mCredentialCheckResultTracker.setListener(null); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 200 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 201 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 202 | @Override |
Fan Zhang | 6507613 | 2016-08-08 10:25:13 -0700 | [diff] [blame] | 203 | public int getMetricsCategory() { |
Fan Zhang | 31b2100 | 2019-01-16 13:49:47 -0800 | [diff] [blame] | 204 | return SettingsEnums.CONFIRM_LOCK_PATTERN; |
Chris Wren | 8a963ba | 2015-03-20 10:29:14 -0400 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | @Override |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 208 | public void onResume() { |
| 209 | super.onResume(); |
| 210 | |
| 211 | // if the user is currently locked out, enforce it. |
Andres Morales | 7bdffd8 | 2015-08-04 16:55:00 -0700 | [diff] [blame] | 212 | long deadline = mLockPatternUtils.getLockoutAttemptDeadline(mEffectiveUserId); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 213 | if (deadline != 0) { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 214 | mCredentialCheckResultTracker.clearResult(); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 215 | handleAttemptLockout(deadline); |
| 216 | } else if (!mLockPatternView.isEnabled()) { |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 217 | // The deadline has passed, but the timer was cancelled. Or the pending lock |
| 218 | // check was cancelled. Need to clean up. |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 219 | updateStage(Stage.NeedToUnlock); |
| 220 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 221 | mCredentialCheckResultTracker.setListener(this); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 222 | } |
| 223 | |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 224 | @Override |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 225 | protected void onShowError() { |
| 226 | } |
| 227 | |
| 228 | @Override |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 229 | public void prepareEnterAnimation() { |
| 230 | super.prepareEnterAnimation(); |
| 231 | mHeaderTextView.setAlpha(0f); |
| 232 | mCancelButton.setAlpha(0f); |
| 233 | mLockPatternView.setAlpha(0f); |
| 234 | mDetailsTextView.setAlpha(0f); |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 235 | } |
| 236 | |
Tony Mak | 7655be0 | 2016-04-21 10:27:43 +0100 | [diff] [blame] | 237 | private int getDefaultDetails() { |
Adrian Roos | 6600dde | 2017-07-23 14:18:16 +0200 | [diff] [blame] | 238 | if (mFrp) { |
| 239 | return R.string.lockpassword_confirm_your_pattern_details_frp; |
| 240 | } |
Charles He | 4c96d9b | 2017-07-04 11:50:03 +0100 | [diff] [blame] | 241 | final boolean isStrongAuthRequired = isStrongAuthRequired(); |
Alex Johnston | 28c6b57 | 2020-01-28 17:49:33 +0000 | [diff] [blame] | 242 | if (mIsManagedProfile) { |
Charles He | 4c96d9b | 2017-07-04 11:50:03 +0100 | [diff] [blame] | 243 | return isStrongAuthRequired |
| 244 | ? R.string.lockpassword_strong_auth_required_work_pattern |
| 245 | : R.string.lockpassword_confirm_your_pattern_generic_profile; |
Tony Mak | 7655be0 | 2016-04-21 10:27:43 +0100 | [diff] [blame] | 246 | } else { |
Charles He | 4c96d9b | 2017-07-04 11:50:03 +0100 | [diff] [blame] | 247 | return isStrongAuthRequired |
| 248 | ? R.string.lockpassword_strong_auth_required_device_pattern |
| 249 | : R.string.lockpassword_confirm_your_pattern_generic; |
Tony Mak | 7655be0 | 2016-04-21 10:27:43 +0100 | [diff] [blame] | 250 | } |
| 251 | } |
| 252 | |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 253 | private Object[][] getActiveViews() { |
| 254 | ArrayList<ArrayList<Object>> result = new ArrayList<>(); |
| 255 | result.add(new ArrayList<Object>(Collections.singletonList(mHeaderTextView))); |
| 256 | result.add(new ArrayList<Object>(Collections.singletonList(mDetailsTextView))); |
| 257 | if (mCancelButton.getVisibility() == View.VISIBLE) { |
| 258 | result.add(new ArrayList<Object>(Collections.singletonList(mCancelButton))); |
| 259 | } |
| 260 | LockPatternView.CellState[][] cellStates = mLockPatternView.getCellStates(); |
| 261 | for (int i = 0; i < cellStates.length; i++) { |
| 262 | ArrayList<Object> row = new ArrayList<>(); |
| 263 | for (int j = 0; j < cellStates[i].length; j++) { |
| 264 | row.add(cellStates[i][j]); |
| 265 | } |
| 266 | result.add(row); |
| 267 | } |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 268 | Object[][] resultArr = new Object[result.size()][cellStates[0].length]; |
| 269 | for (int i = 0; i < result.size(); i++) { |
| 270 | ArrayList<Object> row = result.get(i); |
| 271 | for (int j = 0; j < row.size(); j++) { |
| 272 | resultArr[i][j] = row.get(j); |
| 273 | } |
| 274 | } |
| 275 | return resultArr; |
| 276 | } |
| 277 | |
| 278 | @Override |
| 279 | public void startEnterAnimation() { |
| 280 | super.startEnterAnimation(); |
| 281 | mLockPatternView.setAlpha(1f); |
| 282 | mAppearAnimationUtils.startAnimation2d(getActiveViews(), null, this); |
| 283 | } |
| 284 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 285 | private void updateStage(Stage stage) { |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 286 | switch (stage) { |
| 287 | case NeedToUnlock: |
| 288 | if (mHeaderText != null) { |
| 289 | mHeaderTextView.setText(mHeaderText); |
| 290 | } else { |
Adrian Roos | 6600dde | 2017-07-23 14:18:16 +0200 | [diff] [blame] | 291 | mHeaderTextView.setText(getDefaultHeader()); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 292 | } |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 293 | if (mDetailsText != null) { |
| 294 | mDetailsTextView.setText(mDetailsText); |
Clara Bayarri | 34ec5f9 | 2016-01-22 14:59:24 +0000 | [diff] [blame] | 295 | } else { |
Tony Mak | 7655be0 | 2016-04-21 10:27:43 +0100 | [diff] [blame] | 296 | mDetailsTextView.setText(getDefaultDetails()); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 297 | } |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 298 | mErrorTextView.setText(""); |
Charles He | 641c9fc | 2017-04-26 18:45:48 +0100 | [diff] [blame] | 299 | updateErrorMessage( |
| 300 | mLockPatternUtils.getCurrentFailedPasswordAttempts(mEffectiveUserId)); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 301 | |
| 302 | mLockPatternView.setEnabled(true); |
| 303 | mLockPatternView.enableInput(); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 304 | mLockPatternView.clearPattern(); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 305 | break; |
| 306 | case NeedToUnlockWrong: |
Charles He | caf9510 | 2017-08-18 17:35:27 +0100 | [diff] [blame] | 307 | showError(R.string.lockpattern_need_to_unlock_wrong, |
| 308 | CLEAR_WRONG_ATTEMPT_TIMEOUT_MS); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 309 | |
| 310 | mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong); |
| 311 | mLockPatternView.setEnabled(true); |
| 312 | mLockPatternView.enableInput(); |
| 313 | break; |
| 314 | case LockedOut: |
| 315 | mLockPatternView.clearPattern(); |
| 316 | // enabled = false means: disable input, and have the |
| 317 | // appearance of being disabled. |
| 318 | mLockPatternView.setEnabled(false); // appearance of being disabled |
| 319 | break; |
| 320 | } |
alanv | eef72c3 | 2012-10-03 17:10:50 -0700 | [diff] [blame] | 321 | |
| 322 | // Always announce the header for accessibility. This is a no-op |
| 323 | // when accessibility is disabled. |
| 324 | mHeaderTextView.announceForAccessibility(mHeaderTextView.getText()); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 325 | } |
| 326 | |
Adrian Roos | 6600dde | 2017-07-23 14:18:16 +0200 | [diff] [blame] | 327 | private int getDefaultHeader() { |
Alex Johnston | 7868acf | 2019-12-09 12:52:14 +0000 | [diff] [blame] | 328 | if (mFrp) return R.string.lockpassword_confirm_your_pattern_header_frp; |
| 329 | return mIsManagedProfile |
| 330 | ? R.string.lockpassword_confirm_your_work_pattern_header |
Adrian Roos | 6600dde | 2017-07-23 14:18:16 +0200 | [diff] [blame] | 331 | : R.string.lockpassword_confirm_your_pattern_header; |
| 332 | } |
| 333 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 334 | private Runnable mClearPatternRunnable = new Runnable() { |
| 335 | public void run() { |
| 336 | mLockPatternView.clearPattern(); |
| 337 | } |
| 338 | }; |
| 339 | |
| 340 | // clear the wrong pattern unless they have started a new one |
| 341 | // already |
| 342 | private void postClearPatternRunnable() { |
| 343 | mLockPatternView.removeCallbacks(mClearPatternRunnable); |
Charles He | caf9510 | 2017-08-18 17:35:27 +0100 | [diff] [blame] | 344 | mLockPatternView.postDelayed(mClearPatternRunnable, CLEAR_WRONG_ATTEMPT_TIMEOUT_MS); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 345 | } |
| 346 | |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 347 | @Override |
Andres Morales | 59f5976 | 2015-04-16 16:30:31 -0700 | [diff] [blame] | 348 | protected void authenticationSucceeded() { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 349 | mCredentialCheckResultTracker.setResult(true, new Intent(), 0, mEffectiveUserId); |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | private void startDisappearAnimation(final Intent intent) { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 353 | if (mDisappearing) { |
| 354 | return; |
| 355 | } |
| 356 | mDisappearing = true; |
| 357 | |
Maurice Lam | daaf8f8 | 2017-03-10 15:31:30 -0800 | [diff] [blame] | 358 | final ConfirmLockPattern activity = (ConfirmLockPattern) getActivity(); |
| 359 | // Bail if there is no active activity. |
| 360 | if (activity == null || activity.isFinishing()) { |
| 361 | return; |
| 362 | } |
| 363 | if (activity.getConfirmCredentialTheme() == ConfirmCredentialTheme.DARK) { |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 364 | mLockPatternView.clearPattern(); |
| 365 | mDisappearAnimationUtils.startAnimation2d(getActiveViews(), |
Maurice Lam | daaf8f8 | 2017-03-10 15:31:30 -0800 | [diff] [blame] | 366 | () -> { |
| 367 | activity.setResult(RESULT_OK, intent); |
| 368 | activity.finish(); |
| 369 | activity.overridePendingTransition( |
| 370 | R.anim.confirm_credential_close_enter, |
| 371 | R.anim.confirm_credential_close_exit); |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 372 | }, this); |
| 373 | } else { |
Maurice Lam | daaf8f8 | 2017-03-10 15:31:30 -0800 | [diff] [blame] | 374 | activity.setResult(RESULT_OK, intent); |
| 375 | activity.finish(); |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 376 | } |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 377 | } |
| 378 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 379 | /** |
| 380 | * The pattern listener that responds according to a user confirming |
| 381 | * an existing lock pattern. |
| 382 | */ |
| 383 | private LockPatternView.OnPatternListener mConfirmExistingLockPatternListener |
| 384 | = new LockPatternView.OnPatternListener() { |
| 385 | |
| 386 | public void onPatternStart() { |
| 387 | mLockPatternView.removeCallbacks(mClearPatternRunnable); |
| 388 | } |
| 389 | |
| 390 | public void onPatternCleared() { |
| 391 | mLockPatternView.removeCallbacks(mClearPatternRunnable); |
| 392 | } |
| 393 | |
| 394 | public void onPatternCellAdded(List<Cell> pattern) { |
| 395 | |
| 396 | } |
| 397 | |
| 398 | public void onPatternDetected(List<LockPatternView.Cell> pattern) { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 399 | if (mPendingLockCheck != null || mDisappearing) { |
| 400 | return; |
Andres Morales | 6609b0c | 2015-04-12 15:38:25 -0700 | [diff] [blame] | 401 | } |
| 402 | |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 403 | mLockPatternView.setEnabled(false); |
| 404 | |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 405 | final boolean verifyChallenge = getActivity().getIntent().getBooleanExtra( |
| 406 | ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false); |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 407 | final LockscreenCredential credential = LockscreenCredential.createPattern(pattern); |
| 408 | //TODO: how to sanitize this? |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 409 | Intent intent = new Intent(); |
| 410 | if (verifyChallenge) { |
| 411 | if (isInternalActivity()) { |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 412 | startVerifyPattern(credential, intent); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 413 | return; |
| 414 | } |
| 415 | } else { |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 416 | startCheckPattern(credential, intent); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 417 | return; |
| 418 | } |
| 419 | |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 420 | mCredentialCheckResultTracker.setResult(false, intent, 0, mEffectiveUserId); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 421 | } |
| 422 | |
| 423 | private boolean isInternalActivity() { |
| 424 | return getActivity() instanceof ConfirmLockPattern.InternalActivity; |
| 425 | } |
| 426 | |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 427 | private void startVerifyPattern(final LockscreenCredential pattern, |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 428 | final Intent intent) { |
Andres Morales | 7bdffd8 | 2015-08-04 16:55:00 -0700 | [diff] [blame] | 429 | final int localEffectiveUserId = mEffectiveUserId; |
Ricky Wai | 996d0df | 2016-04-05 16:33:47 +0100 | [diff] [blame] | 430 | final int localUserId = mUserId; |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 431 | long challenge = getActivity().getIntent().getLongExtra( |
| 432 | ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0); |
Ricky Wai | 996d0df | 2016-04-05 16:33:47 +0100 | [diff] [blame] | 433 | final LockPatternChecker.OnVerifyCallback onVerifyCallback = |
| 434 | new LockPatternChecker.OnVerifyCallback() { |
| 435 | @Override |
| 436 | public void onVerified(byte[] token, int timeoutMs) { |
| 437 | mPendingLockCheck = null; |
| 438 | boolean matched = false; |
| 439 | if (token != null) { |
| 440 | matched = true; |
Victor Chang | 5e0a46b | 2016-05-13 17:06:59 +0100 | [diff] [blame] | 441 | if (mReturnCredentials) { |
| 442 | intent.putExtra( |
| 443 | ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, |
| 444 | token); |
| 445 | } |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 446 | } |
Ricky Wai | 996d0df | 2016-04-05 16:33:47 +0100 | [diff] [blame] | 447 | mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, |
| 448 | localEffectiveUserId); |
| 449 | } |
| 450 | }; |
| 451 | mPendingLockCheck = (localEffectiveUserId == localUserId) |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 452 | ? LockPatternChecker.verifyCredential( |
Ricky Wai | 996d0df | 2016-04-05 16:33:47 +0100 | [diff] [blame] | 453 | mLockPatternUtils, pattern, challenge, localUserId, |
| 454 | onVerifyCallback) |
| 455 | : LockPatternChecker.verifyTiedProfileChallenge( |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 456 | mLockPatternUtils, pattern, |
| 457 | challenge, localUserId, onVerifyCallback); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 458 | } |
| 459 | |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 460 | private void startCheckPattern(final LockscreenCredential pattern, |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 461 | final Intent intent) { |
Andres Morales | 864d13e | 2015-05-27 13:04:38 -0700 | [diff] [blame] | 462 | if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) { |
Tony Mak | 818312d | 2016-07-20 09:55:25 +0100 | [diff] [blame] | 463 | // Pattern size is less than the minimum, do not count it as an fail attempt. |
| 464 | onPatternChecked(false, intent, 0, mEffectiveUserId, false /* newResult */); |
Andres Morales | 91e6c49 | 2015-05-15 15:20:33 -0700 | [diff] [blame] | 465 | return; |
| 466 | } |
| 467 | |
Andres Morales | 7bdffd8 | 2015-08-04 16:55:00 -0700 | [diff] [blame] | 468 | final int localEffectiveUserId = mEffectiveUserId; |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 469 | mPendingLockCheck = LockPatternChecker.checkCredential( |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 470 | mLockPatternUtils, |
| 471 | pattern, |
Andres Morales | 7bdffd8 | 2015-08-04 16:55:00 -0700 | [diff] [blame] | 472 | localEffectiveUserId, |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 473 | new LockPatternChecker.OnCheckCallback() { |
| 474 | @Override |
Andres Morales | 91e6c49 | 2015-05-15 15:20:33 -0700 | [diff] [blame] | 475 | public void onChecked(boolean matched, int timeoutMs) { |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 476 | mPendingLockCheck = null; |
Victor Chang | 5e0a46b | 2016-05-13 17:06:59 +0100 | [diff] [blame] | 477 | if (matched && isInternalActivity() && mReturnCredentials) { |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 478 | intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, |
| 479 | StorageManager.CRYPT_TYPE_PATTERN); |
| 480 | intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, |
Rubin Xu | 010116a | 2019-09-11 17:36:37 +0100 | [diff] [blame] | 481 | pattern); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 482 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 483 | mCredentialCheckResultTracker.setResult(matched, intent, timeoutMs, |
Andres Morales | 7bdffd8 | 2015-08-04 16:55:00 -0700 | [diff] [blame] | 484 | localEffectiveUserId); |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 485 | } |
| 486 | }); |
| 487 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 488 | }; |
Xiyuan Xia | bf9ac6b | 2015-05-05 16:04:00 -0700 | [diff] [blame] | 489 | |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 490 | private void onPatternChecked(boolean matched, Intent intent, int timeoutMs, |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 491 | int effectiveUserId, boolean newResult) { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 492 | mLockPatternView.setEnabled(true); |
| 493 | if (matched) { |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 494 | if (newResult) { |
Kevin Chyn | 127da9c | 2018-11-09 16:13:53 -0800 | [diff] [blame] | 495 | ConfirmDeviceCredentialUtils.reportSuccessfulAttempt(mLockPatternUtils, |
| 496 | mUserManager, mEffectiveUserId); |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 497 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 498 | startDisappearAnimation(intent); |
Kevin Chyn | 127da9c | 2018-11-09 16:13:53 -0800 | [diff] [blame] | 499 | ConfirmDeviceCredentialUtils.checkForPendingIntent(getActivity()); |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 500 | } else { |
| 501 | if (timeoutMs > 0) { |
Ricky Wai | 9aa434c | 2016-06-27 11:10:09 +0100 | [diff] [blame] | 502 | refreshLockScreen(); |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 503 | long deadline = mLockPatternUtils.setLockoutAttemptDeadline( |
| 504 | effectiveUserId, timeoutMs); |
| 505 | handleAttemptLockout(deadline); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 506 | } else { |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 507 | updateStage(Stage.NeedToUnlockWrong); |
| 508 | postClearPatternRunnable(); |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 509 | } |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 510 | if (newResult) { |
| 511 | reportFailedAttempt(); |
| 512 | } |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 513 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 514 | } |
| 515 | |
| 516 | @Override |
| 517 | public void onCredentialChecked(boolean matched, Intent intent, int timeoutMs, |
Clara Bayarri | 9d357ea | 2016-01-28 17:50:53 +0000 | [diff] [blame] | 518 | int effectiveUserId, boolean newResult) { |
| 519 | onPatternChecked(matched, intent, timeoutMs, effectiveUserId, newResult); |
| 520 | } |
| 521 | |
| 522 | @Override |
Charles He | 641c9fc | 2017-04-26 18:45:48 +0100 | [diff] [blame] | 523 | protected int getLastTryErrorMessage(int userType) { |
| 524 | switch (userType) { |
| 525 | case USER_TYPE_PRIMARY: |
| 526 | return R.string.lock_last_pattern_attempt_before_wipe_device; |
| 527 | case USER_TYPE_MANAGED_PROFILE: |
| 528 | return R.string.lock_last_pattern_attempt_before_wipe_profile; |
| 529 | case USER_TYPE_SECONDARY: |
| 530 | return R.string.lock_last_pattern_attempt_before_wipe_user; |
| 531 | default: |
| 532 | throw new IllegalArgumentException("Unrecognized user type:" + userType); |
| 533 | } |
Xiyuan Xia | 00b17fa | 2015-08-31 11:59:46 -0700 | [diff] [blame] | 534 | } |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 535 | |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 536 | private void handleAttemptLockout(long elapsedRealtimeDeadline) { |
| 537 | updateStage(Stage.LockedOut); |
| 538 | long elapsedRealtime = SystemClock.elapsedRealtime(); |
| 539 | mCountdownTimer = new CountDownTimer( |
| 540 | elapsedRealtimeDeadline - elapsedRealtime, |
| 541 | LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) { |
| 542 | |
| 543 | @Override |
| 544 | public void onTick(long millisUntilFinished) { |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 545 | final int secondsCountdown = (int) (millisUntilFinished / 1000); |
Xiyuan Xia | 4458fd6 | 2015-06-02 15:21:51 -0700 | [diff] [blame] | 546 | mErrorTextView.setText(getString( |
Jorim Jaggi | 8a09b61 | 2015-04-06 17:47:18 -0700 | [diff] [blame] | 547 | R.string.lockpattern_too_many_failed_confirmation_attempts, |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 548 | secondsCountdown)); |
| 549 | } |
| 550 | |
| 551 | @Override |
| 552 | public void onFinish() { |
Jim Miller | 17e9e19 | 2010-12-07 20:41:41 -0800 | [diff] [blame] | 553 | updateStage(Stage.NeedToUnlock); |
| 554 | } |
| 555 | }.start(); |
| 556 | } |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 557 | |
| 558 | @Override |
| 559 | public void createAnimation(Object obj, long delay, |
| 560 | long duration, float translationY, final boolean appearing, |
| 561 | Interpolator interpolator, |
| 562 | final Runnable finishListener) { |
| 563 | if (obj instanceof LockPatternView.CellState) { |
| 564 | final LockPatternView.CellState animatedCell = (LockPatternView.CellState) obj; |
Jorim Jaggi | f5b17e5 | 2015-07-21 15:34:26 -0700 | [diff] [blame] | 565 | mLockPatternView.startCellStateAnimation(animatedCell, |
| 566 | 1f, appearing ? 1f : 0f, /* alpha */ |
| 567 | appearing ? translationY : 0f, /* startTranslation */ |
| 568 | appearing ? 0f : translationY, /* endTranslation */ |
| 569 | appearing ? 0f : 1f, 1f /* scale */, |
| 570 | delay, duration, interpolator, finishListener); |
Jorim Jaggi | ff41a9a | 2015-06-09 15:31:28 -0700 | [diff] [blame] | 571 | } else { |
| 572 | mAppearAnimationUtils.createAnimation((View) obj, delay, duration, translationY, |
| 573 | appearing, interpolator, finishListener); |
| 574 | } |
| 575 | } |
The Android Open Source Project | afc4ab2 | 2009-03-03 19:32:34 -0800 | [diff] [blame] | 576 | } |
| 577 | } |