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 
54     private final ArrayList<String> mBusyList = new ArrayList<String>();
55 
56     protected boolean mIsForeground = false;
57 
58     @Override
onCreateDialog(int id)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, mDismiss);
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
onResume()122     public void onResume() {
123         super.onResume();
124         mIsForeground = true;
125     }
126 
127     @Override
onPause()128     public void onPause() {
129         super.onPause();
130         mIsForeground = false;
131     }
132 
133     @Override
onStarted(Preference preference, boolean reading)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
onFinished(Preference preference, boolean reading)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
onError(Preference preference, int error)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
onException(Preference preference, CommandException exception)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
onCancel(DialogInterface dialog)189     public void onCancel(DialogInterface dialog) {
190         if (DBG) dumpState();
191         finish();
192     }
193 
dismissDialogSafely(int id)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 
dumpState()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