1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import android.app.ProgressDialog; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.AsyncTask; 24 import android.os.RecoverySystem; 25 import android.os.UserHandle; 26 import android.os.storage.StorageManager; 27 import android.text.TextUtils; 28 import android.util.Log; 29 import android.util.Slog; 30 import android.view.WindowManager; 31 32 import com.android.internal.R; 33 34 import java.io.IOException; 35 36 public class MasterClearReceiver extends BroadcastReceiver { 37 private static final String TAG = "MasterClear"; 38 private boolean mWipeExternalStorage; 39 private boolean mWipeEsims; 40 41 @Override onReceive(final Context context, final Intent intent)42 public void onReceive(final Context context, final Intent intent) { 43 if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) { 44 if (!"google.com".equals(intent.getStringExtra("from"))) { 45 Slog.w(TAG, "Ignoring master clear request -- not from trusted server."); 46 return; 47 } 48 } 49 if (Intent.ACTION_MASTER_CLEAR.equals(intent.getAction())) { 50 Slog.w(TAG, "The request uses the deprecated Intent#ACTION_MASTER_CLEAR, " 51 + "Intent#ACTION_FACTORY_RESET should be used instead."); 52 } 53 if (intent.hasExtra(Intent.EXTRA_FORCE_MASTER_CLEAR)) { 54 Slog.w(TAG, "The request uses the deprecated Intent#EXTRA_FORCE_MASTER_CLEAR, " 55 + "Intent#EXTRA_FORCE_FACTORY_RESET should be used instead."); 56 } 57 58 final String factoryResetPackage = context 59 .getString(com.android.internal.R.string.config_factoryResetPackage); 60 if (Intent.ACTION_FACTORY_RESET.equals(intent.getAction()) 61 && !TextUtils.isEmpty(factoryResetPackage)) { 62 intent.setPackage(factoryResetPackage).setComponent(null); 63 context.sendBroadcastAsUser(intent, UserHandle.SYSTEM); 64 return; 65 } 66 67 final boolean shutdown = intent.getBooleanExtra("shutdown", false); 68 final String reason = intent.getStringExtra(Intent.EXTRA_REASON); 69 mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false); 70 mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false); 71 final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false) 72 || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false); 73 74 Slog.w(TAG, "!!! FACTORY RESET !!!"); 75 // The reboot call is blocking, so we need to do it on another thread. 76 Thread thr = new Thread("Reboot") { 77 @Override 78 public void run() { 79 try { 80 RecoverySystem 81 .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims); 82 Log.wtf(TAG, "Still running after master clear?!"); 83 } catch (IOException e) { 84 Slog.e(TAG, "Can't perform master clear/factory reset", e); 85 } catch (SecurityException e) { 86 Slog.e(TAG, "Can't perform master clear/factory reset", e); 87 } 88 } 89 }; 90 91 if (mWipeExternalStorage) { 92 // thr will be started at the end of this task. 93 new WipeDataTask(context, thr).execute(); 94 } else { 95 thr.start(); 96 } 97 } 98 99 private class WipeDataTask extends AsyncTask<Void, Void, Void> { 100 private final Thread mChainedTask; 101 private final Context mContext; 102 private final ProgressDialog mProgressDialog; 103 WipeDataTask(Context context, Thread chainedTask)104 public WipeDataTask(Context context, Thread chainedTask) { 105 mContext = context; 106 mChainedTask = chainedTask; 107 mProgressDialog = new ProgressDialog(context); 108 } 109 110 @Override onPreExecute()111 protected void onPreExecute() { 112 mProgressDialog.setIndeterminate(true); 113 mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 114 mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing)); 115 mProgressDialog.show(); 116 } 117 118 @Override doInBackground(Void... params)119 protected Void doInBackground(Void... params) { 120 Slog.w(TAG, "Wiping adoptable disks"); 121 if (mWipeExternalStorage) { 122 StorageManager sm = (StorageManager) mContext.getSystemService( 123 Context.STORAGE_SERVICE); 124 sm.wipeAdoptableDisks(); 125 } 126 return null; 127 } 128 129 @Override onPostExecute(Void result)130 protected void onPostExecute(Void result) { 131 mProgressDialog.dismiss(); 132 mChainedTask.start(); 133 } 134 135 } 136 } 137