Files
frameworks_base/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java
Dave Mankoff dc01930044 Revert^2 "7/N controllers for remaining Keyguard Password ..."
Revert submission 12656261-revert-12585643-b166448040-keyguard-message-area-NUUJOVRYJS

This also fixes the original issue introduced in this CL.
KeyguardAbsKeyInputViewController#reset would call mView#resetState
instead of its own internal resetState method. However, all the logic
from the various resetState methods had been moved from the views to
their controllers. Simply calling resetState direclty resolves the
issue (line 105 of KeyguardAbsKeyInputViewController).

Reason for revert: Fixing http://b/169231892 and http://b/169145796
Reverted Changes:
I7683b2234:Revert "4/N Setup Controller fo KeyguardSecurityCo...
I5cbe04c0c:Revert "5/N Add KeyguardSecurityViewFlipperControl...
I11dff38ad:Revert "6/N Add Controller for KeyguardPatternView...
I55c250121:Revert "7/N controllers for remaining Keyguard Pas...
Ie84234cb8:Revert "8/N Remove View Injection from KeyguardMes...
Ic62f199a5:Revert "9/N Clean Up Keyguard Class Structure"

Change-Id: Ie3669e0c9a23ffd4443ced0fb08ec754f1df55db
Fixes: 169145796
2020-09-24 11:04:51 -04:00

405 lines
16 KiB
Java

/*
* 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);
}
});
}
}
}
}