diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e82ad1ec24d41..490eab87f75c5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -97,6 +97,13 @@ the SIM card. --> Your SIM card is PUK-locked. Type the PUK code to unlock it. Type PUK2 to unblock SIM card. + + Unsuccessful, enable SIM/RUIM Lock. + + + You have %d remaining attempt before SIM is locked. + You have %d remaining attempts before SIM is locked. + IMEI diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index dc0841ab1041d..a5573c98f17b9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -612,6 +612,7 @@ + @@ -965,6 +966,7 @@ + diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml index abc4483705bda..4738049f99848 100644 --- a/packages/Keyguard/res/values/strings.xml +++ b/packages/Keyguard/res/values/strings.xml @@ -24,12 +24,12 @@ - Type PUK and new PIN code + Type SIM PUK and new PIN code - PUK code + SIM PUK code - New PIN code + New SIM PIN code Touch to type password @@ -249,8 +249,6 @@ Confirm desired PIN code Unlocking SIM card\u2026 - - Incorrect PIN code. Type a PIN that is 4 to 8 numbers. @@ -333,6 +331,34 @@ Remove + + Incorrect SIM PIN code you must now contact your carrier to unlock your device. + + + Incorrect SIM PIN code, you have %d remaining attempt before you must contact your carrier to unlock your device. + Incorrect SIM PIN code, you have %d remaining attempts. + + + + SIM is unusable. Contact your carrier. + + + Incorrect SIM PUK code, you have %d remaining attempt before SIM becomes permanently unusable. + Incorrect SIM PUK code, you have %d remaining attempts before SIM becomes permanently unusable. + + + SIM PIN operation failed! + + SIM PUK operation failed! + + Code Accepted! + Previous track button diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java index 50594073d2b7b..e39622a54c66d 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java @@ -17,11 +17,16 @@ package com.android.keyguard; import com.android.internal.telephony.ITelephony; +import com.android.internal.telephony.PhoneConstants; import android.content.Context; +import android.content.DialogInterface; import android.app.Activity; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.ProgressDialog; +import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; import android.text.Editable; @@ -30,6 +35,7 @@ import android.text.TextWatcher; import android.text.method.DigitsKeyListener; import android.util.AttributeSet; import android.view.View; +import android.util.Log; import android.view.WindowManager; import android.widget.TextView.OnEditorActionListener; @@ -38,10 +44,14 @@ import android.widget.TextView.OnEditorActionListener; */ public class KeyguardSimPinView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { + private static final String LOG_TAG = "KeyguardSimPinView"; + private static final boolean DEBUG = KeyguardViewMediator.DEBUG; private ProgressDialog mSimUnlockProgressDialog = null; private volatile boolean mSimCheckInProgress; + private AlertDialog mRemainingAttemptsDialog; + public KeyguardSimPinView(Context context) { this(context, null); } @@ -55,6 +65,23 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView mPasswordEntry.setEnabled(true); } + private String getPinPasswordErrorMessage(int attemptsRemaining) { + String displayMessage; + + if (attemptsRemaining == 0) { + displayMessage = getContext().getString(R.string.kg_password_wrong_pin_code_pukked); + } else if (attemptsRemaining > 0) { + displayMessage = getContext().getResources() + .getQuantityString(R.plurals.kg_password_wrong_pin_code, attemptsRemaining, + attemptsRemaining); + } else { + displayMessage = getContext().getString(R.string.kg_password_pin_failed); + } + 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 @@ -109,6 +136,8 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView | InputType.TYPE_NUMBER_VARIATION_PASSWORD); mPasswordEntry.requestFocus(); + + mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default } @Override @@ -135,22 +164,22 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView mPin = pin; } - abstract void onSimCheckResponse(boolean success); + abstract void onSimCheckResponse(final int result, final int attemptsRemaining); @Override public void run() { try { - final boolean result = ITelephony.Stub.asInterface(ServiceManager - .checkService("phone")).supplyPin(mPin); + final int[] result = ITelephony.Stub.asInterface(ServiceManager + .checkService("phone")).supplyPinReportResult(mPin); post(new Runnable() { public void run() { - onSimCheckResponse(result); + onSimCheckResponse(result[0], result[1]); } }); } catch (RemoteException e) { post(new Runnable() { public void run() { - onSimCheckResponse(false); + onSimCheckResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1); } }); } @@ -164,14 +193,28 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView 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); - } + mSimUnlockProgressDialog.getWindow().setType( + WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); } return mSimUnlockProgressDialog; } + private Dialog getSimRemainingAttemptsDialog(int remaining) { + String msg = getPinPasswordErrorMessage(remaining); + 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().toString(); @@ -189,20 +232,34 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView if (!mSimCheckInProgress) { mSimCheckInProgress = true; // there should be only one new CheckSimPin(mPasswordEntry.getText().toString()) { - void onSimCheckResponse(final boolean success) { + void onSimCheckResponse(final int result, final int attemptsRemaining) { post(new Runnable() { public void run() { if (mSimUnlockProgressDialog != null) { mSimUnlockProgressDialog.hide(); } - if (success) { - // before closing the keyguard, report back that the sim is unlocked - // so it knows right away. + if (result == PhoneConstants.PIN_RESULT_SUCCESS) { KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(); mCallback.dismiss(true); } else { - mSecurityMessageDisplay.setMessage - (R.string.kg_password_wrong_pin_code, true); + if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) { + if (attemptsRemaining <= 2) { + // this is getting critical - show dialog + getSimRemainingAttemptsDialog(attemptsRemaining).show(); + } else { + // show message + mSecurityMessageDisplay.setMessage( + getPinPasswordErrorMessage(attemptsRemaining), true); + } + } 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), true); + } + if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock " + + " CheckSimPin.onSimCheckResponse: " + result + + " attemptsRemaining=" + attemptsRemaining); mPasswordEntry.setText(""); } mCallback.userActivity(0); diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java index 2ae4cc7ba6538..31518a1e31f8c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java @@ -16,10 +16,10 @@ package com.android.keyguard; -import com.android.internal.telephony.ITelephony; - import android.content.Context; +import android.animation.AnimatorSet.Builder; import android.app.Activity; +import android.app.AlertDialog; import android.app.Dialog; import android.app.ProgressDialog; import android.os.RemoteException; @@ -29,21 +29,29 @@ import android.text.InputType; import android.text.TextWatcher; import android.text.method.DigitsKeyListener; import android.util.AttributeSet; +import android.util.Log; import android.view.View; import android.view.WindowManager; import android.widget.TextView.OnEditorActionListener; +import com.android.internal.telephony.ITelephony; +import com.android.internal.telephony.PhoneConstants; + + /** * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier. */ public class KeyguardSimPukView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { + private static final String LOG_TAG = "KeyguardSimPukView"; + private static final boolean DEBUG = KeyguardViewMediator.DEBUG; private ProgressDialog mSimUnlockProgressDialog = null; private volatile boolean mCheckInProgress; private String mPukText; private String mPinText; private StateMachine mStateMachine = new StateMachine(); + private AlertDialog mRemainingAttemptsDialog; private class StateMachine { final int ENTER_PUK = 0; @@ -93,6 +101,23 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView } } + private String getPukPasswordErrorMessage(int attemptsRemaining) { + String displayMessage; + + if (attemptsRemaining == 0) { + displayMessage = getContext().getString(R.string.kg_password_wrong_puk_code_dead); + } else if (attemptsRemaining > 0) { + displayMessage = getContext().getResources() + .getQuantityString(R.plurals.kg_password_wrong_puk_code, attemptsRemaining, + attemptsRemaining); + } else { + displayMessage = getContext().getString(R.string.kg_password_puk_failed); + } + if (DEBUG) Log.d(LOG_TAG, "getPukPasswordErrorMessage:" + + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage); + return displayMessage; + } + public KeyguardSimPukView(Context context) { this(context, null); } @@ -190,23 +215,23 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView mPin = pin; } - abstract void onSimLockChangedResponse(boolean success); + abstract void onSimLockChangedResponse(final int result, final int attemptsRemaining); @Override public void run() { try { - final boolean result = ITelephony.Stub.asInterface(ServiceManager - .checkService("phone")).supplyPuk(mPuk, mPin); + final int[] result = ITelephony.Stub.asInterface(ServiceManager + .checkService("phone")).supplyPukReportResult(mPuk, mPin); post(new Runnable() { public void run() { - onSimLockChangedResponse(result); + onSimLockChangedResponse(result[0], result[1]); } }); } catch (RemoteException e) { post(new Runnable() { public void run() { - onSimLockChangedResponse(false); + onSimLockChangedResponse(PhoneConstants.PIN_GENERAL_FAILURE, -1); } }); } @@ -228,6 +253,22 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView return mSimUnlockProgressDialog; } + private Dialog getPukRemainingAttemptsDialog(int remaining) { + String msg = getPukPasswordErrorMessage(remaining); + 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) { @@ -257,17 +298,33 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView if (!mCheckInProgress) { mCheckInProgress = true; new CheckSimPuk(mPukText, mPinText) { - void onSimLockChangedResponse(final boolean success) { + void onSimLockChangedResponse(final int result, final int attemptsRemaining) { post(new Runnable() { public void run() { if (mSimUnlockProgressDialog != null) { mSimUnlockProgressDialog.hide(); } - if (success) { + if (result == PhoneConstants.PIN_RESULT_SUCCESS) { + KeyguardUpdateMonitor.getInstance(getContext()).reportSimUnlocked(); mCallback.dismiss(true); } else { + if (result == PhoneConstants.PIN_PASSWORD_INCORRECT) { + if (attemptsRemaining <= 2) { + // this is getting critical - show dialog + getPukRemainingAttemptsDialog(attemptsRemaining).show(); + } else { + // show message + mSecurityMessageDisplay.setMessage( + getPukPasswordErrorMessage(attemptsRemaining), true); + } + } else { + mSecurityMessageDisplay.setMessage(getContext().getString( + R.string.kg_password_puk_failed), true); + } + if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock " + + " UpdateSim.onSimCheckResponse: " + + " attemptsRemaining=" + attemptsRemaining); mStateMachine.reset(); - mSecurityMessageDisplay.setMessage(R.string.kg_invalid_puk, true); } mCheckInProgress = false; } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 584411b83db7a..7bd2c8412e979 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -154,6 +154,26 @@ interface ITelephony { */ boolean supplyPuk(String puk, String pin); + /** + * Supply a pin to unlock the SIM. Blocks until a result is determined. + * Returns a specific success/error code. + * @param pin The pin to check. + * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code + * retValue[1] = number of attempts remaining if known otherwise -1 + */ + int[] supplyPinReportResult(String pin); + + /** + * Supply puk to unlock the SIM and set SIM pin to new pin. + * Blocks until a result is determined. + * Returns a specific success/error code + * @param puk The puk to check + * pin The pin to check. + * @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code + * retValue[1] = number of attempts remaining if known otherwise -1 + */ + int[] supplyPukReportResult(String puk, String pin); + /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated * without SEND (so dial is not appropriate). diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index 4a4a62b9640d8..416325591352b 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -85,6 +85,14 @@ public class PhoneConstants { public static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged"; + /** + * Return codes for supplyPinReturnResult and + * supplyPukReturnResult APIs + */ + public static final int PIN_RESULT_SUCCESS = 0; + public static final int PIN_PASSWORD_INCORRECT = 1; + public static final int PIN_GENERAL_FAILURE = 2; + /** * Return codes for enableApnType() */