1 /*
2  * Copyright (C) 2020 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.devicepolicy;
18 
19 import static com.android.server.FactoryResetter.setFactoryResetting;
20 
21 import android.annotation.Nullable;
22 import android.app.admin.DevicePolicySafetyChecker;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.os.Bundle;
26 import android.os.RecoverySystem;
27 import android.os.RemoteException;
28 import android.os.UserManager;
29 import android.os.storage.StorageManager;
30 import android.service.persistentdata.PersistentDataBlockManager;
31 
32 import com.android.internal.os.IResultReceiver;
33 import com.android.internal.util.Preconditions;
34 import com.android.server.utils.Slogf;
35 
36 import java.io.IOException;
37 import java.util.Objects;
38 
39 /**
40  * Entry point for "factory reset" requests.
41  *
42  * @deprecated TODO(b/225012970): should be moved to {@code com.android.server.FactoryResetter}
43  */
44 @Deprecated
45 public final class FactoryResetter {
46 
47     private static final String TAG = FactoryResetter.class.getSimpleName();
48 
49     private final Context mContext;
50     private final @Nullable DevicePolicySafetyChecker mSafetyChecker;
51     private final @Nullable String mReason;
52     private final boolean mShutdown;
53     private final boolean mForce;
54     private final boolean mWipeEuicc;
55     private final boolean mWipeAdoptableStorage;
56     private final boolean mWipeFactoryResetProtection;
57 
58     /**
59      * Factory reset the device according to the builder's arguments.
60      *
61      * @return {@code true} if device was factory reset, or {@code false} if it was delayed by the
62      * {@link DevicePolicySafetyChecker}.
63      */
factoryReset()64     public boolean factoryReset() throws IOException {
65         Preconditions.checkCallAuthorization(mContext.checkCallingOrSelfPermission(
66                 android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED);
67 
68         setFactoryResetting(mContext);
69 
70         if (mSafetyChecker == null) {
71             factoryResetInternalUnchecked();
72             return true;
73         }
74 
75         IResultReceiver receiver = new IResultReceiver.Stub() {
76             @Override
77             public void send(int resultCode, Bundle resultData) throws RemoteException {
78                 Slogf.i(TAG, "Factory reset confirmed by %s, proceeding", mSafetyChecker);
79                 try {
80                     factoryResetInternalUnchecked();
81                 } catch (IOException e) {
82                     // Shouldn't happen
83                     Slogf.wtf(TAG, e, "IOException calling underlying systems");
84                 }
85             }
86         };
87         Slogf.i(TAG, "Delaying factory reset until %s confirms", mSafetyChecker);
88         mSafetyChecker.onFactoryReset(receiver);
89         return false;
90     }
91 
92     @Override
toString()93     public String toString() {
94         StringBuilder builder = new StringBuilder("FactoryResetter[");
95         if (mReason == null) {
96             builder.append("no_reason");
97         } else {
98             builder.append("reason='").append(mReason).append("'");
99         }
100         if (mSafetyChecker != null) {
101             builder.append(",hasSafetyChecker");
102         }
103         if (mShutdown) {
104             builder.append(",shutdown");
105         }
106         if (mForce) {
107             builder.append(",force");
108         }
109         if (mWipeEuicc) {
110             builder.append(",wipeEuicc");
111         }
112         if (mWipeAdoptableStorage) {
113             builder.append(",wipeAdoptableStorage");
114         }
115         if (mWipeFactoryResetProtection) {
116             builder.append(",ipeFactoryResetProtection");
117         }
118         return builder.append(']').toString();
119     }
120 
factoryResetInternalUnchecked()121     private void factoryResetInternalUnchecked() throws IOException {
122         Slogf.i(TAG, "factoryReset(): reason=%s, shutdown=%b, force=%b, wipeEuicc=%b, "
123                 + "wipeAdoptableStorage=%b, wipeFRP=%b", mReason, mShutdown, mForce, mWipeEuicc,
124                 mWipeAdoptableStorage, mWipeFactoryResetProtection);
125 
126         UserManager um = mContext.getSystemService(UserManager.class);
127         if (!mForce && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
128             throw new SecurityException("Factory reset is not allowed for this user.");
129         }
130 
131         if (mWipeFactoryResetProtection) {
132             PersistentDataBlockManager manager = mContext
133                     .getSystemService(PersistentDataBlockManager.class);
134             if (manager != null) {
135                 Slogf.w(TAG, "Wiping factory reset protection");
136                 manager.wipe();
137             } else {
138                 Slogf.w(TAG, "No need to wipe factory reset protection");
139             }
140         }
141 
142         if (mWipeAdoptableStorage) {
143             Slogf.w(TAG, "Wiping adoptable storage");
144             StorageManager sm = mContext.getSystemService(StorageManager.class);
145             sm.wipeAdoptableDisks();
146         }
147 
148         RecoverySystem.rebootWipeUserData(mContext, mShutdown, mReason, mForce, mWipeEuicc);
149     }
150 
FactoryResetter(Builder builder)151     private FactoryResetter(Builder builder) {
152         mContext = builder.mContext;
153         mSafetyChecker = builder.mSafetyChecker;
154         mReason = builder.mReason;
155         mShutdown = builder.mShutdown;
156         mForce = builder.mForce;
157         mWipeEuicc = builder.mWipeEuicc;
158         mWipeAdoptableStorage = builder.mWipeAdoptableStorage;
159         mWipeFactoryResetProtection = builder.mWipeFactoryResetProtection;
160     }
161 
162     /**
163      * Creates a new builder.
164      */
newBuilder(Context context)165     public static Builder newBuilder(Context context) {
166         return new Builder(context);
167     }
168 
169     /**
170      * Builder for {@link FactoryResetter} instances.
171      */
172     public static final class Builder {
173 
174         private final Context mContext;
175         private @Nullable DevicePolicySafetyChecker mSafetyChecker;
176         private @Nullable String mReason;
177         private boolean mShutdown;
178         private boolean mForce;
179         private boolean mWipeEuicc;
180         private boolean mWipeAdoptableStorage;
181         private boolean mWipeFactoryResetProtection;
182 
Builder(Context context)183         private Builder(Context context) {
184             mContext = Objects.requireNonNull(context);
185         }
186 
187         /**
188          * Sets a {@link DevicePolicySafetyChecker} object that will be used to delay the
189          * factory reset when it's not safe to do so.
190          */
setSafetyChecker(@ullable DevicePolicySafetyChecker safetyChecker)191         public Builder setSafetyChecker(@Nullable DevicePolicySafetyChecker safetyChecker) {
192             mSafetyChecker = safetyChecker;
193             return this;
194         }
195 
196         /**
197          * Sets the (non-null) reason for the factory reset that is visible in the logs
198          */
setReason(String reason)199         public Builder setReason(String reason) {
200             mReason = Objects.requireNonNull(reason);
201             return this;
202         }
203 
204         /**
205          * Sets whether the device will be powered down after the wipe completes, rather than being
206          * rebooted back to the regular system.
207          */
setShutdown(boolean value)208         public Builder setShutdown(boolean value) {
209             mShutdown = value;
210             return this;
211         }
212 
213         /**
214          * Sets whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction should be
215          * ignored.
216          */
setForce(boolean value)217         public Builder setForce(boolean value) {
218             mForce = value;
219             return this;
220         }
221 
222         /**
223          * Sets whether to wipe the {@code euicc} data.
224          */
setWipeEuicc(boolean value)225         public Builder setWipeEuicc(boolean value) {
226             mWipeEuicc = value;
227             return this;
228         }
229 
230         /**
231          * Sets whether to wipe the adoptable external storage (if any).
232          */
setWipeAdoptableStorage(boolean value)233         public Builder setWipeAdoptableStorage(boolean value) {
234             mWipeAdoptableStorage = value;
235             return this;
236         }
237 
238         /**
239          * Sets whether to reset the factory reset protection.
240          */
setWipeFactoryResetProtection(boolean value)241         public Builder setWipeFactoryResetProtection(boolean value) {
242             mWipeFactoryResetProtection = value;
243             return this;
244         }
245 
246         /**
247          * Builds the {@link FactoryResetter} instance.
248          */
build()249         public FactoryResetter build() {
250             return new FactoryResetter(this);
251         }
252     }
253 }
254