• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CallForwardEditPreference(Context context, AttributeSet attrs)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 
CallForwardEditPreference(Context context)60     public CallForwardEditPreference(Context context) {
61         this(context, null);
62     }
63 
init(TimeConsumingPreferenceListener listener, boolean skipReading)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
onBindDialogView(View view)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
onClick(DialogInterface dialog, int which)86     public void onClick(DialogInterface dialog, int which) {
87         super.onClick(dialog, which);
88         mButtonClicked = which;
89     }
90 
91     @Override
onDialogClosed(boolean positiveResult)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 
handleCallForwardResult(CallForwardInfo cf)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 
updateSummaryText()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
handleMessage(Message msg)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 
handleGetCFResponse(Message msg)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 
handleSetCFResponse(Message msg)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