1 package com.android.phone; 2 3 import com.android.internal.telephony.CallForwardInfo; 4 import com.android.internal.telephony.CommandException; 5 import com.android.internal.telephony.CommandsInterface; 6 import com.android.internal.telephony.Phone; 7 import com.android.internal.telephony.PhoneFactory; 8 9 import android.app.AlertDialog; 10 import android.content.Context; 11 import android.content.DialogInterface; 12 import android.content.res.TypedArray; 13 import android.os.AsyncResult; 14 import android.os.Handler; 15 import android.os.Message; 16 import android.text.TextUtils; 17 import android.util.AttributeSet; 18 import android.util.Log; 19 20 import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR; 21 22 public class CallForwardEditPreference extends EditPhoneNumberPreference { 23 private static final String LOG_TAG = "CallForwardEditPreference"; 24 private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 2); 25 26 private static final String SRC_TAGS[] = {"{0}"}; 27 private CharSequence mSummaryOnTemplate; 28 private int mButtonClicked; 29 private int mServiceClass; 30 private MyHandler mHandler = new MyHandler(); 31 int reason; 32 Phone phone; 33 CallForwardInfo callForwardInfo; 34 TimeConsumingPreferenceListener tcpListener; 35 36 public CallForwardEditPreference(Context context, AttributeSet attrs) { 37 super(context, attrs); 38 39 phone = PhoneFactory.getDefaultPhone(); 40 mSummaryOnTemplate = this.getSummaryOn(); 41 42 TypedArray a = context.obtainStyledAttributes(attrs, 43 R.styleable.CallForwardEditPreference, 0, R.style.EditPhoneNumberPreference); 44 mServiceClass = a.getInt(R.styleable.CallForwardEditPreference_serviceClass, 45 CommandsInterface.SERVICE_CLASS_VOICE); 46 reason = a.getInt(R.styleable.CallForwardEditPreference_reason, 47 CommandsInterface.CF_REASON_UNCONDITIONAL); 48 a.recycle(); 49 50 if (DBG) Log.d(LOG_TAG, "mServiceClass=" + mServiceClass + ", reason=" + reason); 51 } 52 53 public CallForwardEditPreference(Context context) { 54 this(context, null); 55 } 56 57 void init(TimeConsumingPreferenceListener listener, boolean skipReading) { 58 tcpListener = listener; 59 if (!skipReading) { 60 phone.getCallForwardingOption(reason, 61 mHandler.obtainMessage(MyHandler.MESSAGE_GET_CF, 62 // unused in this case 63 CommandsInterface.CF_ACTION_DISABLE, 64 MyHandler.MESSAGE_GET_CF, null)); 65 if (tcpListener != null) { 66 tcpListener.onStarted(this, true); 67 } 68 } 69 } 70 71 @Override 72 public void onClick(DialogInterface dialog, int which) { 73 super.onClick(dialog, which); 74 mButtonClicked = which; 75 } 76 77 @Override 78 protected void onDialogClosed(boolean positiveResult) { 79 super.onDialogClosed(positiveResult); 80 81 if (DBG) Log.d(LOG_TAG, "mButtonClicked=" + mButtonClicked 82 + ", positiveResult=" + positiveResult); 83 if (this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) { 84 int action = (isToggled() || (mButtonClicked == DialogInterface.BUTTON_POSITIVE)) ? 85 CommandsInterface.CF_ACTION_REGISTRATION : 86 CommandsInterface.CF_ACTION_DISABLE; 87 int time = (reason != CommandsInterface.CF_REASON_NO_REPLY) ? 0 : 20; 88 final String number = getPhoneNumber(); 89 90 if (DBG) Log.d(LOG_TAG, "callForwardInfo=" + callForwardInfo); 91 92 if (action == CommandsInterface.CF_ACTION_REGISTRATION 93 && callForwardInfo != null 94 && callForwardInfo.status == 1 95 && number.equals(callForwardInfo.number)) { 96 // no change, do nothing 97 if (DBG) Log.d(LOG_TAG, "no change, do nothing"); 98 } else { 99 // set to network 100 if (DBG) Log.d(LOG_TAG, "reason=" + reason + ", action=" + action 101 + ", number=" + number); 102 103 // Display no forwarding number while we're waiting for 104 // confirmation 105 setSummaryOn(""); 106 107 // the interface of Phone.setCallForwardingOption has error: 108 // should be action, reason... 109 phone.setCallForwardingOption(action, 110 reason, 111 number, 112 time, 113 mHandler.obtainMessage(MyHandler.MESSAGE_SET_CF, 114 action, 115 MyHandler.MESSAGE_SET_CF)); 116 117 if (tcpListener != null) { 118 tcpListener.onStarted(this, false); 119 } 120 } 121 } 122 } 123 124 void handleCallForwardResult(CallForwardInfo cf) { 125 callForwardInfo = cf; 126 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse done, callForwardInfo=" + callForwardInfo); 127 128 setToggled(callForwardInfo.status == 1); 129 setPhoneNumber(callForwardInfo.number); 130 } 131 132 private void updateSummaryText() { 133 if (isToggled()) { 134 CharSequence summaryOn; 135 final String number = getRawPhoneNumber(); 136 if (number != null && number.length() > 0) { 137 String values[] = { number }; 138 summaryOn = TextUtils.replace(mSummaryOnTemplate, SRC_TAGS, values); 139 } else { 140 summaryOn = getContext().getString(R.string.sum_cfu_enabled_no_number); 141 } 142 setSummaryOn(summaryOn); 143 } 144 145 } 146 147 // Message protocol: 148 // what: get vs. set 149 // arg1: action -- register vs. disable 150 // arg2: get vs. set for the preceding request 151 private class MyHandler extends Handler { 152 private static final int MESSAGE_GET_CF = 0; 153 private static final int MESSAGE_SET_CF = 1; 154 155 @Override 156 public void handleMessage(Message msg) { 157 switch (msg.what) { 158 case MESSAGE_GET_CF: 159 handleGetCFResponse(msg); 160 break; 161 case MESSAGE_SET_CF: 162 handleSetCFResponse(msg); 163 break; 164 } 165 } 166 167 private void handleGetCFResponse(Message msg) { 168 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse: done"); 169 170 if (msg.arg2 == MESSAGE_SET_CF) { 171 tcpListener.onFinished(CallForwardEditPreference.this, false); 172 } else { 173 tcpListener.onFinished(CallForwardEditPreference.this, true); 174 } 175 176 AsyncResult ar = (AsyncResult) msg.obj; 177 178 callForwardInfo = null; 179 if (ar.exception != null) { 180 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse: ar.exception=" + ar.exception); 181 tcpListener.onException(CallForwardEditPreference.this, 182 (CommandException) ar.exception); 183 } else { 184 if (ar.userObj instanceof Throwable) { 185 tcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR); 186 } 187 CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result; 188 if (cfInfoArray.length == 0) { 189 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse: cfInfoArray.length==0"); 190 setEnabled(false); 191 tcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR); 192 } else { 193 for (int i = 0, length = cfInfoArray.length; i < length; i++) { 194 if (DBG) Log.d(LOG_TAG, "handleGetCFResponse, cfInfoArray[" + i + "]=" 195 + cfInfoArray[i]); 196 if ((mServiceClass & cfInfoArray[i].serviceClass) != 0) { 197 // corresponding class 198 CallForwardInfo info = cfInfoArray[i]; 199 handleCallForwardResult(info); 200 201 // Show an alert if we got a success response but 202 // with unexpected values. 203 // Currently only handle the fail-to-disable case 204 // since we haven't observed fail-to-enable. 205 if (msg.arg2 == MESSAGE_SET_CF && 206 msg.arg1 == CommandsInterface.CF_ACTION_DISABLE && 207 info.status == 1) { 208 CharSequence s; 209 switch (reason) { 210 case CommandsInterface.CF_REASON_BUSY: 211 s = getContext().getText(R.string.disable_cfb_forbidden); 212 break; 213 case CommandsInterface.CF_REASON_NO_REPLY: 214 s = getContext().getText(R.string.disable_cfnry_forbidden); 215 break; 216 default: // not reachable 217 s = getContext().getText(R.string.disable_cfnrc_forbidden); 218 } 219 AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); 220 builder.setNeutralButton(R.string.close_dialog, null); 221 builder.setTitle(getContext().getText(R.string.error_updating_title)); 222 builder.setMessage(s); 223 builder.setCancelable(true); 224 builder.create().show(); 225 } 226 } 227 } 228 } 229 } 230 231 // Now whether or not we got a new number, reset our enabled 232 // summary text since it may have been replaced by an empty 233 // placeholder. 234 updateSummaryText(); 235 } 236 237 private void handleSetCFResponse(Message msg) { 238 AsyncResult ar = (AsyncResult) msg.obj; 239 240 if (ar.exception != null) { 241 if (DBG) Log.d(LOG_TAG, "handleSetCFResponse: ar.exception=" + ar.exception); 242 // setEnabled(false); 243 } 244 if (DBG) Log.d(LOG_TAG, "handleSetCFResponse: re get"); 245 phone.getCallForwardingOption(reason, 246 obtainMessage(MESSAGE_GET_CF, msg.arg1, MESSAGE_SET_CF, ar.exception)); 247 } 248 } 249 } 250