1 package com.android.phone;
2 
3 import android.app.AlertDialog;
4 import android.app.Dialog;
5 import android.app.ProgressDialog;
6 import android.content.DialogInterface;
7 import android.preference.Preference;
8 import android.preference.PreferenceActivity;
9 import android.util.Log;
10 import android.view.WindowManager;
11 
12 import com.android.internal.telephony.CommandException;
13 
14 import java.util.ArrayList;
15 
16 interface  TimeConsumingPreferenceListener {
onStarted(Preference preference, boolean reading)17     public void onStarted(Preference preference, boolean reading);
onFinished(Preference preference, boolean reading)18     public void onFinished(Preference preference, boolean reading);
onError(Preference preference, int error)19     public void onError(Preference preference, int error);
onException(Preference preference, CommandException exception)20     public void onException(Preference preference, CommandException exception);
21 }
22 
23 public class TimeConsumingPreferenceActivity extends PreferenceActivity
24                         implements TimeConsumingPreferenceListener,
25                         DialogInterface.OnCancelListener {
26     private static final String LOG_TAG = "TimeConsumingPrefActivity";
27     private final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
28 
29     private class DismissOnClickListener implements DialogInterface.OnClickListener {
30         @Override
onClick(DialogInterface dialog, int which)31         public void onClick(DialogInterface dialog, int which) {
32             dialog.dismiss();
33         }
34     }
35     private class DismissAndFinishOnClickListener implements DialogInterface.OnClickListener {
36         @Override
onClick(DialogInterface dialog, int which)37         public void onClick(DialogInterface dialog, int which) {
38             dialog.dismiss();
39             finish();
40         }
41     }
42     private final DialogInterface.OnClickListener mDismiss = new DismissOnClickListener();
43     private final DialogInterface.OnClickListener mDismissAndFinish
44             = new DismissAndFinishOnClickListener();
45 
46     private static final int BUSY_READING_DIALOG = 100;
47     private static final int BUSY_SAVING_DIALOG = 200;
48 
49     static final int EXCEPTION_ERROR = 300;
50     static final int RESPONSE_ERROR = 400;
51     static final int RADIO_OFF_ERROR = 500;
52     static final int FDN_CHECK_FAILURE = 600;
53     static final int STK_CC_SS_TO_DIAL_ERROR = 700;
54     static final int STK_CC_SS_TO_USSD_ERROR = 800;
55     static final int STK_CC_SS_TO_SS_ERROR = 900;
56     static final int STK_CC_SS_TO_DIAL_VIDEO_ERROR = 1000;
57 
58     private final ArrayList<String> mBusyList = new ArrayList<String>();
59 
60     protected boolean mIsForeground = false;
61 
62     @Override
onCreateDialog(int id)63     protected Dialog onCreateDialog(int id) {
64         if (id == BUSY_READING_DIALOG || id == BUSY_SAVING_DIALOG) {
65             ProgressDialog dialog = new ProgressDialog(this);
66             dialog.setTitle(getText(R.string.updating_title));
67             dialog.setIndeterminate(true);
68 
69             switch(id) {
70                 case BUSY_READING_DIALOG:
71                     dialog.setCancelable(true);
72                     dialog.setOnCancelListener(this);
73                     dialog.setMessage(getText(R.string.reading_settings));
74                     return dialog;
75                 case BUSY_SAVING_DIALOG:
76                     dialog.setCancelable(false);
77                     dialog.setMessage(getText(R.string.updating_settings));
78                     return dialog;
79             }
80             return null;
81         }
82 
83         if (id == RESPONSE_ERROR || id == RADIO_OFF_ERROR || id == EXCEPTION_ERROR
84                 || id == FDN_CHECK_FAILURE || id == STK_CC_SS_TO_DIAL_ERROR
85                 || id == STK_CC_SS_TO_USSD_ERROR || id == STK_CC_SS_TO_SS_ERROR
86                 || id == STK_CC_SS_TO_DIAL_VIDEO_ERROR) {
87             AlertDialog.Builder builder = new AlertDialog.Builder(this);
88 
89             int msgId;
90             int titleId = R.string.error_updating_title;
91 
92             switch (id) {
93                 case RESPONSE_ERROR:
94                     msgId = R.string.response_error;
95                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
96                     break;
97                 case RADIO_OFF_ERROR:
98                     msgId = R.string.radio_off_error;
99                     // The error is not recoverable on dialog exit.
100                     builder.setPositiveButton(R.string.close_dialog, mDismissAndFinish);
101                     break;
102                 case FDN_CHECK_FAILURE:
103                     msgId = R.string.fdn_check_failure;
104                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
105                     break;
106                 case STK_CC_SS_TO_DIAL_ERROR:
107                     msgId = R.string.stk_cc_ss_to_dial_error;
108                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
109                     break;
110                 case STK_CC_SS_TO_USSD_ERROR:
111                     msgId = R.string.stk_cc_ss_to_ussd_error;
112                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
113                     break;
114                 case STK_CC_SS_TO_SS_ERROR:
115                     msgId = R.string.stk_cc_ss_to_ss_error;
116                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
117                     break;
118                 case STK_CC_SS_TO_DIAL_VIDEO_ERROR:
119                     msgId = R.string.stk_cc_ss_to_dial_video_error;
120                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
121                     break;
122                 case EXCEPTION_ERROR:
123                 default:
124                     msgId = R.string.exception_error;
125                     // The error is not recoverable on dialog exit.
126                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
127                     break;
128             }
129 
130             builder.setTitle(getText(titleId));
131             builder.setMessage(getText(msgId));
132             builder.setCancelable(false);
133             AlertDialog dialog = builder.create();
134 
135             // make the dialog more obvious by blurring the background.
136             dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
137 
138             return dialog;
139         }
140         return null;
141     }
142 
143     @Override
onResume()144     public void onResume() {
145         super.onResume();
146         mIsForeground = true;
147     }
148 
149     @Override
onPause()150     public void onPause() {
151         super.onPause();
152         mIsForeground = false;
153     }
154 
155     @Override
onStarted(Preference preference, boolean reading)156     public void onStarted(Preference preference, boolean reading) {
157         if (DBG) dumpState();
158         Log.i(LOG_TAG, "onStarted, preference=" + preference.getKey() + ", reading=" + reading);
159         mBusyList.add(preference.getKey());
160 
161         if (mIsForeground) {
162               if (reading) {
163                   showDialog(BUSY_READING_DIALOG);
164               } else {
165                   showDialog(BUSY_SAVING_DIALOG);
166               }
167         }
168 
169     }
170 
171     @Override
onFinished(Preference preference, boolean reading)172     public void onFinished(Preference preference, boolean reading) {
173         if (DBG) dumpState();
174         Log.i(LOG_TAG, "onFinished, preference=" + preference.getKey() + ", reading=" + reading);
175         mBusyList.remove(preference.getKey());
176 
177         if (mBusyList.isEmpty()) {
178             if (reading) {
179                 dismissDialogSafely(BUSY_READING_DIALOG);
180             } else {
181                 dismissDialogSafely(BUSY_SAVING_DIALOG);
182             }
183         }
184         preference.setEnabled(true);
185     }
186 
187     @Override
onError(Preference preference, int error)188     public void onError(Preference preference, int error) {
189         if (DBG) dumpState();
190         if (!preference.isEnabled()) {
191             Log.i(LOG_TAG, "onError, skipped duplicated error popup");
192             return;
193         }
194 
195         Log.i(LOG_TAG, "onError, preference=" + preference.getKey() + ", error=" + error);
196 
197         if (mIsForeground) {
198             showDialog(error);
199         }
200         preference.setEnabled(false);
201     }
202 
203     @Override
onException(Preference preference, CommandException exception)204     public void onException(Preference preference, CommandException exception) {
205         if (exception.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
206             onError(preference, FDN_CHECK_FAILURE);
207         } else if (exception.getCommandError() == CommandException.Error.RADIO_NOT_AVAILABLE) {
208             onError(preference, RADIO_OFF_ERROR);
209         } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_DIAL) {
210             onError(preference, STK_CC_SS_TO_DIAL_ERROR);
211         } else if (exception.getCommandError() == CommandException.Error
212                 .SS_MODIFIED_TO_DIAL_VIDEO) {
213             onError(preference, STK_CC_SS_TO_DIAL_VIDEO_ERROR);
214         } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_USSD) {
215             onError(preference, STK_CC_SS_TO_USSD_ERROR);
216         } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_SS) {
217             onError(preference, STK_CC_SS_TO_SS_ERROR);
218         } else {
219             preference.setEnabled(false);
220             onError(preference, EXCEPTION_ERROR);
221         }
222     }
223 
224     @Override
onCancel(DialogInterface dialog)225     public void onCancel(DialogInterface dialog) {
226         if (DBG) dumpState();
227         finish();
228     }
229 
dismissDialogSafely(int id)230     protected void dismissDialogSafely(int id) {
231         try {
232             dismissDialog(id);
233         } catch (IllegalArgumentException e) {
234             // This is expected in the case where we were in the background
235             // at the time we would normally have shown the dialog, so we didn't
236             // show it.
237         }
238     }
239 
dumpState()240     /* package */ void dumpState() {
241         Log.d(LOG_TAG, "dumpState begin");
242         for (String key : mBusyList) {
243             Log.d(LOG_TAG, "mBusyList: key=" + key);
244         }
245         Log.d(LOG_TAG, "dumpState end");
246     }
247 }
248