summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java229
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java257
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java54
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java39
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java233
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java270
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java140
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java113
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java50
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java308
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java350
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java376
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java404
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LiftToActivateListener.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadKey.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ViewController.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java120
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java106
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java79
23 files changed, 1828 insertions, 1354 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 889309dd72e7..1296990d4931 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -16,45 +16,30 @@
package com.android.keyguard;
-import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL;
-import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
-
import android.content.Context;
import android.content.res.ColorStateList;
-import android.os.AsyncTask;
-import android.os.CountDownTimer;
-import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.View;
-import com.android.internal.util.LatencyTracker;
-import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
/**
* Base class for PIN and password unlock screens.
*/
-public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
- implements EmergencyButton.EmergencyButtonCallback {
+public abstract class KeyguardAbsKeyInputView extends KeyguardInputView {
protected KeyguardSecurityCallback mCallback;
- protected LockPatternUtils mLockPatternUtils;
- protected AsyncTask<?, ?, ?> mPendingLockCheck;
protected SecurityMessageDisplay mSecurityMessageDisplay;
protected View mEcaView;
protected boolean mEnableHaptics;
- private boolean mDismissing;
- protected boolean mResumed;
- private CountDownTimer mCountdownTimer = null;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
// To avoid accidental lockout due to events while the device in in the pocket, ignore
// any passwords with length less than or equal to this length.
protected static final int MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT = 3;
+ private KeyDownListener mKeyDownListener;
public KeyguardAbsKeyInputView(Context context) {
this(context, null);
@@ -62,7 +47,10 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
public KeyguardAbsKeyInputView(Context context, AttributeSet attrs) {
super(context, attrs);
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+ }
+
+ void setEnableHaptics(boolean enableHaptics) {
+ mEnableHaptics = enableHaptics;
}
@Override
@@ -72,28 +60,10 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
@Override
public void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- mEnableHaptics = mLockPatternUtils.isTactileFeedbackEnabled();
}
@Override
public void reset() {
- // start fresh
- mDismissing = false;
- resetPasswordText(false /* animate */, false /* announce */);
- // if the user is currently locked out, enforce it.
- long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
- KeyguardUpdateMonitor.getCurrentUser());
- if (shouldLockout(deadline)) {
- handleAttemptLockout(deadline);
- } else {
- resetState();
- }
- }
-
- // Allow subclasses to override this behavior
- protected boolean shouldLockout(long deadline) {
- return deadline != 0;
}
protected abstract int getPasswordTextViewId();
@@ -101,24 +71,7 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
@Override
protected void onFinishInflate() {
- mLockPatternUtils = new LockPatternUtils(mContext);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
-
- EmergencyButton button = findViewById(R.id.emergency_call_button);
- if (button != null) {
- button.setCallback(this);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
- }
-
- @Override
- public void onEmergencyButtonClickedWhenInCall() {
- mCallback.reset();
}
/*
@@ -130,147 +83,14 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
return R.string.kg_wrong_password;
}
- protected void verifyPasswordAndUnlock() {
- if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
-
- final LockscreenCredential password = getEnteredCredential();
- setPasswordEntryInputEnabled(false);
- if (mPendingLockCheck != null) {
- mPendingLockCheck.cancel(false);
- }
-
- final int userId = KeyguardUpdateMonitor.getCurrentUser();
- if (password.size() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
- // to avoid accidental lockout, only count attempts that are long enough to be a
- // real password. This may require some tweaking.
- setPasswordEntryInputEnabled(true);
- onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
- password.zeroize();
- return;
- }
-
- if (LatencyTracker.isEnabled(mContext)) {
- LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
- LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
- }
-
- mKeyguardUpdateMonitor.setCredentialAttempted();
- mPendingLockCheck = LockPatternChecker.checkCredential(
- mLockPatternUtils,
- password,
- userId,
- new LockPatternChecker.OnCheckCallback() {
-
- @Override
- public void onEarlyMatched() {
- if (LatencyTracker.isEnabled(mContext)) {
- LatencyTracker.getInstance(mContext).onActionEnd(
- ACTION_CHECK_CREDENTIAL);
- }
- onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
- true /* isValidPassword */);
- password.zeroize();
- }
-
- @Override
- public void onChecked(boolean matched, int timeoutMs) {
- if (LatencyTracker.isEnabled(mContext)) {
- LatencyTracker.getInstance(mContext).onActionEnd(
- ACTION_CHECK_CREDENTIAL_UNLOCKED);
- }
- setPasswordEntryInputEnabled(true);
- mPendingLockCheck = null;
- if (!matched) {
- onPasswordChecked(userId, false /* matched */, timeoutMs,
- true /* isValidPassword */);
- }
- password.zeroize();
- }
-
- @Override
- public void onCancelled() {
- // We already got dismissed with the early matched callback, so we cancelled
- // the check. However, we still need to note down the latency.
- if (LatencyTracker.isEnabled(mContext)) {
- LatencyTracker.getInstance(mContext).onActionEnd(
- ACTION_CHECK_CREDENTIAL_UNLOCKED);
- }
- password.zeroize();
- }
- });
- }
-
- private void onPasswordChecked(int userId, boolean matched, int timeoutMs,
- boolean isValidPassword) {
- boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
- if (matched) {
- mCallback.reportUnlockAttempt(userId, true, 0);
- if (dismissKeyguard) {
- mDismissing = true;
- mCallback.dismiss(true, userId);
- }
- } else {
- if (isValidPassword) {
- mCallback.reportUnlockAttempt(userId, false, timeoutMs);
- if (timeoutMs > 0) {
- long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
- userId, timeoutMs);
- handleAttemptLockout(deadline);
- }
- }
- if (timeoutMs == 0) {
- mSecurityMessageDisplay.setMessage(getWrongPasswordStringId());
- }
- }
- resetPasswordText(true /* animate */, !matched /* announce deletion if no match */);
- }
-
protected abstract void resetPasswordText(boolean animate, boolean announce);
protected abstract LockscreenCredential getEnteredCredential();
protected abstract void setPasswordEntryEnabled(boolean enabled);
protected abstract void setPasswordEntryInputEnabled(boolean enabled);
- // Prevent user from using the PIN/Password entry until scheduled deadline.
- protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
- setPasswordEntryEnabled(false);
- long elapsedRealtime = SystemClock.elapsedRealtime();
- long secondsInFuture = (long) Math.ceil(
- (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
- mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
-
- @Override
- public void onTick(long millisUntilFinished) {
- int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0);
- mSecurityMessageDisplay.setMessage(mContext.getResources().getQuantityString(
- R.plurals.kg_too_many_failed_attempts_countdown,
- secondsRemaining, secondsRemaining));
- }
-
- @Override
- public void onFinish() {
- mSecurityMessageDisplay.setMessage("");
- resetState();
- }
- }.start();
- }
-
- protected void onUserInput() {
- if (mCallback != null) {
- mCallback.userActivity();
- mCallback.onUserInput();
- }
- mSecurityMessageDisplay.setMessage("");
- }
-
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- // Fingerprint sensor sends a KeyEvent.KEYCODE_UNKNOWN.
- // We don't want to consider it valid user input because the UI
- // will already respond to the event.
- if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
- onUserInput();
- }
- return false;
+ return mKeyDownListener != null && mKeyDownListener.onKeyDown(keyCode, event);
}
@Override
@@ -279,38 +99,13 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
}
@Override
- public void onPause() {
- mResumed = false;
-
- if (mCountdownTimer != null) {
- mCountdownTimer.cancel();
- mCountdownTimer = null;
- }
- if (mPendingLockCheck != null) {
- mPendingLockCheck.cancel(false);
- mPendingLockCheck = null;
- }
- reset();
- }
-
- @Override
- public void onResume(int reason) {
- mResumed = true;
- }
-
- @Override
public KeyguardSecurityCallback getCallback() {
return mCallback;
}
@Override
public void showPromptReason(int reason) {
- if (reason != PROMPT_REASON_NONE) {
- int promtReasonStringRes = getPromptReasonStringRes(reason);
- if (promtReasonStringRes != 0) {
- mSecurityMessageDisplay.setMessage(promtReasonStringRes);
- }
- }
+
}
@Override
@@ -336,5 +131,13 @@ public abstract class KeyguardAbsKeyInputView extends KeyguardInputView
public boolean startDisappearAnimation(Runnable finishRunnable) {
return false;
}
+
+ public void setKeyDownListener(KeyDownListener keyDownListener) {
+ mKeyDownListener = keyDownListener;
+ }
+
+ public interface KeyDownListener {
+ boolean onKeyDown(int keyCode, KeyEvent keyEvent);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
new file mode 100644
index 000000000000..3108ae3d2354
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -0,0 +1,257 @@
+/*
+ * 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 static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL;
+import static com.android.internal.util.LatencyTracker.ACTION_CHECK_CREDENTIAL_UNLOCKED;
+import static com.android.keyguard.KeyguardAbsKeyInputView.MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT;
+
+import android.os.AsyncTask;
+import android.os.CountDownTimer;
+import android.os.SystemClock;
+import android.view.KeyEvent;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternChecker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockscreenCredential;
+import com.android.keyguard.EmergencyButton.EmergencyButtonCallback;
+import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
+
+public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKeyInputView>
+ extends KeyguardInputViewController<T> {
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final LockPatternUtils mLockPatternUtils;
+ protected final KeyguardSecurityCallback mKeyguardSecurityCallback;
+ private final LatencyTracker mLatencyTracker;
+ private CountDownTimer mCountdownTimer;
+ protected KeyguardMessageAreaController mMessageAreaController;
+ private boolean mDismissing;
+ protected AsyncTask<?, ?, ?> mPendingLockCheck;
+ protected boolean mResumed;
+
+ private final KeyDownListener mKeyDownListener = (keyCode, keyEvent) -> {
+ // Fingerprint sensor sends a KeyEvent.KEYCODE_UNKNOWN.
+ // We don't want to consider it valid user input because the UI
+ // will already respond to the event.
+ if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
+ onUserInput();
+ }
+ return false;
+ };
+
+ private final EmergencyButtonCallback mEmergencyButtonCallback = new EmergencyButtonCallback() {
+ @Override
+ public void onEmergencyButtonClickedWhenInCall() {
+ mKeyguardSecurityCallback.reset();
+ }
+ };
+
+ protected KeyguardAbsKeyInputViewController(T view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode,
+ LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker) {
+ super(view, securityMode, keyguardSecurityCallback);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mLockPatternUtils = lockPatternUtils;
+ mKeyguardSecurityCallback = keyguardSecurityCallback;
+ mLatencyTracker = latencyTracker;
+ KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
+ mMessageAreaController = messageAreaControllerFactory.create(kma);
+ }
+
+ abstract void resetState();
+
+ @Override
+ protected void onViewAttached() {
+ mView.setKeyDownListener(mKeyDownListener);
+ mView.setEnableHaptics(mLockPatternUtils.isTactileFeedbackEnabled());
+ EmergencyButton button = mView.findViewById(R.id.emergency_call_button);
+ if (button != null) {
+ button.setCallback(mEmergencyButtonCallback);
+ }
+ }
+
+ @Override
+ public void reset() {
+ // start fresh
+ mDismissing = false;
+ mView.resetPasswordText(false /* animate */, false /* announce */);
+ // if the user is currently locked out, enforce it.
+ long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
+ KeyguardUpdateMonitor.getCurrentUser());
+ if (shouldLockout(deadline)) {
+ handleAttemptLockout(deadline);
+ } else {
+ mView.resetState();
+ }
+ }
+
+ // Allow subclasses to override this behavior
+ protected boolean shouldLockout(long deadline) {
+ return deadline != 0;
+ }
+
+ // Prevent user from using the PIN/Password entry until scheduled deadline.
+ protected void handleAttemptLockout(long elapsedRealtimeDeadline) {
+ mView.setPasswordEntryEnabled(false);
+ long elapsedRealtime = SystemClock.elapsedRealtime();
+ long secondsInFuture = (long) Math.ceil(
+ (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
+ mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {
+
+ @Override
+ public void onTick(long millisUntilFinished) {
+ int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0);
+ mMessageAreaController.setMessage(mView.getResources().getQuantityString(
+ R.plurals.kg_too_many_failed_attempts_countdown,
+ secondsRemaining, secondsRemaining));
+ }
+
+ @Override
+ public void onFinish() {
+ mMessageAreaController.setMessage("");
+ resetState();
+ }
+ }.start();
+ }
+
+ void onPasswordChecked(int userId, boolean matched, int timeoutMs, boolean isValidPassword) {
+ boolean dismissKeyguard = KeyguardUpdateMonitor.getCurrentUser() == userId;
+ if (matched) {
+ mKeyguardSecurityCallback.reportUnlockAttempt(userId, true, 0);
+ if (dismissKeyguard) {
+ mDismissing = true;
+ mKeyguardSecurityCallback.dismiss(true, userId);
+ }
+ } else {
+ if (isValidPassword) {
+ mKeyguardSecurityCallback.reportUnlockAttempt(userId, false, timeoutMs);
+ if (timeoutMs > 0) {
+ long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
+ userId, timeoutMs);
+ handleAttemptLockout(deadline);
+ }
+ }
+ if (timeoutMs == 0) {
+ mMessageAreaController.setMessage(mView.getWrongPasswordStringId());
+ }
+ }
+ mView.resetPasswordText(true /* animate */, !matched /* announce deletion if no match */);
+ }
+
+ protected void verifyPasswordAndUnlock() {
+ if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
+
+ final LockscreenCredential password = mView.getEnteredCredential();
+ mView.setPasswordEntryInputEnabled(false);
+ if (mPendingLockCheck != null) {
+ mPendingLockCheck.cancel(false);
+ }
+
+ final int userId = KeyguardUpdateMonitor.getCurrentUser();
+ if (password.size() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
+ // to avoid accidental lockout, only count attempts that are long enough to be a
+ // real password. This may require some tweaking.
+ mView.setPasswordEntryInputEnabled(true);
+ onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
+ password.zeroize();
+ return;
+ }
+
+ mLatencyTracker.onActionStart(ACTION_CHECK_CREDENTIAL);
+ mLatencyTracker.onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
+
+ mKeyguardUpdateMonitor.setCredentialAttempted();
+ mPendingLockCheck = LockPatternChecker.checkCredential(
+ mLockPatternUtils,
+ password,
+ userId,
+ new LockPatternChecker.OnCheckCallback() {
+
+ @Override
+ public void onEarlyMatched() {
+ mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL);
+
+ onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
+ true /* isValidPassword */);
+ password.zeroize();
+ }
+
+ @Override
+ public void onChecked(boolean matched, int timeoutMs) {
+ mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);
+ mView.setPasswordEntryInputEnabled(true);
+ mPendingLockCheck = null;
+ if (!matched) {
+ onPasswordChecked(userId, false /* matched */, timeoutMs,
+ true /* isValidPassword */);
+ }
+ password.zeroize();
+ }
+
+ @Override
+ public void onCancelled() {
+ // We already got dismissed with the early matched callback, so we cancelled
+ // the check. However, we still need to note down the latency.
+ mLatencyTracker.onActionEnd(ACTION_CHECK_CREDENTIAL_UNLOCKED);
+ password.zeroize();
+ }
+ });
+ }
+
+ @Override
+ public void showPromptReason(int reason) {
+ if (reason != PROMPT_REASON_NONE) {
+ int promtReasonStringRes = mView.getPromptReasonStringRes(reason);
+ if (promtReasonStringRes != 0) {
+ mMessageAreaController.setMessage(promtReasonStringRes);
+ }
+ }
+ }
+
+ protected void onUserInput() {
+ mKeyguardSecurityCallback.userActivity();
+ mKeyguardSecurityCallback.onUserInput();
+ mMessageAreaController.setMessage("");
+ }
+
+ @Override
+ public void onResume(int reason) {
+ mResumed = true;
+ }
+
+ @Override
+ public void onPause() {
+ mResumed = false;
+
+ if (mCountdownTimer != null) {
+ mCountdownTimer.cancel();
+ mCountdownTimer = null;
+ }
+ if (mPendingLockCheck != null) {
+ mPendingLockCheck.cancel(false);
+ mPendingLockCheck = null;
+ }
+ reset();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index ad6ca8582bf0..9ffa658da0e8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -178,18 +178,18 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
/** Initialize the Controller. */
public void init() {
super.init();
- mView.setViewMediatorCallback(mViewMediatorCallback);
- // Update ViewMediator with the current input method requirements
- mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
mKeyguardSecurityContainerController.init();
- mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback);
- mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
}
@Override
protected void onViewAttached() {
+ mView.setViewMediatorCallback(mViewMediatorCallback);
+ // Update ViewMediator with the current input method requirements
+ mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
mView.setOnKeyListener(mOnKeyListener);
+ mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback);
+ mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 552e62052e6f..c73149c7a8b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -17,32 +17,31 @@
package com.android.keyguard;
import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.telephony.TelephonyManager;
import android.view.MotionEvent;
+import android.view.inputmethod.InputMethodManager;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.ViewController;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import javax.inject.Inject;
/** Controller for a {@link KeyguardSecurityView}. */
-public class KeyguardInputViewController<T extends KeyguardInputView> extends ViewController<T>
- implements KeyguardSecurityView {
+public abstract class KeyguardInputViewController<T extends KeyguardInputView>
+ extends ViewController<T> implements KeyguardSecurityView {
private final SecurityMode mSecurityMode;
- private final LockPatternUtils mLockPatternUtils;
- private final KeyguardSecurityCallback mKeyguardSecurityCallback;
- private KeyguardMessageAreaController mMessageAreaController;
protected KeyguardInputViewController(T view, SecurityMode securityMode,
- LockPatternUtils lockPatternUtils,
KeyguardSecurityCallback keyguardSecurityCallback) {
super(view);
mSecurityMode = securityMode;
- mLockPatternUtils = lockPatternUtils;
- mKeyguardSecurityCallback = keyguardSecurityCallback;
mView.setKeyguardCallback(keyguardSecurityCallback);
}
@@ -151,16 +150,29 @@ public class KeyguardInputViewController<T extends KeyguardInputView> extends Vi
private final LockPatternUtils mLockPatternUtils;
private final LatencyTracker mLatencyTracker;
private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory;
+ private final InputMethodManager mInputMethodManager;
+ private final DelayableExecutor mMainExecutor;
+ private final Resources mResources;
+ private LiftToActivateListener mLiftToActivateListener;
+ private TelephonyManager mTelephonyManager;
@Inject
public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor,
LockPatternUtils lockPatternUtils,
LatencyTracker latencyTracker,
- KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ InputMethodManager inputMethodManager, @Main DelayableExecutor mainExecutor,
+ @Main Resources resources, LiftToActivateListener liftToActivateListener,
+ TelephonyManager telephonyManager) {
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
mMessageAreaControllerFactory = messageAreaControllerFactory;
+ mInputMethodManager = inputMethodManager;
+ mMainExecutor = mainExecutor;
+ mResources = resources;
+ mLiftToActivateListener = liftToActivateListener;
+ mTelephonyManager = telephonyManager;
}
/** Create a new {@link KeyguardInputViewController}. */
@@ -170,9 +182,29 @@ public class KeyguardInputViewController<T extends KeyguardInputView> extends Vi
return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
keyguardSecurityCallback, mLatencyTracker, mMessageAreaControllerFactory);
+ } else if (keyguardInputView instanceof KeyguardPasswordView) {
+ return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
+ mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
+ keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
+ mInputMethodManager, mMainExecutor, mResources);
+ } else if (keyguardInputView instanceof KeyguardPINView) {
+ return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
+ mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
+ keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
+ mLiftToActivateListener);
+ } else if (keyguardInputView instanceof KeyguardSimPinView) {
+ return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
+ mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
+ keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
+ mLiftToActivateListener, mTelephonyManager);
+ } else if (keyguardInputView instanceof KeyguardSimPukView) {
+ return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
+ mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
+ keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
+ mLiftToActivateListener, mTelephonyManager);
}
- return new KeyguardInputViewController<>(keyguardInputView, securityMode,
- mLockPatternUtils, keyguardSecurityCallback);
+
+ throw new RuntimeException("Unable to find controller for " + keyguardInputView);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 12ea1d586e10..bfa187ea099b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -24,7 +24,6 @@ import android.view.animation.AnimationUtils;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
/**
@@ -40,10 +39,8 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
private ViewGroup mRow1;
private ViewGroup mRow2;
private ViewGroup mRow3;
- private View mDivider;
private int mDisappearYTranslation;
private View[][] mViews;
- private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
public KeyguardPINView(Context context) {
this(context, null);
@@ -63,15 +60,10 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
mContext, android.R.interpolator.fast_out_linear_in));
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
- mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
}
@Override
protected void resetState() {
- super.resetState();
- if (mSecurityMessageDisplay != null) {
- mSecurityMessageDisplay.setMessage("");
- }
}
@Override
@@ -88,7 +80,6 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
mRow1 = findViewById(R.id.row1);
mRow2 = findViewById(R.id.row2);
mRow3 = findViewById(R.id.row3);
- mDivider = findViewById(R.id.divider);
mViews = new View[][]{
new View[]{
mRow0, null, null
@@ -123,6 +114,16 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
}
@Override
+ public void onPause() {
+
+ }
+
+ @Override
+ public void onResume(int reason) {
+
+ }
+
+ @Override
public void showUsabilityHint() {
}
@@ -149,22 +150,24 @@ public class KeyguardPINView extends KeyguardPinBasedInputView {
@Override
public boolean startDisappearAnimation(final Runnable finishRunnable) {
+ return false;
+ }
+
+ public boolean startDisappearAnimation(boolean needsSlowUnlockTransition,
+ final Runnable finishRunnable) {
+
enableClipping(false);
setTranslationY(0);
AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 280 /* duration */,
mDisappearYTranslation, mDisappearAnimationUtils.getInterpolator());
- DisappearAnimationUtils disappearAnimationUtils = mKeyguardUpdateMonitor
- .needsSlowUnlockTransition()
+ DisappearAnimationUtils disappearAnimationUtils = needsSlowUnlockTransition
? mDisappearAnimationUtilsLocked
: mDisappearAnimationUtils;
disappearAnimationUtils.startAnimation2d(mViews,
- new Runnable() {
- @Override
- public void run() {
- enableClipping(true);
- if (finishRunnable != null) {
- finishRunnable.run();
- }
+ () -> {
+ enableClipping(true);
+ if (finishRunnable != null) {
+ finishRunnable.run();
}
});
return true;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 97317cf5580f..3b865922503a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -18,48 +18,29 @@ package com.android.keyguard;
import android.content.Context;
import android.graphics.Rect;
-import android.os.UserHandle;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.text.method.TextKeyListener;
import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.systemui.R;
-
-import java.util.List;
/**
* Displays an alphanumeric (latin-1) key entry for the user to enter
* an unlock password
*/
public class KeyguardPasswordView extends KeyguardAbsKeyInputView
- implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
+ implements KeyguardSecurityView {
- private final boolean mShowImeAtScreenOn;
private final int mDisappearYTranslation;
// A delay constant to be used in a workaround for the situation where InputMethodManagerService
// is not switched to the new user yet.
// TODO: Remove this by ensuring such a race condition never happens.
- private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms
- InputMethodManager mImm;
private TextView mPasswordEntry;
private TextViewInputDisabler mPasswordEntryDisabler;
- private View mSwitchImeButton;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
@@ -70,8 +51,6 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
public KeyguardPasswordView(Context context, AttributeSet attrs) {
super(context, attrs);
- mShowImeAtScreenOn = context.getResources().
- getBoolean(R.bool.kg_show_ime_at_screen_on);
mDisappearYTranslation = getResources().getDimensionPixelSize(
R.dimen.disappear_y_translation);
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
@@ -82,20 +61,6 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
@Override
protected void resetState() {
- mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
- if (mSecurityMessageDisplay != null) {
- mSecurityMessageDisplay.setMessage("");
- }
- final boolean wasDisabled = mPasswordEntry.isEnabled();
- setPasswordEntryEnabled(true);
- setPasswordEntryInputEnabled(true);
- // Don't call showSoftInput when PasswordEntry is invisible or in pausing stage.
- if (!mResumed || !mPasswordEntry.isVisibleToUser()) {
- return;
- }
- if (wasDisabled) {
- mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
- }
}
@Override
@@ -104,29 +69,21 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
}
@Override
- public boolean needsInput() {
- return true;
+ public void onPause() {
}
@Override
- public void onResume(final int reason) {
- super.onResume(reason);
+ public void onResume(int reason) {
- // Wait a bit to focus the field so the focusable flag on the window is already set then.
- post(new Runnable() {
- @Override
- public void run() {
- if (isShown() && mPasswordEntry.isEnabled()) {
- mPasswordEntry.requestFocus();
- if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) {
- mImm.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
- }
- }
- }
- });
}
@Override
+ public boolean needsInput() {
+ return true;
+ }
+
+
+ @Override
protected int getPromptReasonStringRes(int reason) {
switch (reason) {
case PROMPT_REASON_RESTART:
@@ -146,97 +103,13 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
}
}
- @Override
- public void onPause() {
- super.onPause();
- mImm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
-
- @Override
- public void onStartingToHide() {
- mImm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
-
- private void updateSwitchImeButton() {
- // If there's more than one IME, enable the IME switcher button
- final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
- final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false);
- if (wasVisible != shouldBeVisible) {
- mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
- }
-
- // TODO: Check if we still need this hack.
- // If no icon is visible, reset the start margin on the password field so the text is
- // still centered.
- if (mSwitchImeButton.getVisibility() != View.VISIBLE) {
- android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- final MarginLayoutParams mlp = (MarginLayoutParams) params;
- mlp.setMarginStart(0);
- mPasswordEntry.setLayoutParams(params);
- }
- }
- }
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mImm = (InputMethodManager) getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
-
mPasswordEntry = findViewById(getPasswordTextViewId());
- mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
mPasswordEntryDisabler = new TextViewInputDisabler(mPasswordEntry);
- mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
- mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- mPasswordEntry.setOnEditorActionListener(this);
- mPasswordEntry.addTextChangedListener(this);
-
- // Poke the wakelock any time the text is selected or modified
- mPasswordEntry.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCallback.userActivity();
- }
- });
-
- // Set selected property on so the view can send accessibility events.
- mPasswordEntry.setSelected(true);
-
- mSwitchImeButton = findViewById(R.id.switch_ime_button);
- mSwitchImeButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCallback.userActivity(); // Leave the screen on a bit longer
- // Do not show auxiliary subtypes in password lock screen.
- mImm.showInputMethodPickerFromSystem(false /* showAuxiliarySubtypes */,
- getContext().getDisplayId());
- }
- });
-
- View cancelBtn = findViewById(R.id.cancel_button);
- if (cancelBtn != null) {
- cancelBtn.setOnClickListener(view -> {
- mCallback.reset();
- mCallback.onCancelClicked();
- });
- }
-
- // If there's more than one IME, enable the IME switcher button
- updateSwitchImeButton();
-
- // When we the current user is switching, InputMethodManagerService sometimes has not
- // switched internal state yet here. As a quick workaround, we check the keyboard state
- // again.
- // TODO: Remove this workaround by ensuring such a race condition never happens.
- postDelayed(new Runnable() {
- @Override
- public void run() {
- updateSwitchImeButton();
- }
- }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
}
@Override
@@ -265,55 +138,6 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
mPasswordEntryDisabler.setInputEnabled(enabled);
}
- /**
- * Method adapted from com.android.inputmethod.latin.Utils
- *
- * @param imm The input method manager
- * @param shouldIncludeAuxiliarySubtypes
- * @return true if we have multiple IMEs to choose from
- */
- private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
- final boolean shouldIncludeAuxiliarySubtypes) {
- final List<InputMethodInfo> enabledImis =
- imm.getEnabledInputMethodListAsUser(KeyguardUpdateMonitor.getCurrentUser());
-
- // Number of the filtered IMEs
- int filteredImisCount = 0;
-
- for (InputMethodInfo imi : enabledImis) {
- // We can return true immediately after we find two or more filtered IMEs.
- if (filteredImisCount > 1) return true;
- final List<InputMethodSubtype> subtypes =
- imm.getEnabledInputMethodSubtypeList(imi, true);
- // IMEs that have no subtypes should be counted.
- if (subtypes.isEmpty()) {
- ++filteredImisCount;
- continue;
- }
-
- int auxCount = 0;
- for (InputMethodSubtype subtype : subtypes) {
- if (subtype.isAuxiliary()) {
- ++auxCount;
- }
- }
- final int nonAuxCount = subtypes.size() - auxCount;
-
- // IMEs that have one or more non-auxiliary subtypes should be counted.
- // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
- // subtypes should be counted as well.
- if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
- ++filteredImisCount;
- continue;
- }
- }
-
- return filteredImisCount > 1
- // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
- // input method subtype (The current IME should be LatinIME.)
- || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
- }
-
@Override
public void showUsabilityHint() {
}
@@ -346,45 +170,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
}
@Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- if (mCallback != null) {
- mCallback.userActivity();
- }
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- // Poor man's user edit detection, assuming empty text is programmatic and everything else
- // is from the user.
- if (!TextUtils.isEmpty(s)) {
- onUserInput();
- }
- }
-
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- // Check if this was the result of hitting the enter key
- final boolean isSoftImeEvent = event == null
- && (actionId == EditorInfo.IME_NULL
- || actionId == EditorInfo.IME_ACTION_DONE
- || actionId == EditorInfo.IME_ACTION_NEXT);
- final boolean isKeyboardEnterKey = event != null
- && KeyEvent.isConfirmKey(event.getKeyCode())
- && event.getAction() == KeyEvent.ACTION_DOWN;
- if (isSoftImeEvent || isKeyboardEnterKey) {
- verifyPasswordAndUnlock();
- return true;
- }
- return false;
- }
-
- @Override
public CharSequence getTitle() {
- return getContext().getString(
+ return getResources().getString(
com.android.internal.R.string.keyguard_accessibility_password_unlock);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
new file mode 100644
index 000000000000..52afdcd1cacb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -0,0 +1,270 @@
+/*
+ * 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.content.res.Resources;
+import android.os.UserHandle;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.text.method.TextKeyListener;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup.MarginLayoutParams;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+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.dagger.qualifiers.Main;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+
+import java.util.List;
+
+public class KeyguardPasswordViewController
+ extends KeyguardAbsKeyInputViewController<KeyguardPasswordView> {
+
+ private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms
+
+ private final KeyguardSecurityCallback mKeyguardSecurityCallback;
+ private final InputMethodManager mInputMethodManager;
+ private final DelayableExecutor mMainExecutor;
+ private final boolean mShowImeAtScreenOn;
+ private TextView mPasswordEntry;
+ private View mSwitchImeButton;
+
+ private final OnEditorActionListener mOnEditorActionListener = (v, actionId, event) -> {
+ // Check if this was the result of hitting the enter key
+ final boolean isSoftImeEvent = event == null
+ && (actionId == EditorInfo.IME_NULL
+ || actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT);
+ final boolean isKeyboardEnterKey = event != null
+ && KeyEvent.isConfirmKey(event.getKeyCode())
+ && event.getAction() == KeyEvent.ACTION_DOWN;
+ if (isSoftImeEvent || isKeyboardEnterKey) {
+ verifyPasswordAndUnlock();
+ return true;
+ }
+ return false;
+ };
+
+ private final TextWatcher mTextWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ mKeyguardSecurityCallback.userActivity();
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (!TextUtils.isEmpty(s)) {
+ onUserInput();
+ }
+ }
+ };
+
+ protected KeyguardPasswordViewController(KeyguardPasswordView view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode,
+ LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker,
+ InputMethodManager inputMethodManager,
+ @Main DelayableExecutor mainExecutor,
+ @Main Resources resources) {
+ super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
+ messageAreaControllerFactory, latencyTracker);
+ mKeyguardSecurityCallback = keyguardSecurityCallback;
+ mInputMethodManager = inputMethodManager;
+ mMainExecutor = mainExecutor;
+ mShowImeAtScreenOn = resources.getBoolean(R.bool.kg_show_ime_at_screen_on);
+ mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId());
+ mSwitchImeButton = mView.findViewById(R.id.switch_ime_button);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+ mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
+ mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+ mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+
+ // Set selected property on so the view can send accessibility events.
+ mPasswordEntry.setSelected(true);
+ mPasswordEntry.setOnEditorActionListener(mOnEditorActionListener);
+ mPasswordEntry.addTextChangedListener(mTextWatcher);
+ // Poke the wakelock any time the text is selected or modified
+ mPasswordEntry.setOnClickListener(v -> mKeyguardSecurityCallback.userActivity());
+
+ mSwitchImeButton.setOnClickListener(v -> {
+ mKeyguardSecurityCallback.userActivity(); // Leave the screen on a bit longer
+ // Do not show auxiliary subtypes in password lock screen.
+ mInputMethodManager.showInputMethodPickerFromSystem(false,
+ mView.getContext().getDisplayId());
+ });
+
+ View cancelBtn = mView.findViewById(R.id.cancel_button);
+ if (cancelBtn != null) {
+ cancelBtn.setOnClickListener(view -> {
+ mKeyguardSecurityCallback.reset();
+ mKeyguardSecurityCallback.onCancelClicked();
+ });
+ }
+
+ // If there's more than one IME, enable the IME switcher button
+ updateSwitchImeButton();
+
+ // When we the current user is switching, InputMethodManagerService sometimes has not
+ // switched internal state yet here. As a quick workaround, we check the keyboard state
+ // again.
+ // TODO: Remove this workaround by ensuring such a race condition never happens.
+ mMainExecutor.executeDelayed(
+ this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ super.onViewDetached();
+ mPasswordEntry.setOnEditorActionListener(null);
+ }
+
+ @Override
+ void resetState() {
+ mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
+ mMessageAreaController.setMessage("");
+ final boolean wasDisabled = mPasswordEntry.isEnabled();
+ mView.setPasswordEntryEnabled(true);
+ mView.setPasswordEntryInputEnabled(true);
+ // Don't call showSoftInput when PasswordEntry is invisible or in pausing stage.
+ if (!mResumed || !mPasswordEntry.isVisibleToUser()) {
+ return;
+ }
+ if (wasDisabled) {
+ mInputMethodManager.showSoftInput(mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
+ }
+ }
+
+ @Override
+ public void onResume(int reason) {
+ super.onResume(reason);
+ // Wait a bit to focus the field so the focusable flag on the window is already set then.
+ mMainExecutor.execute(() -> {
+ if (mView.isShown() && mPasswordEntry.isEnabled()) {
+ mPasswordEntry.requestFocus();
+ if (reason != KeyguardSecurityView.SCREEN_ON || mShowImeAtScreenOn) {
+ mInputMethodManager.showSoftInput(
+ mPasswordEntry, InputMethodManager.SHOW_IMPLICIT);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0);
+ }
+
+ @Override
+ public void onStartingToHide() {
+ mInputMethodManager.hideSoftInputFromWindow(mView.getWindowToken(), 0);
+ }
+
+ private void updateSwitchImeButton() {
+ // If there's more than one IME, enable the IME switcher button
+ final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE;
+ final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(
+ mInputMethodManager, false);
+ if (wasVisible != shouldBeVisible) {
+ mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE);
+ }
+
+ // TODO: Check if we still need this hack.
+ // If no icon is visible, reset the start margin on the password field so the text is
+ // still centered.
+ if (mSwitchImeButton.getVisibility() != View.VISIBLE) {
+ android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams();
+ if (params instanceof MarginLayoutParams) {
+ final MarginLayoutParams mlp = (MarginLayoutParams) params;
+ mlp.setMarginStart(0);
+ mPasswordEntry.setLayoutParams(params);
+ }
+ }
+ }
+
+ /**
+ * Method adapted from com.android.inputmethod.latin.Utils
+ *
+ * @param imm The input method manager
+ * @param shouldIncludeAuxiliarySubtypes
+ * @return true if we have multiple IMEs to choose from
+ */
+ private boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm,
+ final boolean shouldIncludeAuxiliarySubtypes) {
+ final List<InputMethodInfo> enabledImis =
+ imm.getEnabledInputMethodListAsUser(KeyguardUpdateMonitor.getCurrentUser());
+
+ // Number of the filtered IMEs
+ int filteredImisCount = 0;
+
+ for (InputMethodInfo imi : enabledImis) {
+ // We can return true immediately after we find two or more filtered IMEs.
+ if (filteredImisCount > 1) return true;
+ final List<InputMethodSubtype> subtypes =
+ imm.getEnabledInputMethodSubtypeList(imi, true);
+ // IMEs that have no subtypes should be counted.
+ if (subtypes.isEmpty()) {
+ ++filteredImisCount;
+ continue;
+ }
+
+ int auxCount = 0;
+ for (InputMethodSubtype subtype : subtypes) {
+ if (subtype.isAuxiliary()) {
+ ++auxCount;
+ }
+ }
+ final int nonAuxCount = subtypes.size() - auxCount;
+
+ // IMEs that have one or more non-auxiliary subtypes should be counted.
+ // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary
+ // subtypes should be counted as well.
+ if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) {
+ ++filteredImisCount;
+ continue;
+ }
+ }
+
+ return filteredImisCount > 1
+ // imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's
+ //enabled input method subtype (The current IME should be LatinIME.)
+ || imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 5e547d3120bf..13a16360be04 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -180,18 +180,18 @@ public class KeyguardPatternViewController
KeyguardSecurityCallback keyguardSecurityCallback,
LatencyTracker latencyTracker,
KeyguardMessageAreaController.Factory messageAreaControllerFactory) {
- super(view, securityMode, lockPatternUtils, keyguardSecurityCallback);
+ super(view, securityMode, keyguardSecurityCallback);
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
mLatencyTracker = latencyTracker;
mMessageAreaControllerFactory = messageAreaControllerFactory;
+ KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
+ mMessageAreaController = mMessageAreaControllerFactory.create(kma);
+ mLockPatternView = mView.findViewById(R.id.lockPatternView);
}
@Override
protected void onViewAttached() {
- KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView);
- mMessageAreaController = mMessageAreaControllerFactory.create(kma);
- mLockPatternView = mView.findViewById(R.id.lockPatternView);
mLockPatternView.setOnPatternListener(new UnlockPatternListener());
mLockPatternView.setSaveEnabled(false);
mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index c7f27cf8a71a..e579380fc8d5 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.View;
import com.android.internal.widget.LockscreenCredential;
@@ -29,22 +28,12 @@ import com.android.systemui.R;
/**
* A Pin based Keyguard input view
*/
-public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
- implements View.OnKeyListener, View.OnTouchListener {
+public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView {
protected PasswordTextView mPasswordEntry;
private View mOkButton;
private View mDeleteButton;
- private View mButton0;
- private View mButton1;
- private View mButton2;
- private View mButton3;
- private View mButton4;
- private View mButton5;
- private View mButton6;
- private View mButton7;
- private View mButton8;
- private View mButton9;
+ private View[] mButtons = new View[10];
public KeyguardPinBasedInputView(Context context) {
this(context, null);
@@ -62,7 +51,6 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
@Override
protected void resetState() {
- setPasswordEntryEnabled(true);
}
@Override
@@ -86,10 +74,10 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (KeyEvent.isConfirmKey(keyCode)) {
- performClick(mOkButton);
+ mOkButton.performClick();
return true;
} else if (keyCode == KeyEvent.KEYCODE_DEL) {
- performClick(mDeleteButton);
+ mDeleteButton.performClick();
return true;
}
if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) {
@@ -125,42 +113,9 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
}
}
- private void performClick(View view) {
- view.performClick();
- }
-
private void performNumberClick(int number) {
- switch (number) {
- case 0:
- performClick(mButton0);
- break;
- case 1:
- performClick(mButton1);
- break;
- case 2:
- performClick(mButton2);
- break;
- case 3:
- performClick(mButton3);
- break;
- case 4:
- performClick(mButton4);
- break;
- case 5:
- performClick(mButton5);
- break;
- case 6:
- performClick(mButton6);
- break;
- case 7:
- performClick(mButton7);
- break;
- case 8:
- performClick(mButton8);
- break;
- case 9:
- performClick(mButton9);
- break;
+ if (number >= 0 && number <= 9) {
+ mButtons[number].performClick();
}
}
@@ -177,94 +132,31 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView
@Override
protected void onFinishInflate() {
mPasswordEntry = findViewById(getPasswordTextViewId());
- mPasswordEntry.setOnKeyListener(this);
// Set selected property on so the view can send accessibility events.
mPasswordEntry.setSelected(true);
- mPasswordEntry.setUserActivityListener(new PasswordTextView.UserActivityListener() {
- @Override
- public void onUserActivity() {
- onUserInput();
- }
- });
-
mOkButton = findViewById(R.id.key_enter);
- if (mOkButton != null) {
- mOkButton.setOnTouchListener(this);
- mOkButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mPasswordEntry.isEnabled()) {
- verifyPasswordAndUnlock();
- }
- }
- });
- mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
- }
mDeleteButton = findViewById(R.id.delete_button);
mDeleteButton.setVisibility(View.VISIBLE);
- mDeleteButton.setOnTouchListener(this);
- mDeleteButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // check for time-based lockouts
- if (mPasswordEntry.isEnabled()) {
- mPasswordEntry.deleteLastChar();
- }
- }
- });
- mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- // check for time-based lockouts
- if (mPasswordEntry.isEnabled()) {
- resetPasswordText(true /* animate */, true /* announce */);
- }
- doHapticKeyClick();
- return true;
- }
- });
- mButton0 = findViewById(R.id.key0);
- mButton1 = findViewById(R.id.key1);
- mButton2 = findViewById(R.id.key2);
- mButton3 = findViewById(R.id.key3);
- mButton4 = findViewById(R.id.key4);
- mButton5 = findViewById(R.id.key5);
- mButton6 = findViewById(R.id.key6);
- mButton7 = findViewById(R.id.key7);
- mButton8 = findViewById(R.id.key8);
- mButton9 = findViewById(R.id.key9);
+ mButtons[0] = findViewById(R.id.key0);
+ mButtons[1] = findViewById(R.id.key1);
+ mButtons[2] = findViewById(R.id.key2);
+ mButtons[3] = findViewById(R.id.key3);
+ mButtons[4] = findViewById(R.id.key4);
+ mButtons[5] = findViewById(R.id.key5);
+ mButtons[6] = findViewById(R.id.key6);
+ mButtons[7] = findViewById(R.id.key7);
+ mButtons[8] = findViewById(R.id.key8);
+ mButtons[9] = findViewById(R.id.key9);
mPasswordEntry.requestFocus();
super.onFinishInflate();
}
@Override
- public void onResume(int reason) {
- super.onResume(reason);
- mPasswordEntry.requestFocus();
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- doHapticKeyClick();
- }
- return false;
- }
-
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- return onKeyDown(keyCode, event);
- }
- return false;
- }
-
- @Override
public CharSequence getTitle() {
return getContext().getString(
com.android.internal.R.string.keyguard_accessibility_pin_unlock);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
new file mode 100644
index 000000000000..4d0ebfffbe04
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -0,0 +1,113 @@
+/*
+ * 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.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnKeyListener;
+import android.view.View.OnTouchListener;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
+
+public abstract class KeyguardPinBasedInputViewController<T extends KeyguardPinBasedInputView>
+ extends KeyguardAbsKeyInputViewController<T> {
+
+ private final LiftToActivateListener mLiftToActivateListener;
+ protected PasswordTextView mPasswordEntry;
+
+ private final OnKeyListener mOnKeyListener = (v, keyCode, event) -> {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ return mView.onKeyDown(keyCode, event);
+ }
+ return false;
+ };
+
+ private final OnTouchListener mOnTouchListener = (v, event) -> {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mView.doHapticKeyClick();
+ }
+ return false;
+ };
+
+ protected KeyguardPinBasedInputViewController(T view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode,
+ LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker,
+ LiftToActivateListener liftToActivateListener) {
+ super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
+ messageAreaControllerFactory, latencyTracker);
+ mLiftToActivateListener = liftToActivateListener;
+ mPasswordEntry = mView.findViewById(mView.getPasswordTextViewId());
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+
+ mPasswordEntry.setOnKeyListener(mOnKeyListener);
+ mPasswordEntry.setUserActivityListener(this::onUserInput);
+
+ View deleteButton = mView.findViewById(R.id.delete_button);
+ deleteButton.setOnTouchListener(mOnTouchListener);
+ deleteButton.setOnClickListener(v -> {
+ // check for time-based lockouts
+ if (mPasswordEntry.isEnabled()) {
+ mPasswordEntry.deleteLastChar();
+ }
+ });
+ deleteButton.setOnLongClickListener(v -> {
+ // check for time-based lockouts
+ if (mPasswordEntry.isEnabled()) {
+ mView.resetPasswordText(true /* animate */, true /* announce */);
+ }
+ mView.doHapticKeyClick();
+ return true;
+ });
+
+ View okButton = mView.findViewById(R.id.key_enter);
+ if (okButton != null) {
+ okButton.setOnTouchListener(mOnTouchListener);
+ okButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mPasswordEntry.isEnabled()) {
+ verifyPasswordAndUnlock();
+ }
+ }
+ });
+ okButton.setOnHoverListener(mLiftToActivateListener);
+ }
+ }
+
+ @Override
+ public void onResume(int reason) {
+ super.onResume(reason);
+ mPasswordEntry.requestFocus();
+ }
+
+ @Override
+ void resetState() {
+ mView.setPasswordEntryEnabled(true);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
new file mode 100644
index 000000000000..625ab5214da1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
+public class KeyguardPinViewController
+ extends KeyguardPinBasedInputViewController<KeyguardPINView> {
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ protected KeyguardPinViewController(KeyguardPINView view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode, LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker,
+ LiftToActivateListener liftToActivateListener) {
+ super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
+ messageAreaControllerFactory, latencyTracker, liftToActivateListener);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ }
+
+ @Override
+ void resetState() {
+ super.resetState();
+ mMessageAreaController.setMessage("");
+ }
+
+ @Override
+ public boolean startDisappearAnimation(Runnable finishRunnable) {
+ return mView.startDisappearAnimation(
+ mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 342f3de2ede3..2c7dce6e4302 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -197,6 +197,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
@Override
public void init() {
super.init();
+ mSecurityViewFlipperController.init();
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 1c47aa0151f0..202971d2a009 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -16,66 +16,19 @@
package com.android.keyguard;
-import android.annotation.NonNull;
-import android.app.AlertDialog;
-import android.app.AlertDialog.Builder;
-import android.app.Dialog;
-import android.app.ProgressDialog;
import android.content.Context;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.telephony.PinResult;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
-import android.view.WindowManager;
-import android.widget.ImageView;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
/**
* Displays a PIN pad for unlocking.
*/
public class KeyguardSimPinView extends KeyguardPinBasedInputView {
- private static final String LOG_TAG = "KeyguardSimPinView";
- private static final boolean DEBUG = KeyguardConstants.DEBUG_SIM_STATES;
public static final String TAG = "KeyguardSimPinView";
- private ProgressDialog mSimUnlockProgressDialog = null;
- private CheckSimPin mCheckSimPinThread;
-
- // Below flag is set to true during power-up or when a new SIM card inserted on device.
- // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
- // be displayed to inform user about the number of remaining PIN attempts left.
- private boolean mShowDefaultMessage = true;
- private int mRemainingAttempts = -1;
- private AlertDialog mRemainingAttemptsDialog;
- private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private ImageView mSimImageView;
-
- KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onSimStateChanged(int subId, int slotId, int simState) {
- if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
- switch(simState) {
- case TelephonyManager.SIM_STATE_READY: {
- mRemainingAttempts = -1;
- resetState();
- break;
- }
- default:
- resetState();
- }
- }
- };
-
public KeyguardSimPinView(Context context) {
this(context, null);
}
@@ -84,81 +37,9 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
super(context, attrs);
}
- @Override
- public void resetState() {
- super.resetState();
- if (DEBUG) Log.v(TAG, "Resetting state");
- handleSubInfoChangeIfNeeded();
- if (mShowDefaultMessage) {
- showDefaultMessage();
- }
- boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
-
+ public void setEsimLocked(boolean locked) {
KeyguardEsimArea esimButton = findViewById(R.id.keyguard_esim_area);
- esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE);
- }
-
- private void setLockedSimMessage() {
- boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = 1;
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- if (telephonyManager != null) {
- count = telephonyManager.getActiveModemCount();
- }
- Resources rez = getResources();
- String msg;
- TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
- int color = array.getColor(0, Color.WHITE);
- array.recycle();
- if (count < 2) {
- msg = rez.getString(R.string.kg_sim_pin_instructions);
- } else {
- SubscriptionInfo info = Dependency.get(KeyguardUpdateMonitor.class)
- .getSubscriptionInfoForSubId(mSubId);
- CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
- msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
- if (info != null) {
- color = info.getIconTint();
- }
- }
- if (isEsimLocked) {
- msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
- }
-
- if (mSecurityMessageDisplay != null && getVisibility() == VISIBLE) {
- mSecurityMessageDisplay.setMessage(msg);
- }
- mSimImageView.setImageTintList(ColorStateList.valueOf(color));
- }
-
- private void showDefaultMessage() {
- setLockedSimMessage();
- if (mRemainingAttempts >= 0) {
- return;
- }
-
- // Sending empty PIN here to query the number of remaining PIN attempts
- new CheckSimPin("", mSubId) {
- void onSimCheckResponse(final PinResult result) {
- Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result "
- + result.toString());
- if (result.getAttemptsRemaining() >= 0) {
- mRemainingAttempts = result.getAttemptsRemaining();
- setLockedSimMessage();
- }
- }
- }.start();
- }
-
- private void handleSubInfoChangeIfNeeded() {
- KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class);
- int subId = monitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PIN_REQUIRED);
- if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
- mSubId = subId;
- mShowDefaultMessage = true;
- mRemainingAttempts = -1;
- }
+ esimButton.setVisibility(locked ? View.VISIBLE : View.GONE);
}
@Override
@@ -173,35 +54,6 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
return 0;
}
- private String getPinPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
- String displayMessage;
- int msgId;
- if (attemptsRemaining == 0) {
- displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked);
- } else if (attemptsRemaining > 0) {
- msgId = isDefault ? R.plurals.kg_password_default_pin_message :
- R.plurals.kg_password_wrong_pin_code;
- displayMessage = getContext().getResources()
- .getQuantityString(msgId, attemptsRemaining, attemptsRemaining);
- } else {
- msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed;
- displayMessage = getContext().getString(msgId);
- }
- if (KeyguardEsimArea.isEsimLocked(mContext, mSubId)) {
- displayMessage = getResources()
- .getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
- }
- if (DEBUG) Log.d(LOG_TAG, "getPinPasswordErrorMessage:"
- + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
- return displayMessage;
- }
-
- @Override
- protected boolean shouldLockout(long deadline) {
- // SIM PIN doesn't have a timed lockout
- return false;
- }
-
@Override
protected int getPasswordTextViewId() {
return R.id.simPinEntry;
@@ -214,173 +66,21 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
if (mEcaView instanceof EmergencyCarrierArea) {
((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
}
- mSimImageView = findViewById(R.id.keyguard_sim);
}
@Override
- public void showUsabilityHint() {
+ public void onPause() {
}
@Override
public void onResume(int reason) {
- super.onResume(reason);
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback);
- resetState();
- }
- @Override
- public void onPause() {
- // dismiss the dialog.
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.dismiss();
- mSimUnlockProgressDialog = null;
- }
- Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mUpdateMonitorCallback);
- }
-
- /**
- * Since the IPC can block, we want to run the request in a separate thread
- * with a callback.
- */
- private abstract class CheckSimPin extends Thread {
- private final String mPin;
- private int mSubId;
-
- protected CheckSimPin(String pin, int subId) {
- mPin = pin;
- mSubId = subId;
- }
-
- abstract void onSimCheckResponse(@NonNull PinResult result);
-
- @Override
- public void run() {
- if (DEBUG) {
- Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
- }
- TelephonyManager telephonyManager =
- ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
- .createForSubscriptionId(mSubId);
- final PinResult result = telephonyManager.supplyPinReportPinResult(mPin);
- if (result == null) {
- Log.e(TAG, "Error result for supplyPinReportResult.");
- post(new Runnable() {
- @Override
- public void run() {
- onSimCheckResponse(PinResult.getDefaultFailedResult());
- }
- });
- } else {
- if (DEBUG) {
- Log.v(TAG, "supplyPinReportResult returned: " + result.toString());
- }
- post(new Runnable() {
- @Override
- public void run() {
- onSimCheckResponse(result);
- }
- });
- }
- }
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- return mSimUnlockProgressDialog;
- }
-
- private Dialog getSimRemainingAttemptsDialog(int remaining) {
- String msg = getPinPasswordErrorMessage(remaining, false);
- if (mRemainingAttemptsDialog == null) {
- Builder builder = new AlertDialog.Builder(mContext);
- builder.setMessage(msg);
- builder.setCancelable(false);
- builder.setNeutralButton(R.string.ok, null);
- mRemainingAttemptsDialog = builder.create();
- mRemainingAttemptsDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- } else {
- mRemainingAttemptsDialog.setMessage(msg);
- }
- return mRemainingAttemptsDialog;
}
@Override
- protected void verifyPasswordAndUnlock() {
- String entry = mPasswordEntry.getText();
-
- if (entry.length() < 4) {
- // otherwise, display a message to the user, and don't submit.
- mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint);
- resetPasswordText(true /* animate */, true /* announce */);
- mCallback.userActivity();
- return;
- }
-
- getSimUnlockProgressDialog().show();
+ public void showUsabilityHint() {
- if (mCheckSimPinThread == null) {
- mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText(), mSubId) {
- @Override
- void onSimCheckResponse(final PinResult result) {
- post(new Runnable() {
- @Override
- public void run() {
- mRemainingAttempts = result.getAttemptsRemaining();
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- resetPasswordText(true /* animate */,
- /* announce */
- result.getType() != PinResult.PIN_RESULT_TYPE_SUCCESS);
- if (result.getType() == PinResult.PIN_RESULT_TYPE_SUCCESS) {
- Dependency.get(KeyguardUpdateMonitor.class)
- .reportSimUnlocked(mSubId);
- mRemainingAttempts = -1;
- mShowDefaultMessage = true;
- if (mCallback != null) {
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
- }
- } else {
- mShowDefaultMessage = false;
- if (result.getType() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
- if (result.getAttemptsRemaining() <= 2) {
- // this is getting critical - show dialog
- getSimRemainingAttemptsDialog(
- result.getAttemptsRemaining()).show();
- } else {
- // show message
- mSecurityMessageDisplay.setMessage(
- getPinPasswordErrorMessage(
- result.getAttemptsRemaining(), false));
- }
- } else {
- // "PIN operation failed!" - no idea what this was and no way to
- // find out. :/
- mSecurityMessageDisplay.setMessage(getContext().getString(
- R.string.kg_password_pin_failed));
- }
- if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
- + " CheckSimPin.onSimCheckResponse: " + result
- + " attemptsRemaining=" + result.getAttemptsRemaining());
- }
- mCallback.userActivity();
- mCheckSimPinThread = null;
- }
- });
- }
- };
- mCheckSimPinThread.start();
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
new file mode 100644
index 000000000000..3c29058e0afc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -0,0 +1,350 @@
+/*
+ * 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.annotation.NonNull;
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.telephony.PinResult;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
+
+public class KeyguardSimPinViewController
+ extends KeyguardPinBasedInputViewController<KeyguardSimPinView> {
+ public static final String TAG = "KeyguardSimPinView";
+ private static final String LOG_TAG = "KeyguardSimPinView";
+ private static final boolean DEBUG = KeyguardConstants.DEBUG_SIM_STATES;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final TelephonyManager mTelephonyManager;
+
+ private ProgressDialog mSimUnlockProgressDialog;
+ private CheckSimPin mCheckSimPinThread;
+ private int mRemainingAttempts;
+ // Below flag is set to true during power-up or when a new SIM card inserted on device.
+ // When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
+ // be displayed to inform user about the number of remaining PIN attempts left.
+ private boolean mShowDefaultMessage;
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private AlertDialog mRemainingAttemptsDialog;
+ private ImageView mSimImageView;
+
+ KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onSimStateChanged(int subId, int slotId, int simState) {
+ if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+ if (simState == TelephonyManager.SIM_STATE_READY) {
+ mRemainingAttempts = -1;
+ resetState();
+ } else {
+ resetState();
+ }
+ }
+ };
+
+ protected KeyguardSimPinViewController(KeyguardSimPinView view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode, LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker,
+ LiftToActivateListener liftToActivateListener,
+ TelephonyManager telephonyManager) {
+ super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
+ messageAreaControllerFactory, latencyTracker, liftToActivateListener);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mTelephonyManager = telephonyManager;
+ mSimImageView = mView.findViewById(R.id.keyguard_sim);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+ }
+
+ @Override
+ void resetState() {
+ super.resetState();
+ if (DEBUG) Log.v(TAG, "Resetting state");
+ handleSubInfoChangeIfNeeded();
+ mMessageAreaController.setMessage("");
+ if (mShowDefaultMessage) {
+ showDefaultMessage();
+ }
+
+ mView.setEsimLocked(KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId));
+ }
+
+ @Override
+ public boolean startDisappearAnimation(Runnable finishRunnable) {
+ return mView.startDisappearAnimation(finishRunnable);
+ }
+
+ @Override
+ public void onResume(int reason) {
+ super.onResume(reason);
+ mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
+ mView.resetState();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
+
+ // dismiss the dialog.
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.dismiss();
+ mSimUnlockProgressDialog = null;
+ }
+ }
+
+ @Override
+ protected void verifyPasswordAndUnlock() {
+ String entry = mPasswordEntry.getText();
+
+ if (entry.length() < 4) {
+ // otherwise, display a message to the user, and don't submit.
+ mMessageAreaController.setMessage(
+ com.android.systemui.R.string.kg_invalid_sim_pin_hint);
+ mView.resetPasswordText(true /* animate */, true /* announce */);
+ mKeyguardSecurityCallback.userActivity();
+ return;
+ }
+
+ getSimUnlockProgressDialog().show();
+
+ if (mCheckSimPinThread == null) {
+ mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText(), mSubId) {
+ @Override
+ void onSimCheckResponse(final PinResult result) {
+ mView.post(() -> {
+ mRemainingAttempts = result.getAttemptsRemaining();
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
+ mView.resetPasswordText(true /* animate */,
+ /* announce */
+ result.getType() != PinResult.PIN_RESULT_TYPE_SUCCESS);
+ if (result.getType() == PinResult.PIN_RESULT_TYPE_SUCCESS) {
+ mKeyguardUpdateMonitor.reportSimUnlocked(mSubId);
+ mRemainingAttempts = -1;
+ mShowDefaultMessage = true;
+ mKeyguardSecurityCallback.dismiss(
+ true, KeyguardUpdateMonitor.getCurrentUser());
+ } else {
+ mShowDefaultMessage = false;
+ if (result.getType() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
+ if (result.getAttemptsRemaining() <= 2) {
+ // this is getting critical - show dialog
+ getSimRemainingAttemptsDialog(
+ result.getAttemptsRemaining()).show();
+ } else {
+ // show message
+ mMessageAreaController.setMessage(
+ getPinPasswordErrorMessage(
+ result.getAttemptsRemaining(), false));
+ }
+ } else {
+ // "PIN operation failed!" - no idea what this was and no way to
+ // find out. :/
+ mMessageAreaController.setMessage(mView.getResources().getString(
+ R.string.kg_password_pin_failed));
+ }
+ if (DEBUG) {
+ Log.d(LOG_TAG, "verifyPasswordAndUnlock "
+ + " CheckSimPin.onSimCheckResponse: " + result
+ + " attemptsRemaining=" + result.getAttemptsRemaining());
+ }
+ }
+ mKeyguardSecurityCallback.userActivity();
+ mCheckSimPinThread = null;
+ });
+ }
+ };
+ mCheckSimPinThread.start();
+ }
+ }
+
+ private Dialog getSimUnlockProgressDialog() {
+ if (mSimUnlockProgressDialog == null) {
+ mSimUnlockProgressDialog = new ProgressDialog(mView.getContext());
+ mSimUnlockProgressDialog.setMessage(
+ mView.getResources().getString(R.string.kg_sim_unlock_progress_dialog_message));
+ mSimUnlockProgressDialog.setIndeterminate(true);
+ mSimUnlockProgressDialog.setCancelable(false);
+ mSimUnlockProgressDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ }
+ return mSimUnlockProgressDialog;
+ }
+
+
+ private Dialog getSimRemainingAttemptsDialog(int remaining) {
+ String msg = getPinPasswordErrorMessage(remaining, false);
+ if (mRemainingAttemptsDialog == null) {
+ Builder builder = new AlertDialog.Builder(mView.getContext());
+ builder.setMessage(msg);
+ builder.setCancelable(false);
+ builder.setNeutralButton(R.string.ok, null);
+ mRemainingAttemptsDialog = builder.create();
+ mRemainingAttemptsDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ } else {
+ mRemainingAttemptsDialog.setMessage(msg);
+ }
+ return mRemainingAttemptsDialog;
+ }
+
+
+ private String getPinPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
+ String displayMessage;
+ int msgId;
+ if (attemptsRemaining == 0) {
+ displayMessage = mView.getResources().getString(
+ R.string.kg_password_wrong_pin_code_pukked);
+ } else if (attemptsRemaining > 0) {
+ msgId = isDefault ? R.plurals.kg_password_default_pin_message :
+ R.plurals.kg_password_wrong_pin_code;
+ displayMessage = mView.getResources()
+ .getQuantityString(msgId, attemptsRemaining, attemptsRemaining);
+ } else {
+ msgId = isDefault ? R.string.kg_sim_pin_instructions : R.string.kg_password_pin_failed;
+ displayMessage = mView.getResources().getString(msgId);
+ }
+ if (KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId)) {
+ displayMessage = mView.getResources()
+ .getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
+ }
+ if (DEBUG) {
+ Log.d(LOG_TAG, "getPinPasswordErrorMessage: attemptsRemaining="
+ + attemptsRemaining + " displayMessage=" + displayMessage);
+ }
+ return displayMessage;
+ }
+
+ private void showDefaultMessage() {
+ setLockedSimMessage();
+ if (mRemainingAttempts >= 0) {
+ return;
+ }
+
+ // Sending empty PIN here to query the number of remaining PIN attempts
+ new CheckSimPin("", mSubId) {
+ void onSimCheckResponse(final PinResult result) {
+ Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result "
+ + result.toString());
+ if (result.getAttemptsRemaining() >= 0) {
+ mRemainingAttempts = result.getAttemptsRemaining();
+ setLockedSimMessage();
+ }
+ }
+ }.start();
+ }
+
+ /**
+ * Since the IPC can block, we want to run the request in a separate thread
+ * with a callback.
+ */
+ private abstract class CheckSimPin extends Thread {
+ private final String mPin;
+ private int mSubId;
+
+ protected CheckSimPin(String pin, int subId) {
+ mPin = pin;
+ mSubId = subId;
+ }
+
+ abstract void onSimCheckResponse(@NonNull PinResult result);
+
+ @Override
+ public void run() {
+ if (DEBUG) {
+ Log.v(TAG, "call supplyPinReportResultForSubscriber(subid=" + mSubId + ")");
+ }
+ TelephonyManager telephonyManager =
+ mTelephonyManager.createForSubscriptionId(mSubId);
+ final PinResult result = telephonyManager.supplyPinReportPinResult(mPin);
+ if (result == null) {
+ Log.e(TAG, "Error result for supplyPinReportResult.");
+ mView.post(() -> onSimCheckResponse(PinResult.getDefaultFailedResult()));
+ } else {
+ if (DEBUG) {
+ Log.v(TAG, "supplyPinReportResult returned: " + result.toString());
+ }
+ mView.post(() -> onSimCheckResponse(result));
+ }
+ }
+ }
+
+ private void setLockedSimMessage() {
+ boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId);
+ int count = 1;
+ if (mTelephonyManager != null) {
+ count = mTelephonyManager.getActiveModemCount();
+ }
+ Resources rez = mView.getResources();
+ String msg;
+ TypedArray array = mView.getContext().obtainStyledAttributes(
+ new int[] { R.attr.wallpaperTextColor });
+ int color = array.getColor(0, Color.WHITE);
+ array.recycle();
+ if (count < 2) {
+ msg = rez.getString(R.string.kg_sim_pin_instructions);
+ } else {
+ SubscriptionInfo info = mKeyguardUpdateMonitor.getSubscriptionInfoForSubId(mSubId);
+ CharSequence displayName = info != null ? info.getDisplayName() : ""; // don't crash
+ msg = rez.getString(R.string.kg_sim_pin_instructions_multi, displayName);
+ if (info != null) {
+ color = info.getIconTint();
+ }
+ }
+ if (isEsimLocked) {
+ msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
+ }
+
+ if (mView.getVisibility() == View.VISIBLE) {
+ mMessageAreaController.setMessage(msg);
+ }
+ mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+ }
+
+ private void handleSubInfoChangeIfNeeded() {
+ int subId = mKeyguardUpdateMonitor
+ .getNextSubIdForState(TelephonyManager.SIM_STATE_PIN_REQUIRED);
+ if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
+ mSubId = subId;
+ mShowDefaultMessage = true;
+ mRemainingAttempts = -1;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 5148dd709026..932d9b966fa3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -16,27 +16,11 @@
package com.android.keyguard;
-import android.annotation.NonNull;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.telephony.PinResult;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.ImageView;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -44,47 +28,10 @@ import com.android.systemui.R;
* Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
*/
public class KeyguardSimPukView extends KeyguardPinBasedInputView {
- private static final String LOG_TAG = "KeyguardSimPukView";
private static final boolean DEBUG = KeyguardConstants.DEBUG;
public static final String TAG = "KeyguardSimPukView";
private ProgressDialog mSimUnlockProgressDialog = null;
- private CheckSimPuk mCheckSimPukThread;
-
- // Below flag is set to true during power-up or when a new SIM card inserted on device.
- // When this is true and when SIM card is PUK locked state, on PIN lock screen, message would
- // be displayed to inform user about the number of remaining PUK attempts left.
- private boolean mShowDefaultMessage = true;
- private int mRemainingAttempts = -1;
- private String mPukText;
- private String mPinText;
- private StateMachine mStateMachine = new StateMachine();
- private AlertDialog mRemainingAttemptsDialog;
- private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private ImageView mSimImageView;
-
- KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
- @Override
- public void onSimStateChanged(int subId, int slotId, int simState) {
- if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
- switch(simState) {
- // If the SIM is unlocked via a key sequence through the emergency dialer, it will
- // move into the READY state and the PUK lock keyguard should be removed.
- case TelephonyManager.SIM_STATE_READY: {
- mRemainingAttempts = -1;
- mShowDefaultMessage = true;
- // mCallback can be null if onSimStateChanged callback is called when keyguard
- // isn't active.
- if (mCallback != null) {
- mCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
- }
- break;
- }
- default:
- resetState();
- }
- }
- };
public KeyguardSimPukView(Context context) {
this(context, null);
@@ -94,136 +41,14 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
super(context, attrs);
}
- private class StateMachine {
- final int ENTER_PUK = 0;
- final int ENTER_PIN = 1;
- final int CONFIRM_PIN = 2;
- final int DONE = 3;
- private int state = ENTER_PUK;
-
- public void next() {
- int msg = 0;
- if (state == ENTER_PUK) {
- if (checkPuk()) {
- state = ENTER_PIN;
- msg = R.string.kg_puk_enter_pin_hint;
- } else {
- msg = R.string.kg_invalid_sim_puk_hint;
- }
- } else if (state == ENTER_PIN) {
- if (checkPin()) {
- state = CONFIRM_PIN;
- msg = R.string.kg_enter_confirm_pin_hint;
- } else {
- msg = R.string.kg_invalid_sim_pin_hint;
- }
- } else if (state == CONFIRM_PIN) {
- if (confirmPin()) {
- state = DONE;
- msg = R.string.keyguard_sim_unlock_progress_dialog_message;
- updateSim();
- } else {
- state = ENTER_PIN; // try again?
- msg = R.string.kg_invalid_confirm_pin_hint;
- }
- }
- resetPasswordText(true /* animate */, true /* announce */);
- if (msg != 0) {
- mSecurityMessageDisplay.setMessage(msg);
- }
- }
-
-
- void reset() {
- mPinText="";
- mPukText="";
- state = ENTER_PUK;
- handleSubInfoChangeIfNeeded();
- if (mShowDefaultMessage) {
- showDefaultMessage();
- }
- boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
-
- KeyguardEsimArea esimButton = findViewById(R.id.keyguard_esim_area);
- esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE);
- mPasswordEntry.requestFocus();
- }
-
-
- }
-
- private void showDefaultMessage() {
- if (mRemainingAttempts >= 0) {
- mSecurityMessageDisplay.setMessage(getPukPasswordErrorMessage(
- mRemainingAttempts, true));
- return;
- }
-
- boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = 1;
- TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- if (telephonyManager != null) {
- count = telephonyManager.getActiveModemCount();
- }
- Resources rez = getResources();
- String msg;
- TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
- int color = array.getColor(0, Color.WHITE);
- array.recycle();
- if (count < 2) {
- msg = rez.getString(R.string.kg_puk_enter_puk_hint);
- } else {
- SubscriptionInfo info = Dependency.get(KeyguardUpdateMonitor.class)
- .getSubscriptionInfoForSubId(mSubId);
- CharSequence displayName = info != null ? info.getDisplayName() : "";
- msg = rez.getString(R.string.kg_puk_enter_puk_hint_multi, displayName);
- if (info != null) {
- color = info.getIconTint();
- }
- }
- if (isEsimLocked) {
- msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
- }
- if (mSecurityMessageDisplay != null) {
- mSecurityMessageDisplay.setMessage(msg);
- }
- mSimImageView.setImageTintList(ColorStateList.valueOf(color));
-
- // Sending empty PUK here to query the number of remaining PIN attempts
- new CheckSimPuk("", "", mSubId) {
- void onSimLockChangedResponse(final PinResult result) {
- if (result == null) Log.e(LOG_TAG, "onSimCheckResponse, pin result is NULL");
- else {
- Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result "
- + result.toString());
- if (result.getAttemptsRemaining() >= 0) {
- mRemainingAttempts = result.getAttemptsRemaining();
- mSecurityMessageDisplay.setMessage(
- getPukPasswordErrorMessage(result.getAttemptsRemaining(), true));
- }
- }
- }
- }.start();
- }
-
- private void handleSubInfoChangeIfNeeded() {
- KeyguardUpdateMonitor monitor = Dependency.get(KeyguardUpdateMonitor.class);
- int subId = monitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PUK_REQUIRED);
- if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
- mSubId = subId;
- mShowDefaultMessage = true;
- mRemainingAttempts = -1;
- }
- }
-
@Override
protected int getPromptReasonStringRes(int reason) {
// No message on SIM Puk
return 0;
}
- private String getPukPasswordErrorMessage(int attemptsRemaining, boolean isDefault) {
+ String getPukPasswordErrorMessage(
+ int attemptsRemaining, boolean isDefault, boolean isEsimLocked) {
String displayMessage;
if (attemptsRemaining == 0) {
@@ -238,28 +63,19 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
R.string.kg_password_puk_failed;
displayMessage = getContext().getString(msgId);
}
- if (KeyguardEsimArea.isEsimLocked(mContext, mSubId)) {
+ if (isEsimLocked) {
displayMessage = getResources()
.getString(R.string.kg_sim_lock_esim_instructions, displayMessage);
}
- if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:"
- + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
+ if (DEBUG) {
+ Log.d(TAG, "getPukPasswordErrorMessage:"
+ + " attemptsRemaining=" + attemptsRemaining
+ + " displayMessage=" + displayMessage);
+ }
return displayMessage;
}
@Override
- public void resetState() {
- super.resetState();
- mStateMachine.reset();
- }
-
- @Override
- protected boolean shouldLockout(long deadline) {
- // SIM PUK doesn't have a timed lockout
- return false;
- }
-
- @Override
protected int getPasswordTextViewId() {
return R.id.pukEntry;
}
@@ -271,20 +87,6 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
if (mEcaView instanceof EmergencyCarrierArea) {
((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true);
}
- mSimImageView = findViewById(R.id.keyguard_sim);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateMonitorCallback);
- resetState();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mUpdateMonitorCallback);
}
@Override
@@ -300,168 +102,8 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
}
}
- /**
- * Since the IPC can block, we want to run the request in a separate thread
- * with a callback.
- */
- private abstract class CheckSimPuk extends Thread {
-
- private final String mPin, mPuk;
- private final int mSubId;
-
- protected CheckSimPuk(String puk, String pin, int subId) {
- mPuk = puk;
- mPin = pin;
- mSubId = subId;
- }
-
- abstract void onSimLockChangedResponse(@NonNull PinResult result);
-
- @Override
- public void run() {
- if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
- TelephonyManager telephonyManager =
- ((TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE))
- .createForSubscriptionId(mSubId);
- final PinResult result = telephonyManager.supplyPukReportPinResult(mPuk, mPin);
- if (result == null) {
- Log.e(TAG, "Error result for supplyPukReportResult.");
- post(new Runnable() {
- @Override
- public void run() {
- onSimLockChangedResponse(PinResult.getDefaultFailedResult());
- }
- });
- } else {
- if (DEBUG) {
- Log.v(TAG, "supplyPukReportResult returned: " + result.toString());
- }
- post(new Runnable() {
- @Override
- public void run() {
- onSimLockChangedResponse(result);
- }
- });
- }
- }
- }
-
- private Dialog getSimUnlockProgressDialog() {
- if (mSimUnlockProgressDialog == null) {
- mSimUnlockProgressDialog = new ProgressDialog(mContext);
- mSimUnlockProgressDialog.setMessage(
- mContext.getString(R.string.kg_sim_unlock_progress_dialog_message));
- mSimUnlockProgressDialog.setIndeterminate(true);
- mSimUnlockProgressDialog.setCancelable(false);
- if (!(mContext instanceof Activity)) {
- mSimUnlockProgressDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- }
- }
- return mSimUnlockProgressDialog;
- }
-
- private Dialog getPukRemainingAttemptsDialog(int remaining) {
- String msg = getPukPasswordErrorMessage(remaining, false);
- if (mRemainingAttemptsDialog == null) {
- AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
- builder.setMessage(msg);
- builder.setCancelable(false);
- builder.setNeutralButton(R.string.ok, null);
- mRemainingAttemptsDialog = builder.create();
- mRemainingAttemptsDialog.getWindow().setType(
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- } else {
- mRemainingAttemptsDialog.setMessage(msg);
- }
- return mRemainingAttemptsDialog;
- }
-
- private boolean checkPuk() {
- // make sure the puk is at least 8 digits long.
- if (mPasswordEntry.getText().length() == 8) {
- mPukText = mPasswordEntry.getText();
- return true;
- }
- return false;
- }
-
- private boolean checkPin() {
- // make sure the PIN is between 4 and 8 digits
- int length = mPasswordEntry.getText().length();
- if (length >= 4 && length <= 8) {
- mPinText = mPasswordEntry.getText();
- return true;
- }
- return false;
- }
-
- public boolean confirmPin() {
- return mPinText.equals(mPasswordEntry.getText());
- }
-
- private void updateSim() {
- getSimUnlockProgressDialog().show();
-
- if (mCheckSimPukThread == null) {
- mCheckSimPukThread = new CheckSimPuk(mPukText, mPinText, mSubId) {
- @Override
- void onSimLockChangedResponse(final PinResult result) {
- post(new Runnable() {
- @Override
- public void run() {
- if (mSimUnlockProgressDialog != null) {
- mSimUnlockProgressDialog.hide();
- }
- resetPasswordText(true /* animate */,
- /* announce */
- result.getType() != PinResult.PIN_RESULT_TYPE_SUCCESS);
- if (result.getType() == PinResult.PIN_RESULT_TYPE_SUCCESS) {
- Dependency.get(KeyguardUpdateMonitor.class)
- .reportSimUnlocked(mSubId);
- mRemainingAttempts = -1;
- mShowDefaultMessage = true;
- if (mCallback != null) {
- mCallback.dismiss(true,
- KeyguardUpdateMonitor.getCurrentUser());
- }
- } else {
- mShowDefaultMessage = false;
- if (result.getType() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
- // show message
- mSecurityMessageDisplay.setMessage(getPukPasswordErrorMessage(
- result.getAttemptsRemaining(), false));
- if (result.getAttemptsRemaining() <= 2) {
- // this is getting critical - show dialog
- getPukRemainingAttemptsDialog(
- result.getAttemptsRemaining()).show();
- } else {
- // show message
- mSecurityMessageDisplay.setMessage(
- getPukPasswordErrorMessage(
- result.getAttemptsRemaining(), false));
- }
- } else {
- mSecurityMessageDisplay.setMessage(getContext().getString(
- R.string.kg_password_puk_failed));
- }
- if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock "
- + " UpdateSim.onSimCheckResponse: "
- + " attemptsRemaining=" + result.getAttemptsRemaining());
- }
- mStateMachine.reset();
- mCheckSimPukThread = null;
- }
- });
- }
- };
- mCheckSimPukThread.start();
- }
- }
-
@Override
- protected void verifyPasswordAndUnlock() {
- mStateMachine.next();
+ public void onResume(int reason) {
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
new file mode 100644
index 000000000000..9b2166b04415
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
@@ -0,0 +1,404 @@
+/*
+ * 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.annotation.NonNull;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.telephony.PinResult;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+
+public class KeyguardSimPukViewController
+ extends KeyguardPinBasedInputViewController<KeyguardSimPukView> {
+ private static final boolean DEBUG = KeyguardConstants.DEBUG;
+ public static final String TAG = "KeyguardSimPukView";
+
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final TelephonyManager mTelephonyManager;
+
+ private String mPukText;
+ private String mPinText;
+ private int mRemainingAttempts;
+ // Below flag is set to true during power-up or when a new SIM card inserted on device.
+ // When this is true and when SIM card is PUK locked state, on PIN lock screen, message would
+ // be displayed to inform user about the number of remaining PUK attempts left.
+ private boolean mShowDefaultMessage;
+ private StateMachine mStateMachine = new StateMachine();
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private CheckSimPuk mCheckSimPukThread;
+ private ProgressDialog mSimUnlockProgressDialog;
+
+ KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onSimStateChanged(int subId, int slotId, int simState) {
+ if (DEBUG) Log.v(TAG, "onSimStateChanged(subId=" + subId + ",state=" + simState + ")");
+ // If the SIM is unlocked via a key sequence through the emergency dialer, it will
+ // move into the READY state and the PUK lock keyguard should be removed.
+ if (simState == TelephonyManager.SIM_STATE_READY) {
+ mRemainingAttempts = -1;
+ mShowDefaultMessage = true;
+ mKeyguardSecurityCallback.dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
+ } else {
+ resetState();
+ }
+ }
+ };
+ private ImageView mSimImageView;
+ private AlertDialog mRemainingAttemptsDialog;
+
+ protected KeyguardSimPukViewController(KeyguardSimPukView view,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ SecurityMode securityMode, LockPatternUtils lockPatternUtils,
+ KeyguardSecurityCallback keyguardSecurityCallback,
+ KeyguardMessageAreaController.Factory messageAreaControllerFactory,
+ LatencyTracker latencyTracker,
+ LiftToActivateListener liftToActivateListener,
+ TelephonyManager telephonyManager) {
+ super(view, keyguardUpdateMonitor, securityMode, lockPatternUtils, keyguardSecurityCallback,
+ messageAreaControllerFactory, latencyTracker, liftToActivateListener);
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mTelephonyManager = telephonyManager;
+ mSimImageView = mView.findViewById(R.id.keyguard_sim);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ super.onViewAttached();
+ mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ super.onViewDetached();
+ mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
+ }
+
+ @Override
+ void resetState() {
+ super.resetState();
+ mStateMachine.reset();
+ }
+
+ @Override
+ protected void verifyPasswordAndUnlock() {
+ mStateMachine.next();
+ }
+
+ private class StateMachine {
+ static final int ENTER_PUK = 0;
+ static final int ENTER_PIN = 1;
+ static final int CONFIRM_PIN = 2;
+ static final int DONE = 3;
+
+ private int mState = ENTER_PUK;
+
+ public void next() {
+ int msg = 0;
+ if (mState == ENTER_PUK) {
+ if (checkPuk()) {
+ mState = ENTER_PIN;
+ msg = com.android.systemui.R.string.kg_puk_enter_pin_hint;
+ } else {
+ msg = com.android.systemui.R.string.kg_invalid_sim_puk_hint;
+ }
+ } else if (mState == ENTER_PIN) {
+ if (checkPin()) {
+ mState = CONFIRM_PIN;
+ msg = com.android.systemui.R.string.kg_enter_confirm_pin_hint;
+ } else {
+ msg = com.android.systemui.R.string.kg_invalid_sim_pin_hint;
+ }
+ } else if (mState == CONFIRM_PIN) {
+ if (confirmPin()) {
+ mState = DONE;
+ msg = com.android.systemui.R.string.keyguard_sim_unlock_progress_dialog_message;
+ updateSim();
+ } else {
+ mState = ENTER_PIN; // try again?
+ msg = com.android.systemui.R.string.kg_invalid_confirm_pin_hint;
+ }
+ }
+ mView.resetPasswordText(true /* animate */, true /* announce */);
+ if (msg != 0) {
+ mMessageAreaController.setMessage(msg);
+ }
+ }
+
+
+ void reset() {
+ mPinText = "";
+ mPukText = "";
+ mState = ENTER_PUK;
+ handleSubInfoChangeIfNeeded();
+ if (mShowDefaultMessage) {
+ showDefaultMessage();
+ }
+ boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId);
+
+ KeyguardEsimArea esimButton = mView.findViewById(R.id.keyguard_esim_area);
+ esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE);
+ mPasswordEntry.requestFocus();
+ }
+ }
+
+ private void showDefaultMessage() {
+ if (mRemainingAttempts >= 0) {
+ mMessageAreaController.setMessage(mView.getPukPasswordErrorMessage(
+ mRemainingAttempts, true,
+ KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId)));
+ return;
+ }
+
+ boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId);
+ int count = 1;
+ if (mTelephonyManager != null) {
+ count = mTelephonyManager.getActiveModemCount();
+ }
+ Resources rez = mView.getResources();
+ String msg;
+ TypedArray array = mView.getContext().obtainStyledAttributes(
+ new int[] { R.attr.wallpaperTextColor });
+ int color = array.getColor(0, Color.WHITE);
+ array.recycle();
+ if (count < 2) {
+ msg = rez.getString(R.string.kg_puk_enter_puk_hint);
+ } else {
+ SubscriptionInfo info = Dependency.get(KeyguardUpdateMonitor.class)
+ .getSubscriptionInfoForSubId(mSubId);
+ CharSequence displayName = info != null ? info.getDisplayName() : "";
+ msg = rez.getString(R.string.kg_puk_enter_puk_hint_multi, displayName);
+ if (info != null) {
+ color = info.getIconTint();
+ }
+ }
+ if (isEsimLocked) {
+ msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
+ }
+ mMessageAreaController.setMessage(msg);
+ mSimImageView.setImageTintList(ColorStateList.valueOf(color));
+
+ // Sending empty PUK here to query the number of remaining PIN attempts
+ new CheckSimPuk("", "", mSubId) {
+ void onSimLockChangedResponse(final PinResult result) {
+ if (result == null) Log.e(TAG, "onSimCheckResponse, pin result is NULL");
+ else {
+ Log.d(TAG, "onSimCheckResponse " + " empty One result "
+ + result.toString());
+ if (result.getAttemptsRemaining() >= 0) {
+ mRemainingAttempts = result.getAttemptsRemaining();
+ mMessageAreaController.setMessage(
+ mView.getPukPasswordErrorMessage(
+ result.getAttemptsRemaining(), true,
+ KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId)));
+ }
+ }
+ }
+ }.start();
+ }
+
+ private boolean checkPuk() {
+ // make sure the puk is at least 8 digits long.
+ if (mPasswordEntry.getText().length() == 8) {
+ mPukText = mPasswordEntry.getText();
+ return true;
+ }
+ return false;
+ }
+
+ private boolean checkPin() {
+ // make sure the PIN is between 4 and 8 digits
+ int length = mPasswordEntry.getText().length();
+ if (length >= 4 && length <= 8) {
+ mPinText = mPasswordEntry.getText();
+ return true;
+ }
+ return false;
+ }
+
+ public boolean confirmPin() {
+ return mPinText.equals(mPasswordEntry.getText());
+ }
+
+
+
+
+ private void updateSim() {
+ getSimUnlockProgressDialog().show();
+
+ if (mCheckSimPukThread == null) {
+ mCheckSimPukThread = new CheckSimPuk(mPukText, mPinText, mSubId) {
+ @Override
+ void onSimLockChangedResponse(final PinResult result) {
+ mView.post(() -> {
+ if (mSimUnlockProgressDialog != null) {
+ mSimUnlockProgressDialog.hide();
+ }
+ mView.resetPasswordText(true /* animate */,
+ /* announce */
+ result.getType() != PinResult.PIN_RESULT_TYPE_SUCCESS);
+ if (result.getType() == PinResult.PIN_RESULT_TYPE_SUCCESS) {
+ mKeyguardUpdateMonitor.reportSimUnlocked(mSubId);
+ mRemainingAttempts = -1;
+ mShowDefaultMessage = true;
+
+ mKeyguardSecurityCallback.dismiss(
+ true, KeyguardUpdateMonitor.getCurrentUser());
+ } else {
+ mShowDefaultMessage = false;
+ if (result.getType() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
+ // show message
+ mMessageAreaController.setMessage(mView.getPukPasswordErrorMessage(
+ result.getAttemptsRemaining(), false,
+ KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId)));
+ if (result.getAttemptsRemaining() <= 2) {
+ // this is getting critical - show dialog
+ getPukRemainingAttemptsDialog(
+ result.getAttemptsRemaining()).show();
+ } else {
+ // show message
+ mMessageAreaController.setMessage(
+ mView.getPukPasswordErrorMessage(
+ result.getAttemptsRemaining(), false,
+ KeyguardEsimArea.isEsimLocked(
+ mView.getContext(), mSubId)));
+ }
+ } else {
+ mMessageAreaController.setMessage(mView.getResources().getString(
+ R.string.kg_password_puk_failed));
+ }
+ if (DEBUG) {
+ Log.d(TAG, "verifyPasswordAndUnlock "
+ + " UpdateSim.onSimCheckResponse: "
+ + " attemptsRemaining=" + result.getAttemptsRemaining());
+ }
+ }
+ mStateMachine.reset();
+ mCheckSimPukThread = null;
+ });
+ }
+ };
+ mCheckSimPukThread.start();
+ }
+ }
+
+ @Override
+ protected boolean shouldLockout(long deadline) {
+ // SIM PUK doesn't have a timed lockout
+ return false;
+ }
+
+ private Dialog getSimUnlockProgressDialog() {
+ if (mSimUnlockProgressDialog == null) {
+ mSimUnlockProgressDialog = new ProgressDialog(mView.getContext());
+ mSimUnlockProgressDialog.setMessage(
+ mView.getResources().getString(R.string.kg_sim_unlock_progress_dialog_message));
+ mSimUnlockProgressDialog.setIndeterminate(true);
+ mSimUnlockProgressDialog.setCancelable(false);
+ if (!(mView.getContext() instanceof Activity)) {
+ mSimUnlockProgressDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ }
+ }
+ return mSimUnlockProgressDialog;
+ }
+
+ private void handleSubInfoChangeIfNeeded() {
+ int subId = mKeyguardUpdateMonitor.getNextSubIdForState(
+ TelephonyManager.SIM_STATE_PUK_REQUIRED);
+ if (subId != mSubId && SubscriptionManager.isValidSubscriptionId(subId)) {
+ mSubId = subId;
+ mShowDefaultMessage = true;
+ mRemainingAttempts = -1;
+ }
+ }
+
+
+ private Dialog getPukRemainingAttemptsDialog(int remaining) {
+ String msg = mView.getPukPasswordErrorMessage(remaining, false,
+ KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId));
+ if (mRemainingAttemptsDialog == null) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(mView.getContext());
+ builder.setMessage(msg);
+ builder.setCancelable(false);
+ builder.setNeutralButton(R.string.ok, null);
+ mRemainingAttemptsDialog = builder.create();
+ mRemainingAttemptsDialog.getWindow().setType(
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ } else {
+ mRemainingAttemptsDialog.setMessage(msg);
+ }
+ return mRemainingAttemptsDialog;
+ }
+
+ /**
+ * Since the IPC can block, we want to run the request in a separate thread
+ * with a callback.
+ */
+ private abstract class CheckSimPuk extends Thread {
+
+ private final String mPin, mPuk;
+ private final int mSubId;
+
+ protected CheckSimPuk(String puk, String pin, int subId) {
+ mPuk = puk;
+ mPin = pin;
+ mSubId = subId;
+ }
+
+ abstract void onSimLockChangedResponse(@NonNull PinResult result);
+
+ @Override
+ public void run() {
+ if (DEBUG) Log.v(TAG, "call supplyPukReportResult()");
+ TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
+ final PinResult result = telephonyManager.supplyPukReportPinResult(mPuk, mPin);
+ if (result == null) {
+ Log.e(TAG, "Error result for supplyPukReportResult.");
+ mView.post(() -> onSimLockChangedResponse(PinResult.getDefaultFailedResult()));
+ } else {
+ if (DEBUG) {
+ Log.v(TAG, "supplyPukReportResult returned: " + result.toString());
+ }
+ mView.post(new Runnable() {
+ @Override
+ public void run() {
+ onSimLockChangedResponse(result);
+ }
+ });
+ }
+ }
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/LiftToActivateListener.java b/packages/SystemUI/src/com/android/keyguard/LiftToActivateListener.java
index e59602b1cfff..425e50ed6397 100644
--- a/packages/SystemUI/src/com/android/keyguard/LiftToActivateListener.java
+++ b/packages/SystemUI/src/com/android/keyguard/LiftToActivateListener.java
@@ -16,11 +16,12 @@
package com.android.keyguard;
-import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
+import javax.inject.Inject;
+
/**
* Hover listener that implements lift-to-activate interaction for
* accessibility. May be added to multiple views.
@@ -31,9 +32,9 @@ class LiftToActivateListener implements View.OnHoverListener {
private boolean mCachedClickableState;
- public LiftToActivateListener(Context context) {
- mAccessibilityManager = (AccessibilityManager) context.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
+ @Inject
+ LiftToActivateListener(AccessibilityManager accessibilityManager) {
+ mAccessibilityManager = accessibilityManager;
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index b0457fce6a1a..2205fdd4267d 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -26,6 +26,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
@@ -90,7 +91,8 @@ public class NumPadKey extends ViewGroup {
}
setOnClickListener(mListener);
- setOnHoverListener(new LiftToActivateListener(context));
+ setOnHoverListener(new LiftToActivateListener(
+ (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE)));
mLockPatternUtils = new LockPatternUtils(context);
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index b35579d3624b..79925bad3cc7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -62,6 +62,7 @@ import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
+import android.view.inputmethod.InputMethodManager;
import com.android.internal.app.IBatteryStats;
import com.android.internal.statusbar.IStatusBarService;
@@ -183,6 +184,12 @@ public class FrameworkServicesModule {
@Provides
@Singleton
+ static InputMethodManager provideInputMethodManager(Context context) {
+ return context.getSystemService(InputMethodManager.class);
+ }
+
+ @Provides
+ @Singleton
static IPackageManager provideIPackageManager() {
return IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/ViewController.java b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
index 64f8dbbb9e34..f30472f75d29 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
@@ -23,7 +23,20 @@ import android.view.View.OnAttachStateChangeListener;
* Utility class that handles view lifecycle events for View Controllers.
*
* Implementations should handle setup and teardown related activities inside of
- * {@link #onViewAttached()} and {@link #onViewDetached()}.
+ * {@link #onViewAttached()} and {@link #onViewDetached()}. Be sure to call {@link #init()} on
+ * any child controllers that this uses. This can be done in {@link init()} if the controllers
+ * are injected, or right after creation time of the child controller.
+ *
+ * Tip: View "attachment" happens top down - parents are notified that they are attached before
+ * any children. That means that if you call a method on a child controller in
+ * {@link #onViewAttached()}, the child controller may not have had its onViewAttach method
+ * called, so it may not be fully set up.
+ *
+ * As such, make sure that methods on your controller are safe to call _before_ its {@link #init()}
+ * and {@link #onViewAttached()} methods are called. Specifically, if your controller must call
+ * {@link View#findViewById(int)} on its root view to setup member variables, do so in its
+ * constructor. Save {@link #onViewAttached()} for things that can happen post-construction - adding
+ * listeners, dynamically changing content, or other runtime decisions.
*
* @param <T> View class that this ViewController is for.
*/
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
new file mode 100644
index 000000000000..2d6ecb6f877e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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 static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.KeyEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.LatencyTracker;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
+
+ @Mock
+ private KeyguardAbsKeyInputView mAbsKeyInputView;
+ @Mock
+ private PasswordTextView mPasswordEntry;
+ @Mock
+ private KeyguardMessageArea mKeyguardMessageArea;
+ @Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private SecurityMode mSecurityMode;
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ @Mock
+ private KeyguardSecurityCallback mKeyguardSecurityCallback;
+ @Mock
+ private KeyguardMessageAreaController.Factory mKeyguardMessageAreaControllerFactory;
+ @Mock
+ private KeyguardMessageAreaController mKeyguardMessageAreaController;
+ @Mock
+ private LatencyTracker mLatencyTracker;
+
+ private KeyguardAbsKeyInputViewController mKeyguardAbsKeyInputViewController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
+ .thenReturn(mKeyguardMessageAreaController);
+ when(mAbsKeyInputView.getPasswordTextViewId()).thenReturn(1);
+ when(mAbsKeyInputView.findViewById(1)).thenReturn(mPasswordEntry);
+ when(mAbsKeyInputView.isAttachedToWindow()).thenReturn(true);
+ when(mAbsKeyInputView.findViewById(R.id.keyguard_message_area))
+ .thenReturn(mKeyguardMessageArea);
+ mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
+ mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
+ mKeyguardMessageAreaControllerFactory, mLatencyTracker) {
+ @Override
+ void resetState() {
+ }
+
+ @Override
+ public void onResume(int reason) {
+ super.onResume(reason);
+ }
+ };
+ mKeyguardAbsKeyInputViewController.init();
+ }
+
+ @Test
+ public void onKeyDown_clearsSecurityMessage() {
+ ArgumentCaptor<KeyDownListener> onKeyDownListenerArgumentCaptor =
+ ArgumentCaptor.forClass(KeyDownListener.class);
+ verify(mAbsKeyInputView).setKeyDownListener(onKeyDownListenerArgumentCaptor.capture());
+ onKeyDownListenerArgumentCaptor.getValue().onKeyDown(
+ KeyEvent.KEYCODE_0, mock(KeyEvent.class));
+ verify(mKeyguardSecurityCallback).userActivity();
+ verify(mKeyguardMessageAreaController).setMessage(eq(""));
+ }
+
+ @Test
+ public void onKeyDown_noSecurityMessageInteraction() {
+ ArgumentCaptor<KeyDownListener> onKeyDownListenerArgumentCaptor =
+ ArgumentCaptor.forClass(KeyDownListener.class);
+ verify(mAbsKeyInputView).setKeyDownListener(onKeyDownListenerArgumentCaptor.capture());
+ onKeyDownListenerArgumentCaptor.getValue().onKeyDown(
+ KeyEvent.KEYCODE_UNKNOWN, mock(KeyEvent.class));
+ verifyZeroInteractions(mKeyguardSecurityCallback);
+ verifyZeroInteractions(mKeyguardMessageAreaController);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
new file mode 100644
index 000000000000..4944284698a0
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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 static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+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.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase {
+
+ @Mock
+ private KeyguardPinBasedInputView mPinBasedInputView;
+ @Mock
+ private PasswordTextView mPasswordEntry;
+ @Mock
+ private KeyguardMessageArea mKeyguardMessageArea;
+ @Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private SecurityMode mSecurityMode;
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ @Mock
+ private KeyguardSecurityCallback mKeyguardSecurityCallback;
+ @Mock
+ private KeyguardMessageAreaController.Factory mKeyguardMessageAreaControllerFactory;
+ @Mock
+ private KeyguardMessageAreaController mKeyguardMessageAreaController;
+ @Mock
+ private LatencyTracker mLatencyTracker;
+ @Mock
+ private LiftToActivateListener mLiftToactivateListener;
+ @Mock
+ private View mDeleteButton;
+ @Mock
+ private View mOkButton;
+
+ private KeyguardPinBasedInputViewController mKeyguardPinViewController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
+ .thenReturn(mKeyguardMessageAreaController);
+ when(mPinBasedInputView.getPasswordTextViewId()).thenReturn(1);
+ when(mPinBasedInputView.findViewById(1)).thenReturn(mPasswordEntry);
+ when(mPinBasedInputView.isAttachedToWindow()).thenReturn(true);
+ when(mPinBasedInputView.findViewById(R.id.keyguard_message_area))
+ .thenReturn(mKeyguardMessageArea);
+ when(mPinBasedInputView.findViewById(R.id.delete_button))
+ .thenReturn(mDeleteButton);
+ when(mPinBasedInputView.findViewById(R.id.key_enter))
+ .thenReturn(mOkButton);
+ mKeyguardPinViewController = new KeyguardPinBasedInputViewController(mPinBasedInputView,
+ mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
+ mKeyguardMessageAreaControllerFactory, mLatencyTracker, mLiftToactivateListener) {
+ @Override
+ public void onResume(int reason) {
+ super.onResume(reason);
+ }
+ };
+ mKeyguardPinViewController.init();
+ }
+
+ @Test
+ public void onResume_requestsFocus() {
+ mKeyguardPinViewController.onResume(KeyguardSecurityView.SCREEN_ON);
+ verify(mPasswordEntry).requestFocus();
+ }
+}
+
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
deleted file mode 100644
index 6666a926c68b..000000000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2018 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 static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public class KeyguardPinBasedInputViewTest extends SysuiTestCase {
-
- @Mock
- private PasswordTextView mPasswordEntry;
- @Mock
- private SecurityMessageDisplay mSecurityMessageDisplay;
- @InjectMocks
- private KeyguardPinBasedInputView mKeyguardPinView;
-
- @Before
- public void setup() {
- LayoutInflater inflater = LayoutInflater.from(getContext());
- mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
- mKeyguardPinView =
- (KeyguardPinBasedInputView) inflater.inflate(R.layout.keyguard_pin_view, null);
- MockitoAnnotations.initMocks(this);
- }
-
- @Test
- public void onResume_requestsFocus() {
- mKeyguardPinView.onResume(KeyguardSecurityView.SCREEN_ON);
- verify(mPasswordEntry).requestFocus();
- }
-
- @Test
- public void onKeyDown_clearsSecurityMessage() {
- mKeyguardPinView.onKeyDown(KeyEvent.KEYCODE_0, mock(KeyEvent.class));
- verify(mSecurityMessageDisplay).setMessage(eq(""));
- }
-
- @Test
- public void onKeyDown_noSecurityMessageInteraction() {
- mKeyguardPinView.onKeyDown(KeyEvent.KEYCODE_UNKNOWN, mock(KeyEvent.class));
- verifyZeroInteractions(mSecurityMessageDisplay);
- }
-}