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