17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.CallForwardInfo;
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.CommandException;
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.CommandsInterface;
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.AlertDialog;
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Context;
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.DialogInterface;
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.res.TypedArray;
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
15cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sunimport android.os.PersistableBundle;
16cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sunimport android.telephony.CarrierConfigManager;
17aca784f06323ef075b3c63765385d861b02fddbbHall Liuimport android.telephony.PhoneNumberUtils;
18491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebingerimport android.telephony.TelephonyManager;
190e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Leeimport android.text.BidiFormatter;
20aca784f06323ef075b3c63765385d861b02fddbbHall Liuimport android.text.SpannableString;
210e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Leeimport android.text.TextDirectionHeuristics;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.AttributeSet;
247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.view.View;
267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport static com.android.phone.TimeConsumingPreferenceActivity.RESPONSE_ERROR;
28d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Leeimport static com.android.phone.TimeConsumingPreferenceActivity.EXCEPTION_ERROR;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpublic class CallForwardEditPreference extends EditPhoneNumberPreference {
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "CallForwardEditPreference";
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String SRC_TAGS[]       = {"{0}"};
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private CharSequence mSummaryOnTemplate;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Remembers which button was clicked by a user. If no button is clicked yet, this should have
377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * {@link DialogInterface#BUTTON_NEGATIVE}, meaning "cancel".
387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: consider removing this variable and having getButtonClicked() in
407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * EditPhoneNumberPreference instead.
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private int mButtonClicked;
437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private int mServiceClass;
447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private MyHandler mHandler = new MyHandler();
457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    int reason;
462b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee    private Phone mPhone;
477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    CallForwardInfo callForwardInfo;
482b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee    private TimeConsumingPreferenceListener mTcpListener;
49491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    // Should we replace CF queries containing an invalid number with "Voicemail"
50491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    private boolean mReplaceInvalidCFNumber = false;
517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public CallForwardEditPreference(Context context, AttributeSet attrs) {
537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        super(context, attrs);
547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mSummaryOnTemplate = this.getSummaryOn();
567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        TypedArray a = context.obtainStyledAttributes(attrs,
587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                R.styleable.CallForwardEditPreference, 0, R.style.EditPhoneNumberPreference);
597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mServiceClass = a.getInt(R.styleable.CallForwardEditPreference_serviceClass,
607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                CommandsInterface.SERVICE_CLASS_VOICE);
617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        reason = a.getInt(R.styleable.CallForwardEditPreference_reason,
627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                CommandsInterface.CF_REASON_UNCONDITIONAL);
637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        a.recycle();
647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6559b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn        Log.d(LOG_TAG, "mServiceClass=" + mServiceClass + ", reason=" + reason);
667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public CallForwardEditPreference(Context context) {
697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        this(context, null);
707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
72491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone,
73491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger            boolean replaceInvalidCFNumber) {
742b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee        mPhone = phone;
752b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee        mTcpListener = listener;
76491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        mReplaceInvalidCFNumber = replaceInvalidCFNumber;
772b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee
787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!skipReading) {
792b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee            mPhone.getCallForwardingOption(reason,
807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mHandler.obtainMessage(MyHandler.MESSAGE_GET_CF,
817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // unused in this case
827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            CommandsInterface.CF_ACTION_DISABLE,
837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            MyHandler.MESSAGE_GET_CF, null));
842b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee            if (mTcpListener != null) {
852b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                mTcpListener.onStarted(this, true);
867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    protected void onBindDialogView(View view) {
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // default the button clicked to be the cancel button.
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mButtonClicked = DialogInterface.BUTTON_NEGATIVE;
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        super.onBindDialogView(view);
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void onClick(DialogInterface dialog, int which) {
997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        super.onClick(dialog, which);
1007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mButtonClicked = which;
1017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
1047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    protected void onDialogClosed(boolean positiveResult) {
1057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        super.onDialogClosed(positiveResult);
1067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10759b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn        Log.d(LOG_TAG, "mButtonClicked=" + mButtonClicked + ", positiveResult=" + positiveResult);
1087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Ignore this event if the user clicked the cancel button, or if the dialog is dismissed
1097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // without any button being pressed (back button press or click event outside the dialog).
1107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (this.mButtonClicked != DialogInterface.BUTTON_NEGATIVE) {
1117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int action = (isToggled() || (mButtonClicked == DialogInterface.BUTTON_POSITIVE)) ?
1127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    CommandsInterface.CF_ACTION_REGISTRATION :
1137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    CommandsInterface.CF_ACTION_DISABLE;
1147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int time = (reason != CommandsInterface.CF_REASON_NO_REPLY) ? 0 : 20;
1157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final String number = getPhoneNumber();
1167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11759b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn            Log.d(LOG_TAG, "callForwardInfo=" + callForwardInfo);
1187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (action == CommandsInterface.CF_ACTION_REGISTRATION
1207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    && callForwardInfo != null
1217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    && callForwardInfo.status == 1
1227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    && number.equals(callForwardInfo.number)) {
1237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // no change, do nothing
12459b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                Log.d(LOG_TAG, "no change, do nothing");
1257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
1267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // set to network
12759b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                Log.d(LOG_TAG, "reason=" + reason + ", action=" + action
1287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        + ", number=" + number);
1297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Display no forwarding number while we're waiting for
1317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // confirmation
1327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                setSummaryOn("");
1337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // the interface of Phone.setCallForwardingOption has error:
1357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // should be action, reason...
1362b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                mPhone.setCallForwardingOption(action,
1377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        reason,
1387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        number,
1397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        time,
1407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        mHandler.obtainMessage(MyHandler.MESSAGE_SET_CF,
1417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                action,
1427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                MyHandler.MESSAGE_SET_CF));
1437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1442b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                if (mTcpListener != null) {
1452b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                    mTcpListener.onStarted(this, false);
1467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
1477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    void handleCallForwardResult(CallForwardInfo cf) {
1527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        callForwardInfo = cf;
15359b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn        Log.d(LOG_TAG, "handleGetCFResponse done, callForwardInfo=" + callForwardInfo);
154491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        // In some cases, the network can send call forwarding URIs for voicemail that violate the
155491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        // 3gpp spec. This can cause us to receive "numbers" that are sequences of letters. In this
156491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        // case, we must detect these series of characters and replace them with "Voicemail".
157491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        // PhoneNumberUtils#formatNumber returns null if the number is not valid.
158491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        if (mReplaceInvalidCFNumber && (PhoneNumberUtils.formatNumber(callForwardInfo.number,
159491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger                getCurrentCountryIso()) == null)) {
160491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger            callForwardInfo.number = getContext().getString(R.string.voicemail);
161491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger            Log.i(LOG_TAG, "handleGetCFResponse: Overridding CF number");
162491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        }
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        setToggled(callForwardInfo.status == 1);
1658af41c945a07da577b1bed3f969cff374655f02fQiong Liu        boolean displayVoicemailNumber = false;
1668af41c945a07da577b1bed3f969cff374655f02fQiong Liu        if (TextUtils.isEmpty(callForwardInfo.number)) {
1678af41c945a07da577b1bed3f969cff374655f02fQiong Liu            PersistableBundle carrierConfig =
1688af41c945a07da577b1bed3f969cff374655f02fQiong Liu                    PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
1698af41c945a07da577b1bed3f969cff374655f02fQiong Liu            if (carrierConfig != null) {
1708af41c945a07da577b1bed3f969cff374655f02fQiong Liu                displayVoicemailNumber = carrierConfig.getBoolean(CarrierConfigManager
1718af41c945a07da577b1bed3f969cff374655f02fQiong Liu                        .KEY_DISPLAY_VOICEMAIL_NUMBER_AS_DEFAULT_CALL_FORWARDING_NUMBER_BOOL);
1728af41c945a07da577b1bed3f969cff374655f02fQiong Liu                Log.d(LOG_TAG, "display voicemail number as default");
1738af41c945a07da577b1bed3f969cff374655f02fQiong Liu            }
1748af41c945a07da577b1bed3f969cff374655f02fQiong Liu        }
1758af41c945a07da577b1bed3f969cff374655f02fQiong Liu        String voicemailNumber = mPhone.getVoiceMailNumber();
1768af41c945a07da577b1bed3f969cff374655f02fQiong Liu        setPhoneNumber(displayVoicemailNumber ? voicemailNumber : callForwardInfo.number);
1777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void updateSummaryText() {
1807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (isToggled()) {
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final String number = getRawPhoneNumber();
1827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (number != null && number.length() > 0) {
1830e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Lee                // Wrap the number to preserve presentation in RTL languages.
1840e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Lee                String wrappedNumber = BidiFormatter.getInstance().unicodeWrap(
1850e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Lee                        number, TextDirectionHeuristics.LTR);
1860e98b3c66e31e6b5e5b1dc7fed33ee8102616eb3Andrew Lee                String values[] = { wrappedNumber };
187aca784f06323ef075b3c63765385d861b02fddbbHall Liu                String summaryOn = String.valueOf(
188aca784f06323ef075b3c63765385d861b02fddbbHall Liu                        TextUtils.replace(mSummaryOnTemplate, SRC_TAGS, values));
189aca784f06323ef075b3c63765385d861b02fddbbHall Liu                int start = summaryOn.indexOf(wrappedNumber);
190aca784f06323ef075b3c63765385d861b02fddbbHall Liu
191aca784f06323ef075b3c63765385d861b02fddbbHall Liu                SpannableString spannableSummaryOn = new SpannableString(summaryOn);
192aca784f06323ef075b3c63765385d861b02fddbbHall Liu                PhoneNumberUtils.addTtsSpan(spannableSummaryOn,
193aca784f06323ef075b3c63765385d861b02fddbbHall Liu                        start, start + wrappedNumber.length());
194aca784f06323ef075b3c63765385d861b02fddbbHall Liu                setSummaryOn(spannableSummaryOn);
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
196aca784f06323ef075b3c63765385d861b02fddbbHall Liu                setSummaryOn(getContext().getString(R.string.sum_cfu_enabled_no_number));
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
2017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
202491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    /**
203491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger     * @return The ISO 3166-1 two letters country code of the country the user is in based on the
204491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger     *      network location.
205491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger     */
206491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    private String getCurrentCountryIso() {
207491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        final TelephonyManager telephonyManager =
208491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
209491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        if (telephonyManager == null) {
210491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger            return "";
211491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        }
212491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger        return telephonyManager.getNetworkCountryIso().toUpperCase();
213491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger    }
214491fd4e3ce586271d4c1b1c1ead5863cd16bbca3Brad Ebinger
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message protocol:
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // what: get vs. set
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // arg1: action -- register vs. disable
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // arg2: get vs. set for the preceding request
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private class MyHandler extends Handler {
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        static final int MESSAGE_GET_CF = 0;
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        static final int MESSAGE_SET_CF = 1;
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
2257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case MESSAGE_GET_CF:
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    handleGetCFResponse(msg);
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case MESSAGE_SET_CF:
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    handleSetCFResponse(msg);
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private void handleGetCFResponse(Message msg) {
23659b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn            Log.d(LOG_TAG, "handleGetCFResponse: done");
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2382b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee            mTcpListener.onFinished(CallForwardEditPreference.this, msg.arg2 != MESSAGE_SET_CF);
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar = (AsyncResult) msg.obj;
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            callForwardInfo = null;
2437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (ar.exception != null) {
24459b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                Log.d(LOG_TAG, "handleGetCFResponse: ar.exception=" + ar.exception);
245d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                if (ar.exception instanceof CommandException) {
246d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    mTcpListener.onException(CallForwardEditPreference.this,
247d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                            (CommandException) ar.exception);
248d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                } else {
249d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    // Most likely an ImsException and we can't handle it the same way as
250d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    // a CommandException. The best we can do is to handle the exception
251d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    // the same way as mTcpListener.onException() does when it is not of type
252d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    // FDN_CHECK_FAILURE.
253d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                    mTcpListener.onError(CallForwardEditPreference.this, EXCEPTION_ERROR);
254d4abfd4fd3b41ee8b2724a89b751c96544821baeAnthony Lee                }
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (ar.userObj instanceof Throwable) {
2572b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                    mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
2597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                CallForwardInfo cfInfoArray[] = (CallForwardInfo[]) ar.result;
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (cfInfoArray.length == 0) {
26159b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                    Log.d(LOG_TAG, "handleGetCFResponse: cfInfoArray.length==0");
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    setEnabled(false);
2632b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee                    mTcpListener.onError(CallForwardEditPreference.this, RESPONSE_ERROR);
2647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } else {
2657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    for (int i = 0, length = cfInfoArray.length; i < length; i++) {
26659b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                        Log.d(LOG_TAG, "handleGetCFResponse, cfInfoArray[" + i + "]="
2677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                + cfInfoArray[i]);
2687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        if ((mServiceClass & cfInfoArray[i].serviceClass) != 0) {
2697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // corresponding class
2707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            CallForwardInfo info = cfInfoArray[i];
2717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            handleCallForwardResult(info);
2727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // Show an alert if we got a success response but
2747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // with unexpected values.
2757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // Currently only handle the fail-to-disable case
2767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            // since we haven't observed fail-to-enable.
2777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            if (msg.arg2 == MESSAGE_SET_CF &&
2787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    msg.arg1 == CommandsInterface.CF_ACTION_DISABLE &&
2797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    info.status == 1) {
280cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                // Skip showing error dialog since some operators return
281cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                // active status even if disable call forward succeeded.
282cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                // And they don't like the error dialog.
283cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                if (isSkipCFFailToDisableDialog()) {
284cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                    Log.d(LOG_TAG, "Skipped Callforwarding fail-to-disable dialog");
285cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                    continue;
286cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                                }
2877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                CharSequence s;
2887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                switch (reason) {
2897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    case CommandsInterface.CF_REASON_BUSY:
2907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                        s = getContext().getText(R.string.disable_cfb_forbidden);
2917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                        break;
2927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    case CommandsInterface.CF_REASON_NO_REPLY:
2937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                        s = getContext().getText(R.string.disable_cfnry_forbidden);
2947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                        break;
2957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    default: // not reachable
2967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                        s = getContext().getText(R.string.disable_cfnrc_forbidden);
2977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
2987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
2997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                builder.setNeutralButton(R.string.close_dialog, null);
3007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                builder.setTitle(getContext().getText(R.string.error_updating_title));
3017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                builder.setMessage(s);
3027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                builder.setCancelable(true);
3037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                builder.create().show();
3047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            }
3057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
3067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
3077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
3087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
3097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Now whether or not we got a new number, reset our enabled
3117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // summary text since it may have been replaced by an empty
3127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // placeholder.
3137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            updateSummaryText();
3147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
3157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private void handleSetCFResponse(Message msg) {
3177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar = (AsyncResult) msg.obj;
3187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
3197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (ar.exception != null) {
32059b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn                Log.d(LOG_TAG, "handleSetCFResponse: ar.exception=" + ar.exception);
3217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // setEnabled(false);
3227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
32359b6e78da15af6bf8706f22ed7176b14f7ca59f7Tyler Gunn            Log.d(LOG_TAG, "handleSetCFResponse: re get");
3242b36ba2d3b68fce3e44078c1bdedf9af00b7fc5bAndrew Lee            mPhone.getCallForwardingOption(reason,
3257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    obtainMessage(MESSAGE_GET_CF, msg.arg1, MESSAGE_SET_CF, ar.exception));
3267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
3277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
328cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun
329cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun    /*
330cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun     * Get the config of whether skip showing CF fail-to-disable dialog
331cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun     * from carrier config manager.
332cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun     *
333cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun     * @return boolean value of the config
334cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun     */
335cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun    private boolean isSkipCFFailToDisableDialog() {
336cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun        PersistableBundle carrierConfig =
337cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
338cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun        if (carrierConfig != null) {
339cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun            return carrierConfig.getBoolean(
340cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun                    CarrierConfigManager.KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL);
341cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun        } else {
342cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun            // by default we should not skip
343cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun            return false;
344cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun        }
345cb318288062c4f00ae36bcbb61c2089a7c6b17c2Ping Sun    }
3467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
347