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