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 { 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 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 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, 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 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