CrashRecoveryHandler.java revision cadae72b6309303bc7b22e85181222b73e176c32
1847b532045e3cb117a847ebb956c9919401f332dJohn Reck/* 2847b532045e3cb117a847ebb956c9919401f332dJohn Reck * Copyright (C) 2011 The Android Open Source Project 3847b532045e3cb117a847ebb956c9919401f332dJohn Reck * 4847b532045e3cb117a847ebb956c9919401f332dJohn Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5847b532045e3cb117a847ebb956c9919401f332dJohn Reck * you may not use this file except in compliance with the License. 6847b532045e3cb117a847ebb956c9919401f332dJohn Reck * You may obtain a copy of the License at 7847b532045e3cb117a847ebb956c9919401f332dJohn Reck * 8847b532045e3cb117a847ebb956c9919401f332dJohn Reck * http://www.apache.org/licenses/LICENSE-2.0 9847b532045e3cb117a847ebb956c9919401f332dJohn Reck * 10847b532045e3cb117a847ebb956c9919401f332dJohn Reck * Unless required by applicable law or agreed to in writing, software 11847b532045e3cb117a847ebb956c9919401f332dJohn Reck * distributed under the License is distributed on an "AS IS" BASIS, 12847b532045e3cb117a847ebb956c9919401f332dJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13847b532045e3cb117a847ebb956c9919401f332dJohn Reck * See the License for the specific language governing permissions and 14847b532045e3cb117a847ebb956c9919401f332dJohn Reck * limitations under the License. 15847b532045e3cb117a847ebb956c9919401f332dJohn Reck */ 16847b532045e3cb117a847ebb956c9919401f332dJohn Reck 17847b532045e3cb117a847ebb956c9919401f332dJohn Reckpackage com.android.browser; 18847b532045e3cb117a847ebb956c9919401f332dJohn Reck 19847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.app.AlertDialog; 20847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.content.Context; 21847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.content.DialogInterface; 220b3165d365baa066465f5ae95d93feeec75a0ef3John Reckimport android.content.DialogInterface.OnCancelListener; 23847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.content.DialogInterface.OnClickListener; 24847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.content.Intent; 25cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reckimport android.content.SharedPreferences; 26847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.os.Bundle; 27378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reckimport android.os.Handler; 28bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reckimport android.os.Message; 29847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.os.Parcel; 30847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport android.util.Log; 31847b532045e3cb117a847ebb956c9919401f332dJohn Reck 32847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport java.io.ByteArrayOutputStream; 33a4816530199095b8e7ad0ebd6ac9f22dff32ea2aJohn Reckimport java.io.File; 34847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport java.io.FileInputStream; 35847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport java.io.FileNotFoundException; 36847b532045e3cb117a847ebb956c9919401f332dJohn Reckimport java.io.FileOutputStream; 37847b532045e3cb117a847ebb956c9919401f332dJohn Reck 38847b532045e3cb117a847ebb956c9919401f332dJohn Reckpublic class CrashRecoveryHandler { 39847b532045e3cb117a847ebb956c9919401f332dJohn Reck 40847b532045e3cb117a847ebb956c9919401f332dJohn Reck private static final String LOGTAG = "BrowserCrashRecovery"; 41847b532045e3cb117a847ebb956c9919401f332dJohn Reck private static final String STATE_FILE = "browser_state.parcel"; 42cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck private static final String RECOVERY_PREFERENCES = "browser_recovery_prefs"; 43cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck private static final String KEY_LAST_RECOVERED = "last_recovered"; 44847b532045e3cb117a847ebb956c9919401f332dJohn Reck private static final int BUFFER_SIZE = 4096; 45378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private static final long BACKUP_DELAY = 500; // 500ms between writes 46cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck /* This is the duration for which we will prompt to restore 47cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck * instead of automatically restoring. The first time the browser crashes, 48cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck * we will automatically restore. If we then crash again within XX minutes, 49cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck * we will prompt instead of automatically restoring. 50cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck */ 51cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck private static final long PROMPT_INTERVAL = 30 * 60 * 1000; // 30 minutes 52378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 53bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private static final int MSG_WRITE_STATE = 1; 54bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private static final int MSG_CLEAR_STATE = 2; 55bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private static final int MSG_PRELOAD_STATE = 3; 56bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck 57378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private static CrashRecoveryHandler sInstance; 58847b532045e3cb117a847ebb956c9919401f332dJohn Reck 59847b532045e3cb117a847ebb956c9919401f332dJohn Reck private Controller mController; 60bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private Context mContext; 61378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private Handler mForegroundHandler; 62378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private Handler mBackgroundHandler; 63bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private boolean mIsPreloading = false; 64bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private boolean mDidPreload = false; 65bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private boolean mShouldPrompt = false; 66bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private Bundle mRecoveryState = null; 67378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 68378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck public static CrashRecoveryHandler initialize(Controller controller) { 69378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck if (sInstance == null) { 70378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck sInstance = new CrashRecoveryHandler(controller); 71378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } else { 72378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck sInstance.mController = controller; 73378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } 74378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck return sInstance; 75378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } 76847b532045e3cb117a847ebb956c9919401f332dJohn Reck 77378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck public static CrashRecoveryHandler getInstance() { 78378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck return sInstance; 79378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } 80378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 81378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private CrashRecoveryHandler(Controller controller) { 82847b532045e3cb117a847ebb956c9919401f332dJohn Reck mController = controller; 83bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mContext = mController.getActivity().getApplicationContext(); 84378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck mForegroundHandler = new Handler(); 85cadae72b6309303bc7b22e85181222b73e176c32John Reck mBackgroundHandler = new Handler(BackgroundHandler.getLooper()) { 86bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck 87bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck @Override 88bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck public void handleMessage(Message msg) { 89bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck switch (msg.what) { 90bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck case MSG_WRITE_STATE: 91bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck Parcel p = Parcel.obtain(); 92bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck try { 93bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck Bundle state = (Bundle) msg.obj; 94bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck state.writeToParcel(p, 0); 95bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck File stateFile = new File(mContext.getCacheDir(), STATE_FILE); 96bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck FileOutputStream fout = new FileOutputStream(stateFile); 97bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck fout.write(p.marshall()); 98bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck fout.close(); 99bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } catch (Throwable e) { 100bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck Log.i(LOGTAG, "Failed to save persistent state", e); 101bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } finally { 102bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck p.recycle(); 103bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 104bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck break; 105bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck case MSG_CLEAR_STATE: 106bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck File state = new File(mContext.getCacheDir(), STATE_FILE); 107bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck if (state.exists()) { 108bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck state.delete(); 109bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 110bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck break; 111bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck case MSG_PRELOAD_STATE: 112bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mRecoveryState = loadCrashState(); 113bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mShouldPrompt = shouldPrompt(); 114bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck synchronized (CrashRecoveryHandler.this) { 115bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mIsPreloading = false; 116bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mDidPreload = true; 117bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck CrashRecoveryHandler.this.notifyAll(); 118bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 119bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck break; 120bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 121bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 122bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck }; 123847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 124847b532045e3cb117a847ebb956c9919401f332dJohn Reck 125847b532045e3cb117a847ebb956c9919401f332dJohn Reck public void backupState() { 126378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck mForegroundHandler.postDelayed(mCreateState, BACKUP_DELAY); 127378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } 128378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 129378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck private Runnable mCreateState = new Runnable() { 130378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 131378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck @Override 132378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck public void run() { 133378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck try { 134378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck final Bundle state = new Bundle(); 135378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck mController.onSaveInstanceState(state, false); 136bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck Message.obtain(mBackgroundHandler, MSG_WRITE_STATE, state) 137bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck .sendToTarget(); 138378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck // Remove any queued up saves 139378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck mForegroundHandler.removeCallbacks(mCreateState); 140378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } catch (Throwable t) { 141378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck Log.w(LOGTAG, "Failed to save state", t); 142378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck return; 143847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 144378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck } 145378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 146378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck }; 147378a41055fab6c521cdc1d9b2cfeefff2af19e7cJohn Reck 148bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck public void clearState() { 149bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mBackgroundHandler.sendEmptyMessage(MSG_CLEAR_STATE); 150847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 151847b532045e3cb117a847ebb956c9919401f332dJohn Reck 152847b532045e3cb117a847ebb956c9919401f332dJohn Reck public void promptToRecover(final Bundle state, final Intent intent) { 153847b532045e3cb117a847ebb956c9919401f332dJohn Reck new AlertDialog.Builder(mController.getActivity()) 154847b532045e3cb117a847ebb956c9919401f332dJohn Reck .setTitle(R.string.recover_title) 155847b532045e3cb117a847ebb956c9919401f332dJohn Reck .setMessage(R.string.recover_prompt) 15624f1826440334ba8a3d2453699c51c1a4b117c7bJohn Reck .setIcon(R.mipmap.ic_launcher_browser) 157847b532045e3cb117a847ebb956c9919401f332dJohn Reck .setPositiveButton(R.string.recover_yes, new OnClickListener() { 158847b532045e3cb117a847ebb956c9919401f332dJohn Reck @Override 159847b532045e3cb117a847ebb956c9919401f332dJohn Reck public void onClick(DialogInterface dialog, int which) { 160cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck updateLastRecovered(); 161847b532045e3cb117a847ebb956c9919401f332dJohn Reck mController.doStart(state, intent); 162847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 163847b532045e3cb117a847ebb956c9919401f332dJohn Reck }) 164847b532045e3cb117a847ebb956c9919401f332dJohn Reck .setNegativeButton(R.string.recover_no, new OnClickListener() { 165847b532045e3cb117a847ebb956c9919401f332dJohn Reck @Override 166847b532045e3cb117a847ebb956c9919401f332dJohn Reck public void onClick(DialogInterface dialog, int which) { 1670b3165d365baa066465f5ae95d93feeec75a0ef3John Reck dialog.cancel(); 1680b3165d365baa066465f5ae95d93feeec75a0ef3John Reck } 1690b3165d365baa066465f5ae95d93feeec75a0ef3John Reck }) 1700b3165d365baa066465f5ae95d93feeec75a0ef3John Reck .setOnCancelListener(new OnCancelListener() { 1710b3165d365baa066465f5ae95d93feeec75a0ef3John Reck @Override 1720b3165d365baa066465f5ae95d93feeec75a0ef3John Reck public void onCancel(DialogInterface dialog) { 173bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck clearState(); 174847b532045e3cb117a847ebb956c9919401f332dJohn Reck mController.doStart(null, intent); 175847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 176847b532045e3cb117a847ebb956c9919401f332dJohn Reck }) 177847b532045e3cb117a847ebb956c9919401f332dJohn Reck .show(); 178847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 179847b532045e3cb117a847ebb956c9919401f332dJohn Reck 180cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck private boolean shouldPrompt() { 181bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck SharedPreferences prefs = mContext.getSharedPreferences( 182cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck RECOVERY_PREFERENCES, Context.MODE_PRIVATE); 183bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck long lastRecovered = prefs.getLong(KEY_LAST_RECOVERED, 0); 184cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck long timeSinceLastRecover = System.currentTimeMillis() - lastRecovered; 185cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck if (timeSinceLastRecover > PROMPT_INTERVAL) { 186cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck return false; 187cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck } 188cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck return true; 189cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck } 190cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck 191cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck private void updateLastRecovered() { 192bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck SharedPreferences prefs = mContext.getSharedPreferences( 193cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck RECOVERY_PREFERENCES, Context.MODE_PRIVATE); 194cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck prefs.edit() 195cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck .putLong(KEY_LAST_RECOVERED, System.currentTimeMillis()) 196cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck .commit(); 197cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck } 198cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck 199bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck private Bundle loadCrashState() { 200cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck Bundle state = null; 201847b532045e3cb117a847ebb956c9919401f332dJohn Reck Parcel parcel = Parcel.obtain(); 202847b532045e3cb117a847ebb956c9919401f332dJohn Reck try { 203bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck File stateFile = new File(mContext.getCacheDir(), STATE_FILE); 204a4816530199095b8e7ad0ebd6ac9f22dff32ea2aJohn Reck FileInputStream fin = new FileInputStream(stateFile); 205847b532045e3cb117a847ebb956c9919401f332dJohn Reck ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 206847b532045e3cb117a847ebb956c9919401f332dJohn Reck byte[] buffer = new byte[BUFFER_SIZE]; 207847b532045e3cb117a847ebb956c9919401f332dJohn Reck int read; 208847b532045e3cb117a847ebb956c9919401f332dJohn Reck while ((read = fin.read(buffer)) > 0) { 209847b532045e3cb117a847ebb956c9919401f332dJohn Reck dataStream.write(buffer, 0, read); 210847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 211847b532045e3cb117a847ebb956c9919401f332dJohn Reck byte[] data = dataStream.toByteArray(); 212847b532045e3cb117a847ebb956c9919401f332dJohn Reck parcel.unmarshall(data, 0, data.length); 213847b532045e3cb117a847ebb956c9919401f332dJohn Reck parcel.setDataPosition(0); 214cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck state = parcel.readBundle(); 215847b532045e3cb117a847ebb956c9919401f332dJohn Reck } catch (FileNotFoundException e) { 216847b532045e3cb117a847ebb956c9919401f332dJohn Reck // No state to recover 217cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck state = null; 218bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } catch (Throwable e) { 219847b532045e3cb117a847ebb956c9919401f332dJohn Reck Log.w(LOGTAG, "Failed to recover state!", e); 220cfeae6d3dc6f62f2d475bf50c0fc26a0e9c730deJohn Reck state = null; 221847b532045e3cb117a847ebb956c9919401f332dJohn Reck } finally { 222847b532045e3cb117a847ebb956c9919401f332dJohn Reck parcel.recycle(); 223847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 224bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck return state; 225bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 226bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck 227bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck public void startRecovery(Intent intent) { 228bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck synchronized (CrashRecoveryHandler.this) { 229bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck while (mIsPreloading) { 230bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck try { 231bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck CrashRecoveryHandler.this.wait(); 232bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } catch (InterruptedException e) {} 233bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 234bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 235bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck if (!mDidPreload) { 236bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mRecoveryState = loadCrashState(); 237bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mShouldPrompt = shouldPrompt(); 238bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 239bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck if (mShouldPrompt) { 240bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck promptToRecover(mRecoveryState, intent); 241bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck return; 242bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } else { 243bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck updateLastRecovered(); 244bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 245bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mController.doStart(mRecoveryState, intent); 246bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mRecoveryState = null; 247847b532045e3cb117a847ebb956c9919401f332dJohn Reck } 248bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck 249bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck public void preloadCrashState() { 250bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck synchronized (CrashRecoveryHandler.this) { 251bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck if (mIsPreloading) { 252bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck return; 253bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 254bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mIsPreloading = true; 255bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 256bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck mBackgroundHandler.sendEmptyMessage(MSG_PRELOAD_STATE); 257bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck } 258bc490d2c32aac4e12069be1b92bfaf185ff5dbb5John Reck 259847b532045e3cb117a847ebb956c9919401f332dJohn Reck} 260