blob: e6a62c26712a1355aa45630a4225bfd2cdba5049 [file] [log] [blame]
Kevin Chyn8110ebb2019-10-02 11:16:31 -07001/*
2 * Copyright (C) 2019 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
17package com.android.systemui.biometrics;
18
19import android.content.Context;
Kevin Chynfc0040d2020-04-15 11:20:18 -070020import android.os.UserHandle;
Kevin Chyn8110ebb2019-10-02 11:16:31 -070021import android.text.InputType;
22import android.util.AttributeSet;
23import android.view.KeyEvent;
24import android.view.inputmethod.EditorInfo;
25import android.view.inputmethod.InputMethodManager;
26import android.widget.EditText;
27import android.widget.TextView;
28
29import com.android.internal.widget.LockPatternChecker;
Rubin Xua58125d2019-09-06 20:11:48 +010030import com.android.internal.widget.LockscreenCredential;
Kevin Chyn8110ebb2019-10-02 11:16:31 -070031import com.android.systemui.R;
32
33/**
34 * Pin and Password UI
35 */
36public class AuthCredentialPasswordView extends AuthCredentialView
37 implements TextView.OnEditorActionListener {
38
39 private static final String TAG = "BiometricPrompt/AuthCredentialPasswordView";
40
41 private final InputMethodManager mImm;
42 private EditText mPasswordField;
43
44 public AuthCredentialPasswordView(Context context,
45 AttributeSet attrs) {
46 super(context, attrs);
47 mImm = mContext.getSystemService(InputMethodManager.class);
48 }
49
50 @Override
51 protected void onFinishInflate() {
52 super.onFinishInflate();
53 mPasswordField = findViewById(R.id.lockPassword);
54 mPasswordField.setOnEditorActionListener(this);
Kevin Chyn0a45b662020-03-27 10:15:50 -070055 // TODO: De-dupe the logic with AuthContainerView
Kevin Chyn8110ebb2019-10-02 11:16:31 -070056 mPasswordField.setOnKeyListener((v, keyCode, event) -> {
57 if (keyCode != KeyEvent.KEYCODE_BACK) {
58 return false;
59 }
60 if (event.getAction() == KeyEvent.ACTION_UP) {
Kevin Chyn0a45b662020-03-27 10:15:50 -070061 mContainerView.sendEarlyUserCanceled();
Kevin Chyn8110ebb2019-10-02 11:16:31 -070062 mContainerView.animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
63 }
64 return true;
65 });
66 }
67
68 @Override
69 protected void onAttachedToWindow() {
70 super.onAttachedToWindow();
71
Kevin Chynfc0040d2020-04-15 11:20:18 -070072 mPasswordField.setTextOperationUser(UserHandle.of(mUserId));
Kevin Chync70d6b82019-10-03 15:32:37 -070073 if (mCredentialType == Utils.CREDENTIAL_PIN) {
74 mPasswordField.setInputType(
75 InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);
76 }
77
Kevin Chyn8110ebb2019-10-02 11:16:31 -070078 // Wait a bit to focus the field so the focusable flag on the window is already set then.
Kevin Chyn804d0c92020-01-23 10:42:20 -080079 postDelayed(() -> {
Kevin Chyn8110ebb2019-10-02 11:16:31 -070080 mPasswordField.requestFocus();
81 mImm.showSoftInput(mPasswordField, InputMethodManager.SHOW_IMPLICIT);
Kevin Chyn804d0c92020-01-23 10:42:20 -080082 }, 100);
Kevin Chyn8110ebb2019-10-02 11:16:31 -070083 }
84
85 @Override
86 public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
87 // Check if this was the result of hitting the enter key
88 final boolean isSoftImeEvent = event == null
89 && (actionId == EditorInfo.IME_NULL
90 || actionId == EditorInfo.IME_ACTION_DONE
91 || actionId == EditorInfo.IME_ACTION_NEXT);
92 final boolean isKeyboardEnterKey = event != null
93 && KeyEvent.isConfirmKey(event.getKeyCode())
94 && event.getAction() == KeyEvent.ACTION_DOWN;
95 if (isSoftImeEvent || isKeyboardEnterKey) {
96 checkPasswordAndUnlock();
97 return true;
98 }
99 return false;
100 }
101
102 private void checkPasswordAndUnlock() {
Kevin Chynb54bdfc2020-01-17 16:07:00 -0800103 try (LockscreenCredential password = mCredentialType == Utils.CREDENTIAL_PIN
Rubin Xua58125d2019-09-06 20:11:48 +0100104 ? LockscreenCredential.createPinOrNone(mPasswordField.getText())
105 : LockscreenCredential.createPasswordOrNone(mPasswordField.getText())) {
106 if (password.isNone()) {
107 return;
108 }
Kevin Chyn8110ebb2019-10-02 11:16:31 -0700109
Kevin Chync8cb6852020-03-10 18:29:15 -0700110 mPendingLockCheck = LockPatternChecker.verifyCredential(mLockPatternUtils,
111 password, mOperationId, mEffectiveUserId, this::onCredentialVerified);
Rubin Xua58125d2019-09-06 20:11:48 +0100112 }
Kevin Chyn8110ebb2019-10-02 11:16:31 -0700113 }
114
115 @Override
Kevin Chync8cb6852020-03-10 18:29:15 -0700116 protected void onCredentialVerified(byte[] attestation, int timeoutMs) {
117 super.onCredentialVerified(attestation, timeoutMs);
118
119 final boolean matched = attestation != null;
Kevin Chyn8110ebb2019-10-02 11:16:31 -0700120
121 if (matched) {
122 mImm.hideSoftInputFromWindow(getWindowToken(), 0 /* flags */);
123 } else {
124 mPasswordField.setText("");
125 }
126 }
127}