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