1package com.android.phone;
2
3import android.app.AlertDialog;
4import android.app.Dialog;
5import android.app.ProgressDialog;
6import android.content.DialogInterface;
7import android.preference.Preference;
8import android.preference.PreferenceActivity;
9import android.util.Log;
10import android.view.WindowManager;
11
12import com.android.internal.telephony.CommandException;
13
14import java.util.ArrayList;
15
16interface  TimeConsumingPreferenceListener {
17    public void onStarted(Preference preference, boolean reading);
18    public void onFinished(Preference preference, boolean reading);
19    public void onError(Preference preference, int error);
20    public void onException(Preference preference, CommandException exception);
21}
22
23public 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
31        public void onClick(DialogInterface dialog, int which) {
32            dialog.dismiss();
33        }
34    }
35    private class DismissAndFinishOnClickListener implements DialogInterface.OnClickListener {
36        @Override
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
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
144    public void onResume() {
145        super.onResume();
146        mIsForeground = true;
147    }
148
149    @Override
150    public void onPause() {
151        super.onPause();
152        mIsForeground = false;
153    }
154
155    @Override
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
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
188    public void onError(Preference preference, int error) {
189        if (DBG) dumpState();
190        Log.i(LOG_TAG, "onError, preference=" + preference.getKey() + ", error=" + error);
191
192        if (mIsForeground) {
193            showDialog(error);
194        }
195        preference.setEnabled(false);
196    }
197
198    @Override
199    public void onException(Preference preference, CommandException exception) {
200        if (exception.getCommandError() == CommandException.Error.FDN_CHECK_FAILURE) {
201            onError(preference, FDN_CHECK_FAILURE);
202        } else if (exception.getCommandError() == CommandException.Error.RADIO_NOT_AVAILABLE) {
203            onError(preference, RADIO_OFF_ERROR);
204        } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_DIAL) {
205            onError(preference, STK_CC_SS_TO_DIAL_ERROR);
206        } else if (exception.getCommandError() == CommandException.Error
207                .SS_MODIFIED_TO_DIAL_VIDEO) {
208            onError(preference, STK_CC_SS_TO_DIAL_VIDEO_ERROR);
209        } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_USSD) {
210            onError(preference, STK_CC_SS_TO_USSD_ERROR);
211        } else if (exception.getCommandError() == CommandException.Error.SS_MODIFIED_TO_SS) {
212            onError(preference, STK_CC_SS_TO_SS_ERROR);
213        } else {
214            preference.setEnabled(false);
215            onError(preference, EXCEPTION_ERROR);
216        }
217    }
218
219    @Override
220    public void onCancel(DialogInterface dialog) {
221        if (DBG) dumpState();
222        finish();
223    }
224
225    private void dismissDialogSafely(int id) {
226        try {
227            dismissDialog(id);
228        } catch (IllegalArgumentException e) {
229            // This is expected in the case where we were in the background
230            // at the time we would normally have shown the dialog, so we didn't
231            // show it.
232        }
233    }
234
235    /* package */ void dumpState() {
236        Log.d(LOG_TAG, "dumpState begin");
237        for (String key : mBusyList) {
238            Log.d(LOG_TAG, "mBusyList: key=" + key);
239        }
240        Log.d(LOG_TAG, "dumpState end");
241    }
242}
243