• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.settings;
18 
19 
20 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
21 
22 import android.app.ActionBar;
23 import android.app.Activity;
24 import android.app.ProgressDialog;
25 import android.app.settings.SettingsEnums;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.ActivityInfo;
29 import android.graphics.Color;
30 import android.os.AsyncTask;
31 import android.os.Bundle;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.service.oemlock.OemLockManager;
35 import android.service.persistentdata.PersistentDataBlockManager;
36 import android.util.Log;
37 import android.view.LayoutInflater;
38 import android.view.View;
39 import android.view.ViewGroup;
40 import android.widget.Button;
41 import android.widget.TextView;
42 
43 import androidx.annotation.VisibleForTesting;
44 
45 import com.android.settings.core.InstrumentedFragment;
46 import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
47 import com.android.settingslib.RestrictedLockUtilsInternal;
48 
49 import com.google.android.setupcompat.template.FooterBarMixin;
50 import com.google.android.setupcompat.template.FooterButton;
51 import com.google.android.setupcompat.template.FooterButton.ButtonType;
52 import com.google.android.setupdesign.GlifLayout;
53 
54 /**
55  * Confirm and execute a reset of the device to a clean "just out of the box"
56  * state.  Multiple confirmations are required: first, a general "are you sure
57  * you want to do this?" prompt, followed by a keyguard pattern trace if the user
58  * has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING
59  * ON THE PHONE" prompt.  If at any time the phone is allowed to go to sleep, is
60  * locked, et cetera, then the confirmation sequence is abandoned.
61  *
62  * This is the confirmation screen.
63  */
64 public class MasterClearConfirm extends InstrumentedFragment {
65     private final static String TAG = "MasterClearConfirm";
66 
67     @VisibleForTesting View mContentView;
68     private boolean mEraseSdCard;
69     @VisibleForTesting boolean mEraseEsims;
70 
71     /**
72      * The user has gone through the multiple confirmation, so now we go ahead
73      * and invoke the Checkin Service to reset the device to its factory-default
74      * state (rebooting in the process).
75      */
76     private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
77 
78         public void onClick(View v) {
79             if (Utils.isMonkeyRunning()) {
80                 return;
81             }
82 
83             final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
84                     getActivity().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
85             final OemLockManager oemLockManager = (OemLockManager)
86                     getActivity().getSystemService(Context.OEM_LOCK_SERVICE);
87 
88             if (pdbManager != null && !oemLockManager.isOemUnlockAllowed() &&
89                     Utils.isDeviceProvisioned(getActivity())) {
90                 // if OEM unlock is allowed, the persistent data block will be wiped during FR
91                 // process. If disabled, it will be wiped here, unless the device is still being
92                 // provisioned, in which case the persistent data block will be preserved.
93                 new AsyncTask<Void, Void, Void>() {
94                     int mOldOrientation;
95                     ProgressDialog mProgressDialog;
96 
97                     @Override
98                     protected Void doInBackground(Void... params) {
99                         pdbManager.wipe();
100                         return null;
101                     }
102 
103                     @Override
104                     protected void onPostExecute(Void aVoid) {
105                         mProgressDialog.hide();
106                         if (getActivity() != null) {
107                             getActivity().setRequestedOrientation(mOldOrientation);
108                             doMasterClear();
109                         }
110                     }
111 
112                     @Override
113                     protected void onPreExecute() {
114                         mProgressDialog = getProgressDialog();
115                         mProgressDialog.show();
116 
117                         // need to prevent orientation changes as we're about to go into
118                         // a long IO request, so we won't be able to access inflate resources on
119                         // flash
120                         mOldOrientation = getActivity().getRequestedOrientation();
121                         getActivity().setRequestedOrientation(
122                                 ActivityInfo.SCREEN_ORIENTATION_LOCKED);
123                     }
124                 }.execute();
125             } else {
126                 doMasterClear();
127             }
128         }
129 
130         private ProgressDialog getProgressDialog() {
131             final ProgressDialog progressDialog = new ProgressDialog(getActivity());
132             progressDialog.setIndeterminate(true);
133             progressDialog.setCancelable(false);
134             progressDialog.setTitle(
135                     getActivity().getString(R.string.master_clear_progress_title));
136             progressDialog.setMessage(
137                     getActivity().getString(R.string.master_clear_progress_text));
138             return progressDialog;
139         }
140     };
141 
doMasterClear()142     private void doMasterClear() {
143         Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
144         intent.setPackage("android");
145         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
146         intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
147         intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);
148         intent.putExtra(Intent.EXTRA_WIPE_ESIMS, mEraseEsims);
149         getActivity().sendBroadcast(intent);
150         // Intent handling is asynchronous -- assume it will happen soon.
151     }
152 
153     /**
154      * Configure the UI for the final confirmation interaction
155      */
establishFinalConfirmationState()156     private void establishFinalConfirmationState() {
157         final GlifLayout layout = mContentView.findViewById(R.id.setup_wizard_layout);
158 
159         final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
160         mixin.setPrimaryButton(
161                 new FooterButton.Builder(getActivity())
162                         .setText(R.string.master_clear_button_text)
163                         .setListener(mFinalClickListener)
164                         .setButtonType(ButtonType.OTHER)
165                         .setTheme(R.style.SudGlifButton_Primary)
166                         .build()
167         );
168     }
169 
setUpActionBarAndTitle()170     private void setUpActionBarAndTitle() {
171         final Activity activity = getActivity();
172         if (activity == null) {
173             Log.e(TAG, "No activity attached, skipping setUpActionBarAndTitle");
174             return;
175         }
176         final ActionBar actionBar = activity.getActionBar();
177         if (actionBar == null) {
178             Log.e(TAG, "No actionbar, skipping setUpActionBarAndTitle");
179             return;
180         }
181         actionBar.hide();
182         activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
183     }
184 
185     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)186     public View onCreateView(LayoutInflater inflater, ViewGroup container,
187             Bundle savedInstanceState) {
188         final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
189                 getActivity(), UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
190         if (RestrictedLockUtilsInternal.hasBaseUserRestriction(getActivity(),
191                 UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
192             return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
193         } else if (admin != null) {
194             new ActionDisabledByAdminDialogHelper(getActivity())
195                     .prepareDialogBuilder(UserManager.DISALLOW_FACTORY_RESET, admin)
196                     .setOnDismissListener(__ -> getActivity().finish())
197                     .show();
198             return new View(getActivity());
199         }
200         mContentView = inflater.inflate(R.layout.master_clear_confirm, null);
201         setUpActionBarAndTitle();
202         establishFinalConfirmationState();
203         setAccessibilityTitle();
204         setSubtitle();
205         return mContentView;
206     }
207 
setAccessibilityTitle()208     private void setAccessibilityTitle() {
209         CharSequence currentTitle = getActivity().getTitle();
210         TextView confirmationMessage = mContentView.findViewById(R.id.sud_layout_description);
211         if (confirmationMessage != null) {
212             String accessibleText = new StringBuilder(currentTitle).append(",").append(
213                     confirmationMessage.getText()).toString();
214             getActivity().setTitle(Utils.createAccessibleSequence(currentTitle, accessibleText));
215         }
216     }
217 
218     @VisibleForTesting
setSubtitle()219     void setSubtitle() {
220         if (mEraseEsims) {
221             ((TextView) mContentView.findViewById(R.id.sud_layout_description))
222                 .setText(R.string.master_clear_final_desc_esim);
223         }
224     }
225 
226     @Override
onCreate(Bundle savedInstanceState)227     public void onCreate(Bundle savedInstanceState) {
228         super.onCreate(savedInstanceState);
229 
230         Bundle args = getArguments();
231         mEraseSdCard = args != null
232                 && args.getBoolean(MasterClear.ERASE_EXTERNAL_EXTRA);
233         mEraseEsims = args != null
234                 && args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);
235     }
236 
237     @Override
getMetricsCategory()238     public int getMetricsCategory() {
239         return SettingsEnums.MASTER_CLEAR_CONFIRM;
240     }
241 }
242