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