blob: b3e08c0bc69fe89153ee562b57a95944a0508b08 [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.keyguard;
import android.view.View;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.policy.DevicePostureController;
public class KeyguardPinViewController
extends KeyguardPinBasedInputViewController<KeyguardPINView> {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final DevicePostureController mPostureController;
private final DevicePostureController.Callback mPostureCallback = posture ->
mView.onDevicePostureChanged(posture);
private LockPatternUtils mLockPatternUtils;
private final FeatureFlags mFeatureFlags;
private static final int DEFAULT_PIN_LENGTH = 6;
private static final int MIN_FAILED_PIN_ATTEMPTS = 5;
private NumPadButton mBackspaceKey;
private View mOkButton = mView.findViewById(R.id.key_enter);
private long mPinLength;
private boolean mDisabledAutoConfirmation;
protected KeyguardPinViewController(KeyguardPINView view,
KeyguardUpdateMonitor keyguardUpdateMonitor,
SecurityMode securityMode, LockPatternUtils lockPatternUtils,
KeyguardSecurityCallback keyguardSecurityCallback,
KeyguardMessageAreaController.Factory messageAreaControllerFactory,
LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener,
EmergencyButtonController emergencyButtonController,
FalsingCollector falsingCollector,
DevicePostureController postureController,
FeatureFlags featureFlags) {
super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
messageAreaControllerFactory, latencyTracker, liftToActivateListener,
emergencyButtonController, falsingCollector, featureFlags);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mPostureController = postureController;
mLockPatternUtils = lockPatternUtils;
mFeatureFlags = featureFlags;
mBackspaceKey = view.findViewById(R.id.delete_button);
mPinLength = mLockPatternUtils.getPinLength(KeyguardUpdateMonitor.getCurrentUser());
}
@Override
protected void onViewAttached() {
super.onViewAttached();
View cancelBtn = mView.findViewById(R.id.cancel_button);
if (cancelBtn != null) {
cancelBtn.setOnClickListener(view -> {
getKeyguardSecurityCallback().reset();
getKeyguardSecurityCallback().onCancelClicked();
});
}
mPasswordEntry.setUserActivityListener(this::onUserInput);
mView.onDevicePostureChanged(mPostureController.getDevicePosture());
mPostureController.addCallback(mPostureCallback);
}
protected void onUserInput() {
super.onUserInput();
if (isAutoPinConfirmEnabledInSettings()) {
updateAutoConfirmationState();
if (mPasswordEntry.getText().length() == mPinLength
&& mOkButton.getVisibility() == View.INVISIBLE) {
verifyPasswordAndUnlock();
}
}
}
@Override
protected void onViewDetached() {
super.onViewDetached();
mPostureController.removeCallback(mPostureCallback);
}
@Override
public void startAppearAnimation() {
if (mFeatureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)) {
mPasswordEntry.setUsePinShapes(true);
updateAutoConfirmationState();
}
super.startAppearAnimation();
}
@Override
public boolean startDisappearAnimation(Runnable finishRunnable) {
return mView.startDisappearAnimation(
mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
}
@Override
protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
super.handleAttemptLockout(elapsedRealtimeDeadline);
updateAutoConfirmationState();
}
private void updateAutoConfirmationState() {
mDisabledAutoConfirmation = mLockPatternUtils.getCurrentFailedPasswordAttempts(
KeyguardUpdateMonitor.getCurrentUser()) >= MIN_FAILED_PIN_ATTEMPTS;
updateOKButtonVisibility();
updateBackSpaceVisibility();
updatePinHinting();
}
/**
* Updates the visibility of the OK button for auto confirm feature
*/
private void updateOKButtonVisibility() {
if (isAutoPinConfirmEnabledInSettings() && !mDisabledAutoConfirmation) {
mOkButton.setVisibility(View.INVISIBLE);
} else {
mOkButton.setVisibility(View.VISIBLE);
}
}
/**
* Updates the visibility and the enabled state of the backspace.
* Visibility changes are only for auto confirmation configuration.
*/
private void updateBackSpaceVisibility() {
boolean isAutoConfirmation = isAutoPinConfirmEnabledInSettings();
mBackspaceKey.setTransparentMode(/* isTransparentMode= */
isAutoConfirmation && !mDisabledAutoConfirmation);
if (isAutoConfirmation) {
if (mPasswordEntry.getText().length() > 0
|| mDisabledAutoConfirmation) {
mBackspaceKey.setVisibility(View.VISIBLE);
} else {
mBackspaceKey.setVisibility(View.INVISIBLE);
}
}
}
/** Updates whether to use pin hinting or not. */
void updatePinHinting() {
mPasswordEntry.setIsPinHinting(isAutoPinConfirmEnabledInSettings() && isPinHinting()
&& !mDisabledAutoConfirmation);
}
/**
* Responsible for identifying if PIN hinting is to be enabled or not
*/
private boolean isPinHinting() {
return mPinLength == DEFAULT_PIN_LENGTH;
}
/**
* Responsible for identifying if auto confirm is enabled or not in Settings and
* a valid PIN_LENGTH is stored on the device (though the latter check is only to make it more
* robust since we only allow enabling PIN confirmation if the user has a valid PIN length
* saved on device)
*/
private boolean isAutoPinConfirmEnabledInSettings() {
//Checks if user has enabled the auto confirm in Settings
return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser())
&& mPinLength != LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
}
}