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