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