/*
* Copyright (C) 2008 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.settings;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.widget.Toast;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
import com.android.internal.telephony.ITelephony;
import android.os.ServiceManager;
import android.os.RemoteException;
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
import android.util.Log;
/**
* Implements the preference screen to enable/disable ICC lock and
* also the dialogs to change the ICC PIN. In the former case, enabling/disabling
* the ICC lock will prompt the user for the current PIN.
* In the Change PIN case, it prompts the user for old pin, new pin and new pin
* again before attempting to change it. Calls the SimCard interface to execute
* these operations.
*
*/
public class IccLockSettings extends PreferenceActivity
implements EditPinPreference.OnPinEnteredListener {
private static final int OFF_MODE = 0;
// State when enabling/disabling ICC lock
private static final int ICC_LOCK_MODE = 1;
// State when entering the old pin
private static final int ICC_OLD_MODE = 2;
// State when entering the new pin - first time
private static final int ICC_NEW_MODE = 3;
// State when entering the new pin - second time
private static final int ICC_REENTER_MODE = 4;
// Keys in xml file
private static final String PIN_DIALOG = "sim_pin";
private static final String PIN_TOGGLE = "sim_toggle";
// Keys in icicle
private static final String DIALOG_STATE = "dialogState";
private static final String DIALOG_PIN = "dialogPin";
private static final String DIALOG_ERROR = "dialogError";
private static final String ENABLE_TO_STATE = "enableState";
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
private static final String SAVED_OLD_PIN = "savedOldPin";
private static final String SAVED_NEW_PIN = "savedNewPin";
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
private static final int MIN_PIN_LENGTH = 4;
private static final int MAX_PIN_LENGTH = 8;
// Which dialog to show next when popped up
private int mDialogState = OFF_MODE;
private String mPin;
private String mOldPin;
private String mNewPin;
private String mError;
// Are we trying to enable or disable ICC lock?
private boolean mToState;
private Phone mPhone;
private EditPinPreference mPinDialog;
private CheckBoxPreference mPinToggle;
private Resources mRes;
// For async handler to identify request type
private static final int ENABLE_ICC_PIN_COMPLETE = 100;
private static final int CHANGE_ICC_PIN_COMPLETE = 101;
// For replies from IccCard interface
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
AsyncResult ar = (AsyncResult) msg.obj;
switch (msg.what) {
case ENABLE_ICC_PIN_COMPLETE:
iccLockChanged(ar.exception == null);
break;
case CHANGE_ICC_PIN_COMPLETE:
iccPinChanged(ar.exception == null);
break;
}
return;
}
};
// For top-level settings screen to query
static boolean isIccLockEnabled() {
return PhoneFactory.getDefaultPhone().getIccCard().getIccLockEnabled();
}
static String getSummary(Context context) {
Resources res = context.getResources();
String summary = isIccLockEnabled()
? res.getString(R.string.sim_lock_on)
: res.getString(R.string.sim_lock_off);
return summary;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Utils.isMonkeyRunning()) {
finish();
return;
}
addPreferencesFromResource(R.xml.sim_lock_settings);
mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
mPinToggle = (CheckBoxPreference) findPreference(PIN_TOGGLE);
if (savedInstanceState != null && savedInstanceState.containsKey(DIALOG_STATE)) {
mDialogState = savedInstanceState.getInt(DIALOG_STATE);
mPin = savedInstanceState.getString(DIALOG_PIN);
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
mOldPin = savedInstanceState.getString(SAVED_OLD_PIN);
mNewPin = savedInstanceState.getString(SAVED_NEW_PIN);
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
mError = savedInstanceState.getString(DIALOG_ERROR);
mToState = savedInstanceState.getBoolean(ENABLE_TO_STATE);
}
mPinDialog.setOnPinEnteredListener(this);
// Don't need any changes to be remembered
getPreferenceScreen().setPersistent(false);
mPhone = PhoneFactory.getDefaultPhone();
mRes = getResources();
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
int attemptsRemaining = -1;
try {
attemptsRemaining = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")).getIccPin1RetryCount();
} catch (RemoteException ex) {
attemptsRemaining = -1;
}
if (attemptsRemaining == 0)
{
mPinToggle.setEnabled(false);
}
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
}
@Override
protected void onResume() {
super.onResume();
mPinToggle.setChecked(mPhone.getIccCard().getIccLockEnabled());
if (mDialogState != OFF_MODE) {
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
if (!mPinDialog.isDialogOpen())
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
showPinDialog();
} else {
// Prep for standard click on "Change PIN"
resetDialogState();
}
}
@Override
protected void onSaveInstanceState(Bundle out) {
// Need to store this state for slider open/close
// There is one case where the dialog is popped up by the preference
// framework. In that case, let the preference framework store the
// dialog state. In other cases, where this activity manually launches
// the dialog, store the state of the dialog.
if (mPinDialog.isDialogOpen()) {
out.putInt(DIALOG_STATE, mDialogState);
out.putString(DIALOG_PIN, mPinDialog.getEditText().getText().toString());
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
out.putString(SAVED_OLD_PIN, mOldPin);
out.putString(SAVED_NEW_PIN, mNewPin);
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
out.putString(DIALOG_ERROR, mError);
out.putBoolean(ENABLE_TO_STATE, mToState);
} else {
super.onSaveInstanceState(out);
}
}
private void showPinDialog() {
if (mDialogState == OFF_MODE) {
return;
}
setDialogValues();
mPinDialog.showPinDialog();
}
private void setDialogValues() {
mPinDialog.setText(mPin);
String message = "";
switch (mDialogState) {
case ICC_LOCK_MODE:
message = mRes.getString(R.string.sim_enter_pin);
mPinDialog.setDialogTitle(mToState
? mRes.getString(R.string.sim_enable_sim_lock)
: mRes.getString(R.string.sim_disable_sim_lock));
break;
case ICC_OLD_MODE:
message = mRes.getString(R.string.sim_enter_old);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
case ICC_NEW_MODE:
message = mRes.getString(R.string.sim_enter_new);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
case ICC_REENTER_MODE:
message = mRes.getString(R.string.sim_reenter_new);
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
break;
}
if (mError != null) {
message = mError + "\n" + message;
mError = null;
}
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
if ((mDialogState == ICC_LOCK_MODE) || (mDialogState == ICC_OLD_MODE))
{
int attemptsRemaining = -1;
try {
attemptsRemaining = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")).getIccPin1RetryCount();
} catch (RemoteException ex) {
attemptsRemaining = -1;
}
mPinDialog.setDialogMessage(message + "\n" + getText(com.lge.internal.R.string.STR_TITLETEXT_UICC_REMAINING_COMMON_SHORT) + attemptsRemaining);
Log.d("IccLockSetting","show pin popup1 remaining :" + attemptsRemaining);
}
else
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
mPinDialog.setDialogMessage(message);
}
public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
if (!positiveResult) {
resetDialogState();
return;
}
mPin = preference.getText();
if (!reasonablePin(mPin)) {
// inject error message and display dialog again
mError = mRes.getString(R.string.sim_bad_pin);
showPinDialog();
return;
}
switch (mDialogState) {
case ICC_LOCK_MODE:
tryChangeIccLockState();
break;
case ICC_OLD_MODE:
mOldPin = mPin;
mDialogState = ICC_NEW_MODE;
mError = null;
mPin = null;
showPinDialog();
break;
case ICC_NEW_MODE:
mNewPin = mPin;
mDialogState = ICC_REENTER_MODE;
mPin = null;
showPinDialog();
break;
case ICC_REENTER_MODE:
if (!mPin.equals(mNewPin)) {
mError = mRes.getString(R.string.sim_pins_dont_match);
mDialogState = ICC_NEW_MODE;
mPin = null;
showPinDialog();
} else {
mError = null;
tryChangePin();
}
break;
}
}
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
resetDialogState();
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text Matches> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
if (preference == mPinToggle) {
// Get the new, preferred state
mToState = mPinToggle.isChecked();
// Flip it back and pop up pin dialog
mPinToggle.setChecked(!mToState);
mDialogState = ICC_LOCK_MODE;
showPinDialog();
} else if (preference == mPinDialog) {
mDialogState = ICC_OLD_MODE;
return false;
}
return true;
}
private void tryChangeIccLockState() {
// Try to change icc lock. If it succeeds, toggle the lock state and
// reset dialog state. Else inject error message and show dialog again.
Message callback = Message.obtain(mHandler, ENABLE_ICC_PIN_COMPLETE);
mPhone.getIccCard().setIccLockEnabled(mToState, mPin, callback);
}
private void iccLockChanged(boolean success) {
if (success) {
mPinToggle.setChecked(mToState);
} else {
Toast.makeText(this, mRes.getString(R.string.sim_lock_failed), Toast.LENGTH_SHORT)
.show();
}
resetDialogState();
}
private void iccPinChanged(boolean success) {
if (!success) {
Toast.makeText(this, mRes.getString(R.string.sim_change_failed),
Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(this, mRes.getString(R.string.sim_change_succeeded),
Toast.LENGTH_SHORT)
.show();
}
resetDialogState();
}
private void tryChangePin() {
Message callback = Message.obtain(mHandler, CHANGE_ICC_PIN_COMPLETE);
mPhone.getIccCard().changeIccLockPassword(mOldPin,
mNewPin, callback);
}
private boolean reasonablePin(String pin) {
if (pin == null || pin.length() < MIN_PIN_LENGTH || pin.length() > MAX_PIN_LENGTH) {
return false;
} else {
return true;
}
}
private void resetDialogState() {
mError = null;
mDialogState = ICC_OLD_MODE; // Default for when Change PIN is clicked
mPin = "";
//[Start][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [START_LGE]
mOldPin = "";
mNewPin = "";
// 20100507 euikuk.jeong@lge.com Porting LGE patch <Add retry count text> from Aloha [END_LGE]
//[End][2010-10-19]jinseok.choi@lge.com, for PUK UnBlock Screen, Remaining Counter, Merge from P970
setDialogValues();
mDialogState = OFF_MODE;
}
}