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.KeyEvent; 20 import android.view.MotionEvent; 21 import android.view.View; 22 import android.view.View.OnKeyListener; 23 import android.view.View.OnTouchListener; 24 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.systemui.R; 29 import com.android.systemui.classifier.FalsingCollector; 30 31 public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinBasedInputView> 32 extends KeyguardAbsKeyInputViewController<T> { 33 34 private final LiftToActivateListener mLiftToActivateListener; 35 private final FalsingCollector mFalsingCollector; 36 protected PasswordTextView mPasswordEntry; 37 38 private final OnKeyListener mOnKeyListener = (v, keyCode, event) -> { 39 if (event.getAction() == KeyEvent.ACTION_DOWN) { 40 return mView.onKeyDown(keyCode, event); 41 } 42 return false; 43 }; 44 45 private final OnTouchListener mActionButtonTouchListener = (v, event) -> { 46 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 47 mView.doHapticKeyClick(); 48 } 49 return false; 50 }; 51 KeyguardPinBasedInputViewController(T view, KeyguardUpdateMonitor keyguardUpdateMonitor, SecurityMode securityMode, LockPatternUtils lockPatternUtils, KeyguardSecurityCallback keyguardSecurityCallback, KeyguardMessageAreaController.Factory messageAreaControllerFactory, LatencyTracker latencyTracker, LiftToActivateListener liftToActivateListener, EmergencyButtonController emergencyButtonController, FalsingCollector falsingCollector)52 protected KeyguardPinBasedInputViewController(T view, 53 KeyguardUpdateMonitor keyguardUpdateMonitor, 54 SecurityMode securityMode, 55 LockPatternUtils lockPatternUtils, 56 KeyguardSecurityCallback keyguardSecurityCallback, 57 KeyguardMessageAreaController.Factory messageAreaControllerFactory, 58 LatencyTracker latencyTracker, 59 LiftToActivateListener liftToActivateListener, 60 EmergencyButtonController emergencyButtonController, 61 FalsingCollector falsingCollector) { 62 super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback, 63 messageAreaControllerFactory, latencyTracker, falsingCollector, 64 emergencyButtonController); 65 mLiftToActivateListener = liftToActivateListener; 66 mFalsingCollector = falsingCollector; 67 mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId()); 68 } 69 70 @Override onViewAttached()71 protected void onViewAttached() { 72 super.onViewAttached(); 73 74 boolean showAnimations = !mLockPatternUtils 75 .isPinEnhancedPrivacyEnabled(KeyguardUpdateMonitor.getCurrentUser()); 76 mPasswordEntry.setShowPassword(showAnimations); 77 for (NumPadKey button : mView.getButtons()) { 78 button.setOnTouchListener((v, event) -> { 79 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 80 mFalsingCollector.avoidGesture(); 81 } 82 return false; 83 }); 84 button.setAnimationEnabled(showAnimations); 85 } 86 mPasswordEntry.setOnKeyListener(mOnKeyListener); 87 mPasswordEntry.setUserActivityListener(this::onUserInput); 88 89 View deleteButton = mView.findViewById(R.id.delete_button); 90 deleteButton.setOnTouchListener(mActionButtonTouchListener); 91 deleteButton.setOnClickListener(v -> { 92 // check for time-based lockouts 93 if (mPasswordEntry.isEnabled()) { 94 mPasswordEntry.deleteLastChar(); 95 } 96 }); 97 deleteButton.setOnLongClickListener(v -> { 98 // check for time-based lockouts 99 if (mPasswordEntry.isEnabled()) { 100 mView.resetPasswordText(true /* animate */, true /* announce */); 101 } 102 mView.doHapticKeyClick(); 103 return true; 104 }); 105 106 View okButton = mView.findViewById(R.id.key_enter); 107 if (okButton != null) { 108 okButton.setOnTouchListener(mActionButtonTouchListener); 109 okButton.setOnClickListener(v -> { 110 if (mPasswordEntry.isEnabled()) { 111 verifyPasswordAndUnlock(); 112 } 113 }); 114 okButton.setOnHoverListener(mLiftToActivateListener); 115 } 116 } 117 118 @Override onViewDetached()119 protected void onViewDetached() { 120 super.onViewDetached(); 121 122 for (NumPadKey button : mView.getButtons()) { 123 button.setOnTouchListener(null); 124 } 125 } 126 127 @Override onResume(int reason)128 public void onResume(int reason) { 129 super.onResume(reason); 130 mPasswordEntry.requestFocus(); 131 } 132 133 @Override resetState()134 void resetState() { 135 mView.setPasswordEntryEnabled(true); 136 } 137 138 @Override startErrorAnimation()139 protected void startErrorAnimation() { 140 super.startErrorAnimation(); 141 mView.startErrorAnimation(); 142 } 143 144 @Override getInitialMessageResId()145 protected int getInitialMessageResId() { 146 return R.string.keyguard_enter_your_pin; 147 } 148 } 149