blob: 3d9fbcc8ad7338ff9d622f4bf055a6d075f8d8cd [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.settings.security;
import android.content.Context;
import android.os.CountDownTimer;
import android.os.SystemClock;
import androidx.annotation.Nullable;
import com.android.car.settings.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
/** Common lockout handling code. */
public class ConfirmLockLockoutHelper {
private static ConfirmLockLockoutHelper sInstance;
private final Context mContext;
private final int mUserId;
private final LockPatternUtils mLockPatternUtils;
private ConfirmLockUIController mUiController;
private CountDownTimer mCountDownTimer;
/** Return an instance of {@link ConfirmLockLockoutHelper}. */
public static ConfirmLockLockoutHelper getInstance(Context context, int userId) {
if (sInstance == null) {
sInstance = new ConfirmLockLockoutHelper(context, userId,
new LockPatternUtils(context));
}
return sInstance;
}
@VisibleForTesting
ConfirmLockLockoutHelper(Context context, int userId,
LockPatternUtils lockPatternUtils) {
mContext = context;
mUserId = userId;
mLockPatternUtils = lockPatternUtils;
}
/** Sets the UI controller. */
public void setConfirmLockUIController(ConfirmLockUIController uiController) {
mUiController = uiController;
}
/** Gets the lock pattern utils used by this helper. */
public LockPatternUtils getLockPatternUtils() {
return mLockPatternUtils;
}
/** Handles when the lock check is completed but returns a timeout. */
public void onCheckCompletedWithTimeout(int timeoutMs) {
if (timeoutMs <= 0) {
return;
}
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(mUserId, timeoutMs);
handleAttemptLockout(deadline);
}
/** To be called when the UI is resumed to reset the timeout countdown if necessary. */
public void onResumeUI() {
if (isLockedOut()) {
handleAttemptLockout(mLockPatternUtils.getLockoutAttemptDeadline(mUserId));
} else {
mUiController.refreshUI(isLockedOut());
}
}
/** To be called when the UI is paused to cancel the ongoing countdown timer. */
public void onPauseUI() {
if (mCountDownTimer != null) {
mCountDownTimer.cancel();
mUiController.setErrorText("");
}
}
@VisibleForTesting
@Nullable
CountDownTimer getCountDownTimer() {
return mCountDownTimer;
}
private void handleAttemptLockout(long deadline) {
long elapsedRealtime = SystemClock.elapsedRealtime();
mUiController.refreshUI(isLockedOut());
mCountDownTimer = newCountDownTimer(deadline - elapsedRealtime).start();
}
private boolean isLockedOut() {
return mLockPatternUtils.getLockoutAttemptDeadline(mUserId) != 0;
}
private CountDownTimer newCountDownTimer(long countDownMillis) {
return new CountDownTimer(countDownMillis,
LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
@Override
public void onTick(long millisUntilFinished) {
int secondsCountdown = (int) (millisUntilFinished / 1000);
mUiController.setErrorText(
mContext.getString(
R.string.lockpattern_too_many_failed_confirmation_attempts,
secondsCountdown));
}
@Override
public void onFinish() {
mUiController.refreshUI(/* isLockedOut= */ false);
mUiController.setErrorText("");
}
};
}
/** Interface for controlling the associated lock UI. */
public interface ConfirmLockUIController {
/** Sets the error text with the given string. */
void setErrorText(String text);
/** Refreshes the UI based on the locked out state. */
void refreshUI(boolean isLockedOut);
}
}