• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.tv.settings.device.storage;
18 
19 import android.annotation.Nullable;
20 import android.app.ActivityManager;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.AsyncTask;
24 import android.os.Bundle;
25 import android.os.UserHandle;
26 import android.service.oemlock.OemLockManager;
27 import android.service.persistentdata.PersistentDataBlockManager;
28 import android.util.Log;
29 
30 import androidx.annotation.NonNull;
31 import androidx.fragment.app.FragmentActivity;
32 import androidx.leanback.app.GuidedStepSupportFragment;
33 import androidx.leanback.widget.GuidanceStylist;
34 import androidx.leanback.widget.GuidedAction;
35 
36 import com.android.tv.settings.R;
37 import com.android.tv.settings.util.GuidedActionsAlignUtil;
38 
39 import java.util.List;
40 
41 public class ResetActivity extends FragmentActivity {
42 
43     private static final String TAG = "ResetActivity";
44 
45     /**
46      * Support for shutdown-after-reset. If our launch intent has a true value for
47      * the boolean extra under the following key, then include it in the intent we
48      * use to trigger a factory reset. This will cause us to shut down instead of
49      * restart after the reset.
50      */
51     private static final String SHUTDOWN_INTENT_EXTRA = "shutdown";
52 
53     @Override
onCreate(@ullable Bundle savedInstanceState)54     protected void onCreate(@Nullable Bundle savedInstanceState) {
55         super.onCreate(savedInstanceState);
56         if (savedInstanceState == null) {
57             GuidedStepSupportFragment
58                     .addAsRoot(this, ResetFragment.newInstance(), android.R.id.content);
59         }
60     }
61 
62     public static class ResetFragment extends GuidedStepSupportFragment {
63 
newInstance()64         public static ResetFragment newInstance() {
65 
66             Bundle args = new Bundle();
67 
68             ResetFragment fragment = new ResetFragment();
69             fragment.setArguments(args);
70             return fragment;
71         }
72 
73         @NonNull
74         @Override
onCreateGuidance(Bundle savedInstanceState)75         public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
76             return new GuidanceStylist.Guidance(
77                     getString(R.string.device_reset),
78                     getString(R.string.factory_reset_description),
79                     null,
80                     getContext().getDrawable(R.drawable.ic_settings_backup_restore_132dp));
81         }
82 
83         @Override
onCreateActions(@onNull List<GuidedAction> actions, Bundle savedInstanceState)84         public void onCreateActions(@NonNull List<GuidedAction> actions,
85                 Bundle savedInstanceState) {
86             actions.add(new GuidedAction.Builder(getContext())
87                     .clickAction(GuidedAction.ACTION_ID_CANCEL)
88                     .build());
89             actions.add(new GuidedAction.Builder(getContext())
90                     .clickAction(GuidedAction.ACTION_ID_OK)
91                     .title(getString(R.string.device_reset))
92                     .multilineDescription(true)
93                     .build());
94         }
95 
96         @Override
onGuidedActionClicked(GuidedAction action)97         public void onGuidedActionClicked(GuidedAction action) {
98             if (action.getId() == GuidedAction.ACTION_ID_OK) {
99                 add(getFragmentManager(), ResetConfirmFragment.newInstance());
100             } else if (action.getId() == GuidedAction.ACTION_ID_CANCEL) {
101                 getActivity().finish();
102             } else {
103                 Log.wtf(TAG, "Unknown action clicked");
104             }
105         }
106 
107         @Override
onCreateGuidanceStylist()108         public GuidanceStylist onCreateGuidanceStylist() {
109             return GuidedActionsAlignUtil.createGuidanceStylist();
110         }
111     }
112 
113     public static class ResetConfirmFragment extends GuidedStepSupportFragment {
114 
newInstance()115         public static ResetConfirmFragment newInstance() {
116 
117             Bundle args = new Bundle();
118 
119             ResetConfirmFragment fragment = new ResetConfirmFragment();
120             fragment.setArguments(args);
121             return fragment;
122         }
123 
124         @NonNull
125         @Override
onCreateGuidance(Bundle savedInstanceState)126         public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
127             return new GuidanceStylist.Guidance(
128                     getString(R.string.device_reset),
129                     getString(R.string.confirm_factory_reset_description),
130                     null,
131                     getContext().getDrawable(R.drawable.ic_settings_backup_restore_132dp));
132         }
133 
134         @Override
onCreateActions(@onNull List<GuidedAction> actions, Bundle savedInstanceState)135         public void onCreateActions(@NonNull List<GuidedAction> actions,
136                 Bundle savedInstanceState) {
137             actions.add(new GuidedAction.Builder(getContext())
138                     .clickAction(GuidedAction.ACTION_ID_CANCEL)
139                     .build());
140             actions.add(new GuidedAction.Builder(getContext())
141                     .clickAction(GuidedAction.ACTION_ID_OK)
142                     .title(getString(R.string.confirm_factory_reset_device))
143                     .build());
144         }
145 
146         @Override
onCreateGuidanceStylist()147         public GuidanceStylist onCreateGuidanceStylist() {
148             return GuidedActionsAlignUtil.createGuidanceStylist();
149         }
150 
151         @Override
onGuidedActionClicked(GuidedAction action)152         public void onGuidedActionClicked(GuidedAction action) {
153             if (action.getId() == GuidedAction.ACTION_ID_OK) {
154                 if (ActivityManager.isUserAMonkey()) {
155                     Log.v(TAG, "Monkey tried to erase the device. Bad monkey, bad!");
156                     getActivity().finish();
157                 } else {
158                     performFactoryReset();
159                 }
160             } else if (action.getId() == GuidedAction.ACTION_ID_CANCEL) {
161                 getActivity().finish();
162             } else {
163                 Log.wtf(TAG, "Unknown action clicked");
164             }
165         }
166 
performFactoryReset()167         private void performFactoryReset() {
168             final PersistentDataBlockManager pdbManager = (PersistentDataBlockManager)
169                     getContext().getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
170 
171             if (shouldWipePersistentDataBlock(pdbManager)) {
172                 new AsyncTask<Void, Void, Void>() {
173                     @Override
174                     protected Void doInBackground(Void... params) {
175                         pdbManager.wipe();
176                         return null;
177                     }
178 
179                     @Override
180                     protected void onPostExecute(Void aVoid) {
181                         doMainClear();
182                     }
183                 }.execute();
184             } else {
185                 doMainClear();
186             }
187         }
188 
shouldWipePersistentDataBlock(PersistentDataBlockManager pdbManager)189         private boolean shouldWipePersistentDataBlock(PersistentDataBlockManager pdbManager) {
190             if (pdbManager == null) {
191                 return false;
192             }
193             // If OEM unlock is allowed, the persistent data block will be wiped during FR.
194             // If disabled, it will be wiped here instead.
195             if (((OemLockManager) getActivity().getSystemService(Context.OEM_LOCK_SERVICE))
196                     .isOemUnlockAllowed()) {
197                 return false;
198             }
199             return true;
200         }
201 
doMainClear()202         private void doMainClear() {
203             if (getActivity() == null) {
204                 return;
205             }
206             Intent resetIntent = new Intent(Intent.ACTION_FACTORY_RESET);
207             resetIntent.setPackage("android");
208             resetIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
209             resetIntent.putExtra(Intent.EXTRA_REASON, "ResetConfirmFragment");
210             if (getActivity().getIntent().getBooleanExtra(SHUTDOWN_INTENT_EXTRA, false)) {
211                 resetIntent.putExtra(SHUTDOWN_INTENT_EXTRA, true);
212             }
213             getActivity().sendBroadcastAsUser(resetIntent, UserHandle.SYSTEM);
214         }
215     }
216 }
217