1 /* 2 * Copyright (C) 2020 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.keyguard; 18 19 import android.view.View; 20 21 import com.android.internal.util.LatencyTracker; 22 import com.android.internal.widget.LockPatternUtils; 23 import com.android.keyguard.KeyguardSecurityModel.SecurityMode; 24 import com.android.systemui.R; 25 import com.android.systemui.classifier.FalsingCollector; 26 import com.android.systemui.flags.FeatureFlags; 27 import com.android.systemui.flags.Flags; 28 import com.android.systemui.statusbar.policy.DevicePostureController; 29 30 public class KeyguardPinViewController 31 extends KeyguardPinBasedInputViewController<KeyguardPINView> { 32 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 33 private final DevicePostureController mPostureController; 34 private final DevicePostureController.Callback mPostureCallback = posture -> 35 mView.onDevicePostureChanged(posture); 36 private LockPatternUtils mLockPatternUtils; 37 private final FeatureFlags mFeatureFlags; 38 private static final int DEFAULT_PIN_LENGTH = 6; 39 private static final int MIN_FAILED_PIN_ATTEMPTS = 5; 40 private NumPadButton mBackspaceKey; 41 private View mOkButton = mView.findViewById(R.id.key_enter); 42 43 private long mPinLength; 44 45 private boolean mDisabledAutoConfirmation; 46 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)47 protected KeyguardPinViewController(KeyguardPINView view, 48 KeyguardUpdateMonitor keyguardUpdateMonitor, 49 SecurityMode securityMode, LockPatternUtils lockPatternUtils, 50 KeyguardSecurityCallback keyguardSecurityCallback, 51 KeyguardMessageAreaController.Factory messageAreaControllerFactory, 52 LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener, 53 EmergencyButtonController emergencyButtonController, 54 FalsingCollector falsingCollector, 55 DevicePostureController postureController, 56 FeatureFlags featureFlags) { 57 super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback, 58 messageAreaControllerFactory, latencyTracker, liftToActivateListener, 59 emergencyButtonController, falsingCollector, featureFlags); 60 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 61 mPostureController = postureController; 62 mLockPatternUtils = lockPatternUtils; 63 mFeatureFlags = featureFlags; 64 mBackspaceKey = view.findViewById(R.id.delete_button); 65 mPinLength = mLockPatternUtils.getPinLength(KeyguardUpdateMonitor.getCurrentUser()); 66 } 67 68 @Override onViewAttached()69 protected void onViewAttached() { 70 super.onViewAttached(); 71 72 View cancelBtn = mView.findViewById(R.id.cancel_button); 73 if (cancelBtn != null) { 74 cancelBtn.setOnClickListener(view -> { 75 getKeyguardSecurityCallback().reset(); 76 getKeyguardSecurityCallback().onCancelClicked(); 77 }); 78 } 79 mPasswordEntry.setUserActivityListener(this::onUserInput); 80 mView.onDevicePostureChanged(mPostureController.getDevicePosture()); 81 mPostureController.addCallback(mPostureCallback); 82 if (mFeatureFlags.isEnabled(Flags.AUTO_PIN_CONFIRMATION)) { 83 mPasswordEntry.setUsePinShapes(true); 84 updateAutoConfirmationState(); 85 } 86 } 87 onUserInput()88 protected void onUserInput() { 89 super.onUserInput(); 90 if (isAutoPinConfirmEnabledInSettings()) { 91 updateAutoConfirmationState(); 92 if (mPasswordEntry.getText().length() == mPinLength 93 && mOkButton.getVisibility() == View.INVISIBLE) { 94 verifyPasswordAndUnlock(); 95 } 96 } 97 } 98 99 @Override onViewDetached()100 protected void onViewDetached() { 101 super.onViewDetached(); 102 mPostureController.removeCallback(mPostureCallback); 103 } 104 105 @Override startAppearAnimation()106 public void startAppearAnimation() { 107 super.startAppearAnimation(); 108 } 109 110 @Override startDisappearAnimation(Runnable finishRunnable)111 public boolean startDisappearAnimation(Runnable finishRunnable) { 112 return mView.startDisappearAnimation( 113 mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable); 114 } 115 116 @Override handleAttemptLockout(long elapsedRealtimeDeadline)117 protected void handleAttemptLockout(long elapsedRealtimeDeadline) { 118 super.handleAttemptLockout(elapsedRealtimeDeadline); 119 updateAutoConfirmationState(); 120 } 121 updateAutoConfirmationState()122 private void updateAutoConfirmationState() { 123 mDisabledAutoConfirmation = mLockPatternUtils.getCurrentFailedPasswordAttempts( 124 KeyguardUpdateMonitor.getCurrentUser()) >= MIN_FAILED_PIN_ATTEMPTS; 125 updateOKButtonVisibility(); 126 updateBackSpaceVisibility(); 127 updatePinHinting(); 128 } 129 130 /** 131 * Updates the visibility of the OK button for auto confirm feature 132 */ updateOKButtonVisibility()133 private void updateOKButtonVisibility() { 134 if (isAutoPinConfirmEnabledInSettings() && !mDisabledAutoConfirmation) { 135 mOkButton.setVisibility(View.INVISIBLE); 136 } else { 137 mOkButton.setVisibility(View.VISIBLE); 138 } 139 } 140 141 /** 142 * Updates the visibility and the enabled state of the backspace. 143 * Visibility changes are only for auto confirmation configuration. 144 */ updateBackSpaceVisibility()145 private void updateBackSpaceVisibility() { 146 boolean isAutoConfirmation = isAutoPinConfirmEnabledInSettings(); 147 mBackspaceKey.setTransparentMode(/* isTransparentMode= */ 148 isAutoConfirmation && !mDisabledAutoConfirmation); 149 if (isAutoConfirmation) { 150 if (mPasswordEntry.getText().length() > 0 151 || mDisabledAutoConfirmation) { 152 mBackspaceKey.setVisibility(View.VISIBLE); 153 } else { 154 mBackspaceKey.setVisibility(View.INVISIBLE); 155 } 156 } 157 } 158 /** Updates whether to use pin hinting or not. */ updatePinHinting()159 void updatePinHinting() { 160 mPasswordEntry.setIsPinHinting(isAutoPinConfirmEnabledInSettings() && isPinHinting() 161 && !mDisabledAutoConfirmation); 162 } 163 164 /** 165 * Responsible for identifying if PIN hinting is to be enabled or not 166 */ isPinHinting()167 private boolean isPinHinting() { 168 return mPinLength == DEFAULT_PIN_LENGTH; 169 } 170 171 /** 172 * Responsible for identifying if auto confirm is enabled or not in Settings and 173 * a valid PIN_LENGTH is stored on the device (though the latter check is only to make it more 174 * robust since we only allow enabling PIN confirmation if the user has a valid PIN length 175 * saved on device) 176 */ isAutoPinConfirmEnabledInSettings()177 private boolean isAutoPinConfirmEnabledInSettings() { 178 //Checks if user has enabled the auto confirm in Settings 179 return mLockPatternUtils.isAutoPinConfirmEnabled(KeyguardUpdateMonitor.getCurrentUser()) 180 && mPinLength != LockPatternUtils.PIN_LENGTH_UNAVAILABLE; 181 } 182 } 183