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