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.PendingIntent;
20 import android.app.ProgressDialog;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.os.AsyncTask;
25 import android.os.RecoverySystem;
26 import android.os.storage.StorageManager;
27 import android.provider.Settings;
28 import android.telephony.euicc.EuiccManager;
29 import android.util.Log;
30 import android.util.Slog;
31 import android.view.WindowManager;
32 
33 import com.android.internal.R;
34 
35 import java.io.IOException;
36 import java.util.concurrent.CountDownLatch;
37 import java.util.concurrent.TimeUnit;
38 
39 public class MasterClearReceiver extends BroadcastReceiver {
40     private static final String TAG = "MasterClear";
41     private boolean mWipeExternalStorage;
42     private boolean mWipeEsims;
43 
44     @Override
onReceive(final Context context, final Intent intent)45     public void onReceive(final Context context, final Intent intent) {
46         if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
47             if (!"google.com".equals(intent.getStringExtra("from"))) {
48                 Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");
49                 return;
50             }
51         }
52         if (Intent.ACTION_MASTER_CLEAR.equals(intent.getAction())) {
53             Slog.w(TAG, "The request uses the deprecated Intent#ACTION_MASTER_CLEAR, "
54                     + "Intent#ACTION_FACTORY_RESET should be used instead.");
55         }
56         if (intent.hasExtra(Intent.EXTRA_FORCE_MASTER_CLEAR)) {
57             Slog.w(TAG, "The request uses the deprecated Intent#EXTRA_FORCE_MASTER_CLEAR, "
58                     + "Intent#EXTRA_FORCE_FACTORY_RESET should be used instead.");
59         }
60 
61         final boolean shutdown = intent.getBooleanExtra("shutdown", false);
62         final String reason = intent.getStringExtra(Intent.EXTRA_REASON);
63         mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
64         mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);
65         final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
66                 || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);
67 
68         Slog.w(TAG, "!!! FACTORY RESET !!!");
69         // The reboot call is blocking, so we need to do it on another thread.
70         Thread thr = new Thread("Reboot") {
71             @Override
72             public void run() {
73                 try {
74                     RecoverySystem
75                             .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);
76                     Log.wtf(TAG, "Still running after master clear?!");
77                 } catch (IOException e) {
78                     Slog.e(TAG, "Can't perform master clear/factory reset", e);
79                 } catch (SecurityException e) {
80                     Slog.e(TAG, "Can't perform master clear/factory reset", e);
81                 }
82             }
83         };
84 
85         if (mWipeExternalStorage) {
86             // thr will be started at the end of this task.
87             new WipeDataTask(context, thr).execute();
88         } else {
89             thr.start();
90         }
91     }
92 
93     private class WipeDataTask extends AsyncTask<Void, Void, Void> {
94         private final Thread mChainedTask;
95         private final Context mContext;
96         private final ProgressDialog mProgressDialog;
97 
WipeDataTask(Context context, Thread chainedTask)98         public WipeDataTask(Context context, Thread chainedTask) {
99             mContext = context;
100             mChainedTask = chainedTask;
101             mProgressDialog = new ProgressDialog(context);
102         }
103 
104         @Override
onPreExecute()105         protected void onPreExecute() {
106             mProgressDialog.setIndeterminate(true);
107             mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
108             mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));
109             mProgressDialog.show();
110         }
111 
112         @Override
doInBackground(Void... params)113         protected Void doInBackground(Void... params) {
114             Slog.w(TAG, "Wiping adoptable disks");
115             if (mWipeExternalStorage) {
116                 StorageManager sm = (StorageManager) mContext.getSystemService(
117                         Context.STORAGE_SERVICE);
118                 sm.wipeAdoptableDisks();
119             }
120             return null;
121         }
122 
123         @Override
onPostExecute(Void result)124         protected void onPostExecute(Void result) {
125             mProgressDialog.dismiss();
126             mChainedTask.start();
127         }
128 
129     }
130 }
131