• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.phone;
2 
3 import static com.android.phone.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
4 import static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
5 
6 import android.app.AlertDialog;
7 import android.content.Context;
8 import android.content.DialogInterface;
9 import android.content.res.TypedArray;
10 import android.os.AsyncResult;
11 import android.os.Handler;
12 import android.os.Message;
13 import android.os.PersistableBundle;
14 import android.telephony.CarrierConfigManager;
15 import android.telephony.PhoneNumberUtils;
16 import android.telephony.TelephonyManager;
17 import android.text.BidiFormatter;
18 import android.text.SpannableString;
19 import android.text.TextDirectionHeuristics;
20 import android.text.TextUtils;
21 import android.util.AttributeSet;
22 import android.util.Log;
23 import android.view.View;
24 
25 import com.android.internal.telephony.CallForwardInfo;
26 import com.android.internal.telephony.CommandException;
27 import com.android.internal.telephony.CommandsInterface;
28 import com.android.internal.telephony.Phone;
29 
30 import java.util.HashMap;
31 import java.util.Locale;
32 
33 public class CallForwardEditPreference extends EditPhoneNumberPreference {
34     private static final String LOG_TAG = "CallForwardEditPreference";
35 
36     private static final String SRC_TAGS[]       = {"{0}"};
37     private CharSequence mSummaryOnTemplate;
38     /**
39      * Remembers which button was clicked by a user. If no button is clicked yet, this should have
40      * {@link DialogInterface#BUTTON_NEGATIVE}, meaning "cancel".
41      *
42      * TODO: consider removing this variable and having getButtonClicked() in
43      * EditPhoneNumberPreference instead.
44      */
45     private int mButtonClicked;
46     private int mServiceClass;
47     private MyHandler mHandler = new MyHandler();
48     int reason;
49     private Phone mPhone;
50     CallForwardInfo callForwardInfo;
51     private TimeConsumingPreferenceListener mTcpListener;
52     // Should we replace CF queries containing an invalid number with "Voicemail"
53     private boolean mReplaceInvalidCFNumber = false;
54     private boolean mCallForwardByUssd = false;
55     private CarrierXmlParser mCarrierXmlParser;
56     private int mPreviousCommand = MyHandler.MESSAGE_GET_CF;
57     private Object mCommandException;
58     private CarrierXmlParser.SsEntry.SSAction mSsAction =
59             CarrierXmlParser.SsEntry.SSAction.UNKNOWN;
60     private int mAction;
61     private HashMap<String, String> mCfInfo;
62     private long mDelayMillisAfterUssdSet = 1000;
63 
CallForwardEditPreference(Context context, AttributeSet attrs)64     public CallForwardEditPreference(Context context, AttributeSet attrs) {
65         super(context, attrs);
66 
67         mSummaryOnTemplate = this.getSummaryOn();
68 
69         TypedArray a = context.obtainStyledAttributes(attrs,
70                 R.styleable.CallForwardEditPreference, 0, R.style.EditPhoneNumberPreference);
71         mServiceClass = a.getInt(R.styleable.CallForwardEditPreference_serviceClass,
72                 CommandsInterface.SERVICE_CLASS_VOICE);
73         reason = a.getInt(R.styleable.CallForwardEditPreference_reason,
74                 CommandsInterface.CF_REASON_UNCONDITIONAL);
75         a.recycle();
76 
77         Log.d(LOG_TAG, "mServiceClass=" + mServiceClass + ", reason=" + reason);
78     }
79 
CallForwardEditPreference(Context context)80     public CallForwardEditPreference(Context context) {
81         this(context, null);
82     }
83 
init(TimeConsumingPreferenceListener listener, Phone phone, boolean replaceInvalidCFNumber, boolean callForwardByUssd)84     void init(TimeConsumingPreferenceListener listener, Phone phone,
85             boolean replaceInvalidCFNumber, boolean callForwardByUssd) {
86         mPhone = phone;
87         mTcpListener = listener;
88         mReplaceInvalidCFNumber = replaceInvalidCFNumber;
89         mCallForwardByUssd = callForwardByUssd;
90         Log.d(LOG_TAG,
91                 "init :mReplaceInvalidCFNumber " + mReplaceInvalidCFNumber + ", mCallForwardByUssd "
92                         + mCallForwardByUssd);
93         if (mCallForwardByUssd) {
94             mCfInfo = new HashMap<String, String>();
95             TelephonyManager telephonyManager = new TelephonyManager(getContext(),
96                     phone.getSubId());
97             mCarrierXmlParser = new CarrierXmlParser(getContext(),
98                     telephonyManager.getSimCarrierId());
99         }
100     }
101 
restoreCallForwardInfo(CallForwardInfo cf)102     void restoreCallForwardInfo(CallForwardInfo cf) {
103         handleCallForwardResult(cf);
104         updateSummaryText();
105     }
106 
107     @Override
onBindDialogView(View view)108     protected void onBindDialogView(View view) {
109         // default the button clicked to be the cancel button.
110         mButtonClicked = DialogInterface.BUTTON_NEGATIVE;
111         super.onBindDialogView(view);
112     }
113 
114     @Override
onClick(DialogInterface dialog, int which)115     public void onClick(DialogInterface dialog, int which) {
116         super.onClick(dialog, which);
117         mButtonClicked = which;
118     }
119 
120     @Override
onDialogClosed(boolean positiveResult)121     protected void onDialogClosed(boolean positiveResult) {
122         super.onDialogClosed(positiveResult);
123 
124         Log.d(LOG_TAG, "mButtonClicked=" + mButtonClicked + ", positiveResult=" + positiveResult);
125         // Ignore this event if the user clicked the cancel button, or if the dialog is dismissed
126         // without any button being pressed (back button press or click event outside the dialog).
127         if (isUnknownStatus() && this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
128             int action = (mButtonClicked == DialogInterface.BUTTON_POSITIVE) ?
129                 CommandsInterface.CF_ACTION_REGISTRATION :
130                 CommandsInterface.CF_ACTION_DISABLE;
131             final String number = (action == CommandsInterface.CF_ACTION_DISABLE) ?
132                     "" : getPhoneNumber();
133 
134             Log.d(LOG_TAG, "reason=" + reason + ", action=" + action + ", number=" + number);
135 
136             // Display no forwarding number while we're waiting for confirmation.
137             setSummaryOff("");
138 
139             mPhone.setCallForwardingOption(action,
140                     reason,
141                     number,
142                     mServiceClass,
143                     0,
144                     mHandler.obtainMessage(MyHandler.MESSAGE_SET_CF,
145                         action,
146                         MyHandler.MESSAGE_SET_CF));
147         } else if (this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
148             int action = (isToggled() || (mButtonClicked == DialogInterface.BUTTON_POSITIVE)) ?
149                     CommandsInterface.CF_ACTION_REGISTRATION :
150                     CommandsInterface.CF_ACTION_DISABLE;
151             int time = 0;
152             if (reason == CommandsInterface.CF_REASON_NO_REPLY) {
153                 PersistableBundle carrierConfig = PhoneGlobals.getInstance()
154                         .getCarrierConfigForSubId(mPhone.getSubId());
155                 if (carrierConfig.getBoolean(
156                         CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
157                     time = 20;
158                 }
159             }
160             final String number = getPhoneNumber();
161 
162             Log.d(LOG_TAG, "callForwardInfo=" + callForwardInfo);
163 
164             if (action == CommandsInterface.CF_ACTION_REGISTRATION
165                     && callForwardInfo != null
166                     && callForwardInfo.status == 1
167                     && number.equals(callForwardInfo.number)) {
168                 // no change, do nothing
169                 Log.d(LOG_TAG, "no change, do nothing");
170             } else {
171                 // set to network
172                 Log.d(LOG_TAG, "reason=" + reason + ", action=" + action
173                         + ", number=" + number);
174 
175                 // Display no forwarding number while we're waiting for
176                 // confirmation
177                 setSummaryOn("");
178                 if (!mCallForwardByUssd) {
179                     // the interface of Phone.setCallForwardingOption has error:
180                     // should be action, reason...
181                     mPhone.setCallForwardingOption(action,
182                             reason,
183                             number,
184                             mServiceClass,
185                             time,
186                             mHandler.obtainMessage(MyHandler.MESSAGE_SET_CF,
187                                     action,
188                                     MyHandler.MESSAGE_SET_CF));
189                 } else {
190                     if (action == CommandsInterface.CF_ACTION_REGISTRATION) {
191                         mCfInfo.put(CarrierXmlParser.TAG_ENTRY_NUMBER, number);
192                         mCfInfo.put(CarrierXmlParser.TAG_ENTRY_TIME, Integer.toString(time));
193                     } else {
194                         mCfInfo.clear();
195                     }
196                     mHandler.sendMessage(mHandler.obtainMessage(mHandler.MESSAGE_SET_CF_USSD,
197                             action, MyHandler.MESSAGE_SET_CF));
198                 }
199                 if (mTcpListener != null) {
200                     mTcpListener.onStarted(this, false);
201                 }
202             }
203         }
204     }
205 
handleCallForwardResult(CallForwardInfo cf)206     private void handleCallForwardResult(CallForwardInfo cf) {
207         callForwardInfo = cf;
208         Log.d(LOG_TAG, "handleGetCFResponse done, callForwardInfo=" + callForwardInfo);
209         // In some cases, the network can send call forwarding URIs for voicemail that violate the
210         // 3gpp spec. This can cause us to receive "numbers" that are sequences of letters. In this
211         // case, we must detect these series of characters and replace them with "Voicemail".
212         // PhoneNumberUtils#formatNumber returns null if the number is not valid.
213         if (mReplaceInvalidCFNumber && !TextUtils.isEmpty(callForwardInfo.number)
214                 && (PhoneNumberUtils.formatNumber(callForwardInfo.number, getCurrentCountryIso())
215                 == null)) {
216             callForwardInfo.number = getContext().getString(R.string.voicemail);
217             Log.i(LOG_TAG, "handleGetCFResponse: Overridding CF number");
218         }
219 
220         setUnknownStatus(callForwardInfo.status == CommandsInterface.SS_STATUS_UNKNOWN);
221         setToggled(callForwardInfo.status == 1);
222         boolean displayVoicemailNumber = false;
223         if (TextUtils.isEmpty(callForwardInfo.number)) {
224             PersistableBundle carrierConfig =
225                     PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
226             if (carrierConfig != null) {
227                 displayVoicemailNumber = carrierConfig.getBoolean(CarrierConfigManager
228                         .KEY_DISPLAY_VOICEMAIL_NUMBER_AS_DEFAULT_CALL_FORWARDING_NUMBER_BOOL);
229                 Log.d(LOG_TAG, "display voicemail number as default");
230             }
231         }
232         String voicemailNumber = mPhone.getVoiceMailNumber();
233         setPhoneNumber(displayVoicemailNumber ? voicemailNumber : callForwardInfo.number);
234     }
235 
236     /**
237      * Starts the Call Forwarding Option query to the network and calls
238      * {@link TimeConsumingPreferenceListener#onStarted}. Will call
239      * {@link TimeConsumingPreferenceListener#onFinished} when finished, or
240      * {@link TimeConsumingPreferenceListener#onError} if an error has occurred.
241      */
startCallForwardOptionsQuery()242     void startCallForwardOptionsQuery() {
243         if (!mCallForwardByUssd) {
244             mPhone.getCallForwardingOption(reason, mServiceClass,
245                     mHandler.obtainMessage(MyHandler.MESSAGE_GET_CF,
246                             // unused in this case
247                             CommandsInterface.CF_ACTION_DISABLE,
248                             MyHandler.MESSAGE_GET_CF, null));
249         } else {
250             mHandler.sendMessage(mHandler.obtainMessage(mHandler.MESSAGE_GET_CF_USSD,
251                     // unused in this case
252                     CommandsInterface.CF_ACTION_DISABLE, MyHandler.MESSAGE_GET_CF, null));
253         }
254         if (mTcpListener != null) {
255             mTcpListener.onStarted(this, true);
256         }
257     }
258 
updateSummaryText()259     private void updateSummaryText() {
260         if (isToggled()) {
261             final String number = getRawPhoneNumber();
262             if (number != null && number.length() > 0) {
263                 // Wrap the number to preserve presentation in RTL languages.
264                 String wrappedNumber = BidiFormatter.getInstance().unicodeWrap(
265                         number, TextDirectionHeuristics.LTR);
266                 String values[] = { wrappedNumber };
267                 String summaryOn = String.valueOf(
268                         TextUtils.replace(mSummaryOnTemplate, SRC_TAGS, values));
269                 int start = summaryOn.indexOf(wrappedNumber);
270 
271                 SpannableString spannableSummaryOn = new SpannableString(summaryOn);
272                 PhoneNumberUtils.addTtsSpan(spannableSummaryOn,
273                         start, start + wrappedNumber.length());
274                 setSummaryOn(spannableSummaryOn);
275             } else {
276                 setSummaryOn(getContext().getString(R.string.sum_cfu_enabled_no_number));
277             }
278         }
279 
280     }
281 
282     /**
283      * @return The ISO 3166-1 two letters country code of the country the user is in based on the
284      *      network location.
285      */
getCurrentCountryIso()286     private String getCurrentCountryIso() {
287         final TelephonyManager telephonyManager =
288                 (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
289         if (telephonyManager == null) {
290             return "";
291         }
292         return telephonyManager.getNetworkCountryIso().toUpperCase(Locale.ROOT);
293     }
294 
295     // Message protocol:
296     // what: get vs. set
297     // arg1: action -- register vs. disable
298     // arg2: get vs. set for the preceding request
299     private class MyHandler extends Handler {
300         static final int MESSAGE_GET_CF = 0;
301         static final int MESSAGE_SET_CF = 1;
302         static final int MESSAGE_GET_CF_USSD = 2;
303         static final int MESSAGE_SET_CF_USSD = 3;
304 
305         TelephonyManager.UssdResponseCallback mUssdCallback =
306                 new TelephonyManager.UssdResponseCallback() {
307                     @Override
308                     public void onReceiveUssdResponse(final TelephonyManager telephonyManager,
309                             String request, CharSequence response) {
310                         if (mSsAction == CarrierXmlParser.SsEntry.SSAction.UNKNOWN) {
311                             return;
312                         }
313 
314                         HashMap<String, String> analysisResult = mCarrierXmlParser.getFeature(
315                                 CarrierXmlParser.FEATURE_CALL_FORWARDING)
316                                 .getResponseSet(mSsAction,
317                                         response.toString());
318 
319                         Throwable throwableException = null;
320                         if (analysisResult.get(CarrierXmlParser.TAG_RESPONSE_STATUS_ERROR)
321                                 != null) {
322                             throwableException = new CommandException(
323                                     CommandException.Error.GENERIC_FAILURE);
324                         }
325 
326                         Object obj = null;
327                         if (mSsAction == CarrierXmlParser.SsEntry.SSAction.QUERY) {
328                             obj = makeCallForwardInfo(analysisResult);
329                         }
330 
331                         sendCfMessage(obj, throwableException);
332                     }
333 
334                     @Override
335                     public void onReceiveUssdResponseFailed(final TelephonyManager telephonyManager,
336                             String request, int failureCode) {
337                         Log.d(LOG_TAG, "receive the ussd result failed");
338                         Throwable throwableException = new CommandException(
339                                 CommandException.Error.GENERIC_FAILURE);
340                         sendCfMessage(null, throwableException);
341                     }
342                 };
343 
344         @Override
handleMessage(Message msg)345         public void handleMessage(Message msg) {
346             switch (msg.what) {
347                 case MESSAGE_GET_CF:
348                     handleGetCFResponse(msg);
349                     break;
350                 case MESSAGE_SET_CF:
351                     handleSetCFResponse(msg);
352                     break;
353                 case MESSAGE_GET_CF_USSD:
354                     prepareUssdCommand(msg, CarrierXmlParser.SsEntry.SSAction.QUERY);
355                     break;
356                 case MESSAGE_SET_CF_USSD:
357                     prepareUssdCommand(msg, CarrierXmlParser.SsEntry.SSAction.UNKNOWN);
358                     break;
359             }
360         }
361 
handleGetCFResponse(Message msg)362         private void handleGetCFResponse(Message msg) {
363             Log.d(LOG_TAG, "handleGetCFResponse: done");
364 
365             mTcpListener.onFinished(CallForwardEditPreference.this, msg.arg2 != MESSAGE_SET_CF);
366 
367             AsyncResult ar = (AsyncResult) msg.obj;
368 
369             callForwardInfo = null;
370             boolean summaryOff = false;
371             if (ar.exception != null) {
372                 Log.d(LOG_TAG, "handleGetCFResponse: ar.exception=" + ar.exception);
373                 if (ar.exception instanceof CommandException) {
374                     mTcpListener.onException(CallForwardEditPreference.this,
375                             (CommandException) ar.exception);
376                 } else {
377                     // Most likely an ImsException and we can't handle it the same way as
378                     // a CommandException. The best we can do is to handle the exception
379                     // the same way as mTcpListener.onException() does when it is not of type
380                     // FDN_CHECK_FAILURE.
381                     mTcpListener.onError(CallForwardEditPreference.this, EXCEPTION_ERROR);
382                 }
383             } else {
384                 if (ar.userObj instanceof Throwable) {
385                     mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
386                 }
387                 CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
388                 if (cfInfoArray == null || cfInfoArray.length == 0) {
389                     Log.d(LOG_TAG, "handleGetCFResponse: cfInfoArray.length==0");
390                     if (!(ar.userObj instanceof Throwable)) {
391                         mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
392                     }
393                 } else {
394                     for (int i = 0, length = cfInfoArray.length; i < length; i++) {
395                         Log.d(LOG_TAG, "handleGetCFResponse, cfInfoArray[" + i + "]="
396                                 + cfInfoArray[i]);
397                         if ((mServiceClass & cfInfoArray[i].serviceClass) != 0) {
398                             // corresponding class
399                             CallForwardInfo info = cfInfoArray[i];
400                             handleCallForwardResult(info);
401 
402                             summaryOff = (info.status == CommandsInterface.SS_STATUS_UNKNOWN);
403 
404                             if (ar.userObj instanceof Throwable) {
405                                 Log.d(LOG_TAG, "Skipped duplicated error dialog");
406                                 continue;
407                             }
408 
409                             // Show an alert if we got a success response but
410                             // with unexpected values.
411                             // Handle the fail-to-disable case.
412                             if (msg.arg2 == MESSAGE_SET_CF &&
413                                     msg.arg1 == CommandsInterface.CF_ACTION_DISABLE &&
414                                     info.status == 1) {
415                                 // Skip showing error dialog since some operators return
416                                 // active status even if disable call forward succeeded.
417                                 // And they don't like the error dialog.
418                                 if (isSkipCFFailToDisableDialog()) {
419                                     Log.d(LOG_TAG, "Skipped Callforwarding fail-to-disable dialog");
420                                     continue;
421                                 }
422                                 CharSequence s;
423                                 switch (reason) {
424                                     case CommandsInterface.CF_REASON_BUSY:
425                                         s = getContext().getText(R.string.disable_cfb_forbidden);
426                                         break;
427                                     case CommandsInterface.CF_REASON_NO_REPLY:
428                                         s = getContext().getText(R.string.disable_cfnry_forbidden);
429                                         break;
430                                     default: // not reachable
431                                         s = getContext().getText(R.string.disable_cfnrc_forbidden);
432                                 }
433                                 AlertDialog.Builder builder =
434                                         FrameworksUtils.makeAlertDialogBuilder(getContext());
435                                 builder.setNeutralButton(R.string.close_dialog, null);
436                                 builder.setTitle(getContext()
437                                         .getText(R.string.error_updating_title));
438                                 builder.setMessage(s);
439                                 builder.setCancelable(true);
440                                 builder.create().show();
441                             } else if (msg.arg2 == MESSAGE_SET_CF &&
442                                     msg.arg1 == CommandsInterface.CF_ACTION_REGISTRATION &&
443                                     info.status == 0) {
444                                 // Handle the fail-to-enable case.
445                                 CharSequence s = getContext()
446                                     .getText(R.string.registration_cf_forbidden);
447                                 AlertDialog.Builder builder =
448                                         FrameworksUtils.makeAlertDialogBuilder(getContext());
449                                 builder.setNeutralButton(R.string.close_dialog, null);
450                                 builder.setTitle(getContext()
451                                         .getText(R.string.error_updating_title));
452                                 builder.setMessage(s);
453                                 builder.setCancelable(true);
454                                 builder.create().show();
455                             }
456                         }
457                     }
458                 }
459             }
460 
461             // Now whether or not we got a new number, reset our enabled
462             // summary text since it may have been replaced by an empty
463             // placeholder.
464             // for CDMA, doesn't display summary.
465             if (summaryOff) {
466                 setSummaryOff("");
467             } else {
468                 // Now whether or not we got a new number, reset our enabled
469                 // summary text since it may have been replaced by an empty
470                 // placeholder.
471                 updateSummaryText();
472             }
473         }
474 
handleSetCFResponse(Message msg)475         private void handleSetCFResponse(Message msg) {
476             AsyncResult ar = (AsyncResult) msg.obj;
477             if (ar.exception != null) {
478                 Log.d(LOG_TAG, "handleSetCFResponse: ar.exception=" + ar.exception);
479                 // setEnabled(false);
480             }
481 
482             if (ar.result != null) {
483                 int arr = (int)ar.result;
484                 if (arr == CommandsInterface.SS_STATUS_UNKNOWN) {
485                     Log.d(LOG_TAG, "handleSetCFResponse: no need to re get in CDMA");
486                     mTcpListener.onFinished(CallForwardEditPreference.this, false);
487                     return;
488                 }
489             }
490 
491             Log.d(LOG_TAG, "handleSetCFResponse: re get");
492             if (!mCallForwardByUssd) {
493                 mPhone.getCallForwardingOption(reason, mServiceClass,
494                         obtainMessage(MESSAGE_GET_CF, msg.arg1, MESSAGE_SET_CF, ar.exception));
495             } else {
496                 mHandler.sendMessageDelayed(mHandler.obtainMessage(mHandler.MESSAGE_GET_CF_USSD,
497                         msg.arg1, MyHandler.MESSAGE_SET_CF, ar.exception),
498                         mDelayMillisAfterUssdSet);
499             }
500         }
501 
prepareUssdCommand(Message msg, CarrierXmlParser.SsEntry.SSAction inputSsAction)502         private void prepareUssdCommand(Message msg,
503                 CarrierXmlParser.SsEntry.SSAction inputSsAction) {
504             mAction = msg.arg1;
505             mPreviousCommand = msg.arg2;
506             mCommandException = msg.obj;
507             mSsAction = inputSsAction;
508 
509             if (mSsAction != CarrierXmlParser.SsEntry.SSAction.QUERY) {
510                 if (mAction == CommandsInterface.CF_ACTION_REGISTRATION) {
511                     mSsAction = CarrierXmlParser.SsEntry.SSAction.UPDATE_ACTIVATE;
512                 } else {
513                     mSsAction = CarrierXmlParser.SsEntry.SSAction.UPDATE_DEACTIVATE;
514                 }
515             }
516 
517             new Thread(new Runnable() {
518                 @Override
519                 public void run() {
520                     sendUssdCommand(mUssdCallback, mSsAction, mCfInfo.isEmpty() ? null : mCfInfo);
521                 }
522             }).start();
523         }
524 
sendUssdCommand(TelephonyManager.UssdResponseCallback inputCallback, CarrierXmlParser.SsEntry.SSAction inputAction, HashMap<String, String> inputCfInfo)525         private void sendUssdCommand(TelephonyManager.UssdResponseCallback inputCallback,
526                 CarrierXmlParser.SsEntry.SSAction inputAction,
527                 HashMap<String, String> inputCfInfo) {
528             String newUssdCommand = mCarrierXmlParser.getFeature(
529                     CarrierXmlParser.FEATURE_CALL_FORWARDING)
530                     .makeCommand(inputAction, inputCfInfo);
531             TelephonyManager telephonyManager =
532                     (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
533             telephonyManager.sendUssdRequest(newUssdCommand, inputCallback, mHandler);
534         }
535 
makeGetCfMessage(int inputMsgWhat, int inputMsgArg2, Object inputMsgObj)536         private Message makeGetCfMessage(int inputMsgWhat, int inputMsgArg2, Object inputMsgObj) {
537             return mHandler.obtainMessage(inputMsgWhat,
538                     mAction,
539                     inputMsgArg2,
540                     inputMsgObj);
541         }
542 
makeSetCfMessage(int inputMsgWhat, int inputMsgArg2)543         private Message makeSetCfMessage(int inputMsgWhat, int inputMsgArg2) {
544             return mHandler.obtainMessage(inputMsgWhat,
545                     mAction,
546                     inputMsgArg2);
547         }
548 
sendCfMessage(Object inputArObj, Throwable inputThrowableException)549         private void sendCfMessage(Object inputArObj, Throwable inputThrowableException) {
550             Message message;
551             if (mSsAction == CarrierXmlParser.SsEntry.SSAction.UNKNOWN) {
552                 return;
553             }
554             if (mSsAction == CarrierXmlParser.SsEntry.SSAction.QUERY) {
555                 message = makeGetCfMessage(MyHandler.MESSAGE_GET_CF, mPreviousCommand,
556                         mCommandException);
557             } else {
558                 message = makeSetCfMessage(MyHandler.MESSAGE_SET_CF, MyHandler.MESSAGE_SET_CF);
559             }
560             AsyncResult.forMessage(message, inputArObj, inputThrowableException);
561             message.sendToTarget();
562         }
563 
makeCallForwardInfo(HashMap<String, String> inputInfo)564         private CallForwardInfo[] makeCallForwardInfo(HashMap<String, String> inputInfo) {
565             int tmpStatus = 0;
566             String tmpNumberStr = "";
567             int tmpTime = 0;
568             if (inputInfo != null && inputInfo.size() != 0) {
569                 String tmpStatusStr = inputInfo.get(CarrierXmlParser.TAG_RESPONSE_STATUS);
570 
571                 String tmpTimeStr = inputInfo.get(CarrierXmlParser.TAG_RESPONSE_TIME);
572                 if (!TextUtils.isEmpty(tmpStatusStr)) {
573                     if (tmpStatusStr.equals(
574                             CarrierXmlParser.TAG_COMMAND_RESULT_DEFINITION_ACTIVATE)) {
575                         tmpStatus = 1;
576                     } else if (tmpStatusStr.equals(
577                             CarrierXmlParser.TAG_COMMAND_RESULT_DEFINITION_DEACTIVATE)
578                             || tmpStatusStr.equals(
579                             CarrierXmlParser.TAG_COMMAND_RESULT_DEFINITION_UNREGISTER)) {
580                         tmpStatus = 0;
581                     }
582                 }
583 
584                 tmpNumberStr = inputInfo.get(CarrierXmlParser.TAG_RESPONSE_NUMBER);
585                 if (!TextUtils.isEmpty(tmpTimeStr)) {
586                     tmpTime = Integer.valueOf(inputInfo.get(CarrierXmlParser.TAG_RESPONSE_TIME));
587                 }
588             }
589 
590             CallForwardInfo[] newCallForwardInfo = new CallForwardInfo[1];
591             newCallForwardInfo[0] = new CallForwardInfo();
592             newCallForwardInfo[0].status = tmpStatus;
593             newCallForwardInfo[0].reason = reason;
594             newCallForwardInfo[0].serviceClass = mServiceClass;
595             newCallForwardInfo[0].number = tmpNumberStr;
596             newCallForwardInfo[0].timeSeconds = tmpTime;
597             return newCallForwardInfo;
598         }
599     }
600 
601     /*
602      * Get the config of whether skip showing CF fail-to-disable dialog
603      * from carrier config manager.
604      *
605      * @return boolean value of the config
606      */
isSkipCFFailToDisableDialog()607     private boolean isSkipCFFailToDisableDialog() {
608         PersistableBundle carrierConfig =
609                 PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
610         if (carrierConfig != null) {
611             return carrierConfig.getBoolean(
612                     CarrierConfigManager.KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL);
613         } else {
614             // by default we should not skip
615             return false;
616         }
617     }
618 }
619