1 package com.android.phone;
2 
3 import com.android.internal.telephony.CommandException;
4 
5 import android.app.AlertDialog;
6 import android.app.Dialog;
7 import android.app.ProgressDialog;
8 import android.content.DialogInterface;
9 import android.preference.Preference;
10 import android.preference.PreferenceActivity;
11 import android.util.Log;
12 import android.view.WindowManager;
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 = "TimeConsumingPreferenceActivity";
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 
57     private final ArrayList<String> mBusyList = new ArrayList<String>();
58 
59     protected boolean mIsForeground = false;
60 
61     @Override
onCreateDialog(int id)62     protected Dialog onCreateDialog(int id) {
63         if (id == BUSY_READING_DIALOG || id == BUSY_SAVING_DIALOG) {
64             ProgressDialog dialog = new ProgressDialog(this);
65             dialog.setTitle(getText(R.string.updating_title));
66             dialog.setIndeterminate(true);
67 
68             switch(id) {
69                 case BUSY_READING_DIALOG:
70                     dialog.setCancelable(true);
71                     dialog.setOnCancelListener(this);
72                     dialog.setMessage(getText(R.string.reading_settings));
73                     return dialog;
74                 case BUSY_SAVING_DIALOG:
75                     dialog.setCancelable(false);
76                     dialog.setMessage(getText(R.string.updating_settings));
77                     return dialog;
78             }
79             return null;
80         }
81 
82         if (id == RESPONSE_ERROR || id == RADIO_OFF_ERROR || id == EXCEPTION_ERROR
83                 || id == FDN_CHECK_FAILURE || id == STK_CC_SS_TO_DIAL_ERROR
84                 || id == STK_CC_SS_TO_USSD_ERROR || id == STK_CC_SS_TO_SS_ERROR) {
85             AlertDialog.Builder builder = new AlertDialog.Builder(this);
86 
87             int msgId;
88             int titleId = R.string.error_updating_title;
89 
90             switch (id) {
91                 case RESPONSE_ERROR:
92                     msgId = R.string.response_error;
93                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
94                     break;
95                 case RADIO_OFF_ERROR:
96                     msgId = R.string.radio_off_error;
97                     // The error is not recoverable on dialog exit.
98                     builder.setPositiveButton(R.string.close_dialog, mDismissAndFinish);
99                     break;
100                 case FDN_CHECK_FAILURE:
101                     msgId = R.string.fdn_check_failure;
102                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
103                     break;
104                 case STK_CC_SS_TO_DIAL_ERROR:
105                     msgId = R.string.stk_cc_ss_to_dial_error;
106                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
107                     break;
108                 case STK_CC_SS_TO_USSD_ERROR:
109                     msgId = R.string.stk_cc_ss_to_ussd_error;
110                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
111                     break;
112                 case STK_CC_SS_TO_SS_ERROR:
113                     msgId = R.string.stk_cc_ss_to_ss_error;
114                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
115                     break;
116                 case EXCEPTION_ERROR:
117                 default:
118                     msgId = R.string.exception_error;
119                     // The error is not recoverable on dialog exit.
120                     builder.setPositiveButton(R.string.close_dialog, mDismiss);
121                     break;
122             }
123 
124             builder.setTitle(getText(titleId));
125             builder.setMessage(getText(msgId));
126             builder.setCancelable(false);
127             AlertDialog dialog = builder.create();
128 
129             // make the dialog more obvious by blurring the background.
130             dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
131 
132             return dialog;
133         }
134         return null;
135     }
136 
137     @Override
onResume()138     public void onResume() {
139         super.onResume();
140         mIsForeground = true;
141     }
142 
143     @Override
onPause()144     public void onPause() {
145         super.onPause();
146         mIsForeground = false;
147     }
148 
149     @Override
onStarted(Preference preference, boolean reading)150     public void onStarted(Preference preference, boolean reading) {
151         if (DBG) dumpState();
152         if (DBG) Log.d(LOG_TAG, "onStarted, preference=" + preference.getKey()
153                 + ", reading=" + reading);
154         mBusyList.add(preference.getKey());
155 
156         if (mIsForeground) {
157               if (reading) {
158                   showDialog(BUSY_READING_DIALOG);
159               } else {
160                   showDialog(BUSY_SAVING_DIALOG);
161               }
162         }
163 
164     }
165 
166     @Override
onFinished(Preference preference, boolean reading)167     public void onFinished(Preference preference, boolean reading) {
168         if (DBG) dumpState();
169         if (DBG) Log.d(LOG_TAG, "onFinished, preference=" + preference.getKey()
170                 + ", reading=" + reading);
171         mBusyList.remove(preference.getKey());
172 
173         if (mBusyList.isEmpty()) {
174             if (reading) {
175                 dismissDialogSafely(BUSY_READING_DIALOG);
176             } else {
177                 dismissDialogSafely(BUSY_SAVING_DIALOG);
178             }
179         }
180         preference.setEnabled(true);
181     }
182 
183     @Override
onError(Preference preference, int error)184     public void onError(Preference preference, int error) {
185         if (DBG) dumpState();
186         if (DBG) Log.d(LOG_TAG, "onError, preference=" + preference.getKey() + ", error=" + error);
187 
188         if (mIsForeground) {
189             showDialog(error);
190         }
191         preference.setEnabled(false);
192     }
193 
194     @Override
onException(Preference preference, CommandException exception)195     public void onException(Preference preference, CommandException exception) {
196         if (exception.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
197             onError(preference, FDN_CHECK_FAILURE);
198         } else if (exception.getCommandError() == CommandException.Error.RADIO_NOT_AVAILABLE) {
199             onError(preference, RADIO_OFF_ERROR);
200         } else {
201             preference.setEnabled(false);
202             onError(preference, EXCEPTION_ERROR);
203         }
204     }
205 
206     @Override
onCancel(DialogInterface dialog)207     public void onCancel(DialogInterface dialog) {
208         if (DBG) dumpState();
209         finish();
210     }
211 
dismissDialogSafely(int id)212     private void dismissDialogSafely(int id) {
213         try {
214             dismissDialog(id);
215         } catch (IllegalArgumentException e) {
216             // This is expected in the case where we were in the background
217             // at the time we would normally have shown the dialog, so we didn't
218             // show it.
219         }
220     }
221 
dumpState()222     /* package */ void dumpState() {
223         Log.d(LOG_TAG, "dumpState begin");
224         for (String key : mBusyList) {
225             Log.d(LOG_TAG, "mBusyList: key=" + key);
226         }
227         Log.d(LOG_TAG, "dumpState end");
228     }
229 }
230