/*
* 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.phone;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.view.WindowManager;
import android.widget.Toast;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ITelephony;
/**
* FDN settings UI for the Phone app.
* Rewritten to look and behave closer to the other preferences.
*/
public class FdnSetting extends PreferenceActivity
implements EditPinPreference.OnPinEnteredListener, DialogInterface.OnCancelListener {
static final String LogTag = "FdnSetting";
private Phone mPhone;
/**
* Events we handle.
* The first is used for toggling FDN enable, the second for the PIN change.
*/
private static final int EVENT_PIN2_ENTRY_COMPLETE = 100;
private static final int EVENT_PIN2_CHANGE_COMPLETE = 200;
// String keys for preference lookup
// We only care about the pin preferences here, the manage FDN contacts
// Preference is handled solely in xml.
private static final String BUTTON_FDN_ENABLE_KEY = "button_fdn_enable_key";
private static final String BUTTON_CHANGE_PIN2_KEY = "button_change_pin2_key";
private static final String BUTTON_FDN_LIST_KEY = "button_fdn_list_key";
private EditPinPreference mButtonEnableFDN;
private EditPinPreference mButtonChangePin2;
private Preference mButtonFDNList;
// State variables
private String mOldPin;
private String mNewPin;
private static final int PIN_CHANGE_OLD = 0;
private static final int PIN_CHANGE_NEW = 1;
private static final int PIN_CHANGE_REENTER = 2;
private static final int PIN_CHANGE_PUK = 3;
private int mPinChangeState;
private boolean mSkipOldPin; // Indicates we know that we are PUK2 blocked.
private static final String SKIP_OLD_PIN_KEY = "skip_old_pin_key";
private static final String PIN_CHANGE_STATE_KEY = "pin_change_state_key";
private static final String OLD_PIN_KEY = "old_pin_key";
private static final String NEW_PIN_KEY = "new_pin_key";
private static final String DIALOG_MESSAGE_KEY = "dialog_message_key";
private static final String DIALOG_PIN_ENTRY_KEY = "dialog_pin_entry_key";
// size limits for the pin.
private static final int MIN_PIN_LENGTH = 4;
private static final int MAX_PIN_LENGTH = 8;
//PIN2 Remain times Add start ----jesse----
private TelephonyManager mTelePhoneManager;
private int remainTimesPIN2;
private int remainTimesPUK2;
//PIN2 Remain times Add end
private int mSubId = 0;
/**
* Delegate to the respective handlers.
*/
public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
Log.e(LogTag, "onPinEntered");
if (preference == mButtonEnableFDN) {
toggleFDNEnable(positiveResult);
} else if (preference == mButtonChangePin2){
updatePINChangeState(positiveResult);
}
}
/**
* Attempt to toggle FDN activation.
*/
private void toggleFDNEnable(boolean positiveResult) {
Log.e(LogTag, "toggleFDNEnable");
if (!positiveResult) {
return;
}
// validate the pin first, before submitting it to the RIL for FDN enable.
String password = mButtonEnableFDN.getText();
if (validatePin (password, false)) {
// get the relevant data for the icc call
boolean isEnabled = mPhone.getIccCard().getIccFdnEnabled();
Message onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_ENTRY_COMPLETE);
// make fdn request
mPhone.getIccCard().setIccFdnEnabled(!isEnabled, password, onComplete);
} else {
// throw up error if the pin is invalid.
displayMessage(R.string.invalidPin2);
}
mButtonEnableFDN.setText("");
}
/**
* Attempt to change the pin.
*/
private void updatePINChangeState(boolean positiveResult) {
if (!positiveResult) {
// reset the state on cancel, either to expect PUK2 or PIN2
if (!mSkipOldPin) {
resetPinChangeState();
} else {
resetPinChangeStateForPUK2();
}
return;
}
// Progress through the dialog states, generally in this order:
// 1. Enter old pin
// 2. Enter new pin
// 3. Re-Enter new pin
// While handling any error conditions that may show up in between.
// Also handle the PUK2 entry, if it is requested.
//
// In general, if any invalid entries are made, the dialog re-
// appears with text to indicate what the issue is.
switch (mPinChangeState) {
case PIN_CHANGE_OLD:
mOldPin = mButtonChangePin2.getText();
Log.e(LogTag, "updatePINChangeState PIN_CHANGE_OLD:" + mOldPin);
mButtonChangePin2.setText("");
// if the pin is not valid, display a message and reset the state.
if (validatePin (mOldPin, false)) {
mPinChangeState = PIN_CHANGE_NEW;
displayPinChangeDialog();
} else {
displayPinChangeDialog(R.string.invalidPin2, true);
}
break;
case PIN_CHANGE_NEW:
mNewPin = mButtonChangePin2.getText();
Log.e(LogTag, "updatePINChangeState PIN_CHANGE_NEW:" + mNewPin);
mButtonChangePin2.setText("");
// if the new pin is not valid, display a message and reset the state.
if (validatePin (mNewPin, false)) {
mPinChangeState = PIN_CHANGE_REENTER;
displayPinChangeDialog();
} else {
displayPinChangeDialog(R.string.invalidPin2, true);
}
break;
case PIN_CHANGE_REENTER:
Log.e(LogTag, "updatePINChangeState PIN_CHANGE_REENTER");
// if the re-entered pin is not valid, display a message and reset the state.
if (!mNewPin.equals(mButtonChangePin2.getText())) {
mPinChangeState = PIN_CHANGE_NEW;
mButtonChangePin2.setText("");
displayPinChangeDialog(R.string.mismatchPin2, true);
} else {
// If the PIN is valid, then we either submit the change PIN request or
// display the PUK2 dialog if we KNOW that we're PUK2 locked.
mButtonChangePin2.setText("");
if (!mSkipOldPin) {
Message onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_CHANGE_COMPLETE);
mPhone.getIccCard().changeIccFdnPassword(mOldPin, mNewPin, onComplete);
} else {
mPinChangeState = PIN_CHANGE_PUK;
displayPinChangeDialog();
}
}
break;
case PIN_CHANGE_PUK: {
// Doh! too many incorrect requests, PUK requested.
// if the pin is not valid, display a message and reset the state.
String puk2 = mButtonChangePin2.getText();
Log.e(LogTag, "updatePINChangeState PIN_CHANGE_PUK:" + puk2 + " mNewPin:" + mNewPin);
mButtonChangePin2.setText("");
// make sure that the puk is valid before submitting it.
if (validatePin (puk2, true)) {
Message onComplete = mFDNHandler.obtainMessage(EVENT_PIN2_CHANGE_COMPLETE);
mPhone.getIccCard().supplyPuk2(puk2, mNewPin, onComplete);
} else {
displayPinChangeDialog(R.string.invalidPuk2, true);
}
}
break;
}
}
/**
* Handler for asynchronous replies from the sim.
*/
private Handler mFDNHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
// when we are enabling FDN, either we are unsuccessful and display
// a toast, or just update the UI.
case EVENT_PIN2_ENTRY_COMPLETE: {
Log.e(LogTag, "handleMessage EVENT_PIN2_ENTRY_COMPLETE");
AsyncResult ar = (AsyncResult) msg.obj;
if (ar.exception != null) {
// see if PUK2 is requested and alert the user accordingly.
CommandException ce = (CommandException) ar.exception;
Log.e(LogTag, "!!! " + ce.getCommandError());
if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
// make sure we set the PUK2 state so that we can skip
// some redundant behaviour.
displayMessage(R.string.fdn_enable_puk2_requested);
resetPinChangeStateForPUK2();
} else {
remainTimesPIN2--;
displayMessage(getString(R.string.pin2_invalid) + getString(R.string.promptWordOne)
+ remainTimesPIN2 + getString(R.string.promptWordTwo));
if(remainTimesPIN2 > 0){
resetPinChangeState();
} else {
resetPinChangeStateForPUK2();
}
}
}
updateSimInfo();
updateEnableFDN();
updateFDNList();
Intent intent = new Intent("android.intent.action.FDN_STATE_CHANGED"+ mPhone.getPhoneId());
intent.putExtra("phone_id", mPhone.getPhoneId());
intent.putExtra("fdn_status", mPhone.getIccCard().getIccFdnEnabled());
sendBroadcast(intent);
}
break;
// when changing the pin we need to pay attention to whether or not
// the error requests a PUK (usually after too many incorrect tries)
// Set the state accordingly.
case EVENT_PIN2_CHANGE_COMPLETE: {
Log.e(LogTag, "handleMessage EVENT_PIN2_CHANGE_COMPLETE");
AsyncResult ar = (AsyncResult) msg.obj;
if (ar.exception != null) {
CommandException ce = (CommandException) ar.exception;
Log.e(LogTag, "!!! " + ce.getCommandError());
if (ce.getCommandError() == CommandException.Error.SIM_PUK2) {
// throw an alert dialog on the screen, displaying the
// request for a PUK2. set the cancel listener to
// FdnSetting.onCancel().
AlertDialog a = new AlertDialog.Builder(FdnSetting.this)
.setMessage(R.string.puk2_requested)
.setCancelable(true)
.setOnCancelListener(FdnSetting.this)
.create();
a.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
a.show();
} else {
// set the correct error message depending upon the state.
if (mPinChangeState == PIN_CHANGE_PUK) {
remainTimesPUK2--;
displayMessage(getString(R.string.badPuk2) + getString(R.string.promptWordOne)
+ remainTimesPUK2 + getString(R.string.promptWordTwo));
} else {
remainTimesPIN2--;
displayMessage(R.string.badPin2);
if(remainTimesPIN2 == 0){
mSkipOldPin = true;
}
}
updateEnableFDN();
updateFDNList();
// Reset the state depending upon or knowledge of the PUK state.
if (!mSkipOldPin) {
resetPinChangeState();
} else {
resetPinChangeStateForPUK2();
}
}
} else {
// reset to normal behaviour on successful change.
displayMessage(R.string.pin2_changed);
mSkipOldPin = false;
updateSimInfo();
resetPinChangeState();
updateEnableFDN();
updateFDNList();
}
}
break;
}
}
};
/**
* Cancel listener for the PUK2 request alert dialog.
*/
public void onCancel(DialogInterface dialog) {
// set the state of the preference and then display the dialog.
Log.e(LogTag, "onCancel");
mPinChangeState = PIN_CHANGE_PUK;
displayPinChangeDialog(0, true);
}
/**
* Display a toast for message, like the rest of the settings.
*/
private final void displayMessage(int strId) {
Log.e(LogTag, "displayMessage:" + getString(strId));
Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT)
.show();
}
/**
* Display a toast for message, like the rest of the settings.
*/
private final void displayMessage(String str) {
Log.e(LogTag, "displayMessage:" + str);
Toast.makeText(this, str, Toast.LENGTH_SHORT)
.show();
}
/**
* The next two functions are for updating the message field on the dialog.
*/
private final void displayPinChangeDialog() {
displayPinChangeDialog(0, true);
}
private final void displayPinChangeDialog(int strId, boolean shouldDisplay) {
int msgId;
String dialogMessage;
Log.e(LogTag, "displayPinChangeDialog");
switch (mPinChangeState) {
case PIN_CHANGE_OLD:
msgId = R.string.oldPin2Label;
if (strId != 0) {
dialogMessage = getText(msgId) + "(" + getString(R.string.promptWordOne) + remainTimesPIN2
+ getString(R.string.promptWordTwo) + ")" + "\n" + getText(strId);
} else {
dialogMessage = getText(msgId) + "(" + getString(R.string.promptWordOne)
+ remainTimesPIN2 + getString(R.string.promptWordTwo) + ")";
}
break;
case PIN_CHANGE_NEW:
msgId = R.string.newPin2Label;
if (strId != 0) {
dialogMessage = getText(msgId) + "\n" + getText(strId);
} else {
dialogMessage = getText(msgId) + "";
}
break;
case PIN_CHANGE_REENTER:
msgId = R.string.confirmPin2Label;
if (strId != 0) {
dialogMessage = getText(msgId) + "\n" + getText(strId);
} else {
dialogMessage = getText(msgId) + "";
}
break;
case PIN_CHANGE_PUK:
default:
msgId = R.string.label_puk2_code;
if (strId != 0) {
dialogMessage = getText(msgId) + "(" + getString(R.string.promptWordOne) + remainTimesPUK2
+ getString(R.string.promptWordTwo) + ")" + "\n" + getText(strId);
} else {
dialogMessage = getText(msgId) + "(" + getString(R.string.promptWordOne)
+ remainTimesPUK2 + getString(R.string.promptWordTwo) + ")";
}
break;
}
Log.e(LogTag, "dialogMessage:" + dialogMessage);
mButtonChangePin2.setDialogMessage(dialogMessage);
// only display if requested.
if (shouldDisplay) {
mButtonChangePin2.showPinDialog();
}
}
/**
* Reset the state of the pin change dialog.
*/
private final void resetPinChangeState() {
Log.e(LogTag, "resetPinChangeState");
mPinChangeState = PIN_CHANGE_OLD;
mButtonChangePin2.setSummary(R.string.sum_fdn_change_pin);
displayPinChangeDialog(0, false);
mOldPin = mNewPin = "";
}
/**
* Reset the state of the pin change dialog solely for PUK2 use.
*/
private final void resetPinChangeStateForPUK2() {
Log.e(LogTag, "resetPinChangeStateForPUK2");
mPinChangeState = PIN_CHANGE_NEW;
mButtonChangePin2.setSummary(R.string.puk2_requested);
displayPinChangeDialog(0, false);
mOldPin = mNewPin = "";
mSkipOldPin = true;
}
/**
* Validate the pin entry.
*
* @param pin This is the pin to validate
* @param isPuk Boolean indicating whether we are to treat
* the pin input as a puk.
*/
private boolean validatePin(String pin, boolean isPUK) {
Log.e(LogTag, "validatePin");
// for pin, we have 4-8 numbers, or puk, we use only 8.
int pinMinimum = isPUK ? MAX_PIN_LENGTH : MIN_PIN_LENGTH;
// check validity
if (pin == null || pin.length() < pinMinimum || pin.length() > MAX_PIN_LENGTH) {
return false;
} else {
return true;
}
}
/**
* Reflect the updated FDN state in the UI.
*/
private void updateEnableFDN() {
//PIN2 Remain times Add start ----jesse----
if(remainTimesPIN2 == 0){
mButtonEnableFDN.setEnabled(false);
Log.e(LogTag, "updateEnableFDN Enable false");
} else {
mButtonEnableFDN.setEnabled(true);
String dialogMessage = getString(R.string.enter_pin2_text) + "(" + getString(R.string.promptWordOne)
+ remainTimesPIN2 + getString(R.string.promptWordTwo) + ")";
mButtonEnableFDN.setDialogMessage(dialogMessage);
Log.e(LogTag, "updateEnableFDN " + dialogMessage);
}
//PIN2 Remain times Add end
if (mPhone.getIccCard().getIccFdnEnabled()) {
Log.d(LogTag, "mPhone.getIccCard().getIccFdnEnabled()=true");
mButtonEnableFDN.setTitle(R.string.enable_fdn_ok);
mButtonEnableFDN.setSummary(R.string.fdn_enabled);
mButtonEnableFDN.setDialogTitle(R.string.disable_fdn);
} else {
Log.d(LogTag, "mPhone.getIccCard().getIccFdnEnabled()=false");
mButtonEnableFDN.setTitle(R.string.disable_fdn_ok);
mButtonEnableFDN.setSummary(R.string.fdn_disabled);
mButtonEnableFDN.setDialogTitle(R.string.enable_fdn);
}
//Lino modify for NEWMS00134894 begin 2011-10-28
if(remainTimesPUK2 <= 0){
mButtonChangePin2.setEnabled(false);
}
//Lino modify for NEWMS00134895 end 2011-10-28
}
/**
* Updated FDN List item state in the UI.
*/
private void updateFDNList() {
Log.e(LogTag, "updateFDNList");
if((remainTimesPIN2 == 0) || (!mPhone.getIccCard().getIccFdnEnabled())){
mButtonFDNList.setEnabled(false);
} else {
mButtonFDNList.setEnabled(true);
}
}
/**
* Update pin and puk remain times in sim.
*/
private void updateSimInfo() {
mTelePhoneManager = (TelephonyManager)getSystemService(PhoneFactory.getServiceName(Context.TELEPHONY_SERVICE, mSubId));
remainTimesPIN2 = mTelePhoneManager.getRemainTimes(TelephonyManager.UNLOCK_PIN2);
remainTimesPUK2 = mTelePhoneManager.getRemainTimes(TelephonyManager.UNLOCK_PUK2);
Log.e(LogTag, "updateSimInfo remainTimesPIN2:" + remainTimesPIN2 + " remainTimesPUK2:" + remainTimesPUK2);
}
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.fdn_setting);
mSubId = getIntent().getIntExtra(CallSettingOptions.SUB_ID, 0);
if (TelephonyManager.getPhoneCount() > 1) {
if(mSubId == 0) {
setTitle(getResources().getString(R.string.sim1) + getResources().getString(R.string.fdn));
}else if(mSubId == 1) {
setTitle(getResources().getString(R.string.sim2) + getResources().getString(R.string.fdn));
}
}
Log.e(LogTag, "onCreate");
// mPhone = PhoneFactory.getDefaultPhone();
//for ds
mPhone = PhoneApp.getInstance().getPhone(mSubId);
updateSimInfo();
//get UI object references
PreferenceScreen prefSet = getPreferenceScreen();
mButtonEnableFDN = (EditPinPreference) prefSet.findPreference(BUTTON_FDN_ENABLE_KEY);
mButtonChangePin2 = (EditPinPreference) prefSet.findPreference(BUTTON_CHANGE_PIN2_KEY);
mButtonFDNList = (Preference) prefSet.findPreference(BUTTON_FDN_LIST_KEY);
mButtonFDNList.getIntent().putExtra(CallSettingOptions.SUB_ID, mSubId);
//assign click listener and update state
mButtonEnableFDN.setOnPinEnteredListener(this);
updateEnableFDN();
mButtonChangePin2.setOnPinEnteredListener(this);
// Only reset the pin change dialog if we're not in the middle of changing it.
if (icicle == null) {
if(remainTimesPIN2 > 0){
resetPinChangeState();
} else {
resetPinChangeStateForPUK2();
}
} else {
mSkipOldPin = icicle.getBoolean(SKIP_OLD_PIN_KEY);
mPinChangeState = icicle.getInt(PIN_CHANGE_STATE_KEY);
mOldPin = icicle.getString(OLD_PIN_KEY);
mNewPin = icicle.getString(NEW_PIN_KEY);
mButtonChangePin2.setDialogMessage(icicle.getString(DIALOG_MESSAGE_KEY));
mButtonChangePin2.setText(icicle.getString(DIALOG_PIN_ENTRY_KEY));
Log.e(LogTag, "onCreate dialogMessage2:" + icicle.getString(DIALOG_MESSAGE_KEY));
}
updateFDNList();
}
@Override
protected void onResume() {
super.onResume();
Log.e(LogTag, "onResume");
// mPhone = PhoneFactory.getDefaultPhone();
mPhone = PhoneApp.getInstance().getPhone(mSubId);
updateEnableFDN();
}
//add by niezhong for NEWMS00154369 begin
@Override
protected void onRestart() {
super.onRestart();
updateSimInfo();
if(remainTimesPIN2 > 0){
resetPinChangeState();
} else {
resetPinChangeStateForPUK2();
}
updateEnableFDN();
updateFDNList();
}
//add by niezhong for NEWMS00154369 end
/**
* Save the state of the pin change.
*/
@Override
protected void onSaveInstanceState(Bundle out) {
super.onSaveInstanceState(out);
Log.e(LogTag, "onSaveInstanceState");
out.putBoolean(SKIP_OLD_PIN_KEY, mSkipOldPin);
out.putInt(PIN_CHANGE_STATE_KEY, mPinChangeState);
out.putString(OLD_PIN_KEY, mOldPin);
out.putString(NEW_PIN_KEY, mNewPin);
out.putString(DIALOG_MESSAGE_KEY, mButtonChangePin2.getDialogMessage().toString());
out.putString(DIALOG_PIN_ENTRY_KEY, mButtonChangePin2.getText());
}
}