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