1package com.android.phone;
2
3import com.android.internal.telephony.CommandException;
4
5import android.app.AlertDialog;
6import android.app.Dialog;
7import android.app.ProgressDialog;
8import android.content.DialogInterface;
9import android.preference.Preference;
10import android.preference.PreferenceActivity;
11import android.util.Log;
12import android.view.WindowManager;
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 = "TimeConsumingPreferenceActivity";
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
57    private final ArrayList<String> mBusyList = new ArrayList<String>();
58
59    protected boolean mIsForeground = false;
60
61    @Override
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
138    public void onResume() {
139        super.onResume();
140        mIsForeground = true;
141    }
142
143    @Override
144    public void onPause() {
145        super.onPause();
146        mIsForeground = false;
147    }
148
149    @Override
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
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
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
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
207    public void onCancel(DialogInterface dialog) {
208        if (DBG) dumpState();
209        finish();
210    }
211
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
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