1 /* 2 * Copyright (C) 2019 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 android.app.admin; 18 19 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; 20 import static org.xmlpull.v1.XmlPullParser.END_TAG; 21 import static org.xmlpull.v1.XmlPullParser.TEXT; 22 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.content.ComponentName; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.util.IndentingPrintWriter; 29 import android.util.Log; 30 31 import com.android.modules.utils.TypedXmlPullParser; 32 import com.android.modules.utils.TypedXmlSerializer; 33 34 import org.xmlpull.v1.XmlPullParserException; 35 36 import java.io.IOException; 37 import java.util.ArrayList; 38 import java.util.List; 39 40 /** 41 * The factory reset protection policy determines which accounts can unlock a device that 42 * has gone through untrusted factory reset. 43 * <p> 44 * Only a device owner or profile owner of an organization-owned device can set a factory 45 * reset protection policy for the device by calling the {@code DevicePolicyManager} method 46 * {@link DevicePolicyManager#setFactoryResetProtectionPolicy(ComponentName, 47 * FactoryResetProtectionPolicy)}}. 48 * <p> 49 * Normally factory reset protection does not kick in if the device is factory reset via Settings. 50 * This is also the case when a device owner sets factory reset protection policy. However, 51 * when a profile owner of an organization-owned device sets factory reset protection policy that 52 * locks the device to specific accounts, the policy will take effect even if factory reset is 53 * performed from Settings. 54 * 55 * @see DevicePolicyManager#setFactoryResetProtectionPolicy 56 * @see DevicePolicyManager#getFactoryResetProtectionPolicy 57 */ 58 public final class FactoryResetProtectionPolicy implements Parcelable { 59 60 private static final String LOG_TAG = "FactoryResetProtectionPolicy"; 61 62 private static final String KEY_FACTORY_RESET_PROTECTION_ACCOUNT = 63 "factory_reset_protection_account"; 64 private static final String KEY_FACTORY_RESET_PROTECTION_ENABLED = 65 "factory_reset_protection_enabled"; 66 private static final String ATTR_VALUE = "value"; 67 68 private final List<String> mFactoryResetProtectionAccounts; 69 private final boolean mFactoryResetProtectionEnabled; 70 FactoryResetProtectionPolicy(List<String> factoryResetProtectionAccounts, boolean factoryResetProtectionEnabled)71 private FactoryResetProtectionPolicy(List<String> factoryResetProtectionAccounts, 72 boolean factoryResetProtectionEnabled) { 73 mFactoryResetProtectionAccounts = factoryResetProtectionAccounts; 74 mFactoryResetProtectionEnabled = factoryResetProtectionEnabled; 75 } 76 77 /** 78 * Get the list of accounts that can provision a device which has been factory reset. 79 */ getFactoryResetProtectionAccounts()80 public @NonNull List<String> getFactoryResetProtectionAccounts() { 81 return mFactoryResetProtectionAccounts; 82 } 83 84 /** 85 * Return whether factory reset protection for the device is enabled or not. 86 */ isFactoryResetProtectionEnabled()87 public boolean isFactoryResetProtectionEnabled() { 88 return mFactoryResetProtectionEnabled; 89 } 90 91 /** 92 * Builder class for {@link FactoryResetProtectionPolicy} objects. 93 */ 94 public static class Builder { 95 private List<String> mFactoryResetProtectionAccounts; 96 private boolean mFactoryResetProtectionEnabled; 97 98 /** 99 * Initialize a new Builder to construct a {@link FactoryResetProtectionPolicy}. 100 */ Builder()101 public Builder() { 102 mFactoryResetProtectionEnabled = true; 103 }; 104 105 /** 106 * Sets which accounts can unlock a device that has been factory reset. 107 * <p> 108 * Once set, the consumer unlock flow will be disabled and only accounts in this list 109 * can unlock factory reset protection after untrusted factory reset. 110 * <p> 111 * It's up to the FRP management agent to interpret the {@code String} as account it 112 * supports. Please consult their relevant documentation for details. 113 * 114 * @param factoryResetProtectionAccounts list of accounts. 115 * @return the same Builder instance. 116 */ 117 @NonNull setFactoryResetProtectionAccounts( @onNull List<String> factoryResetProtectionAccounts)118 public Builder setFactoryResetProtectionAccounts( 119 @NonNull List<String> factoryResetProtectionAccounts) { 120 mFactoryResetProtectionAccounts = new ArrayList<>(factoryResetProtectionAccounts); 121 return this; 122 } 123 124 /** 125 * Sets whether factory reset protection is enabled or not. 126 * <p> 127 * Once disabled, factory reset protection will not kick in all together when the device 128 * goes through untrusted factory reset. This applies to both the consumer unlock flow and 129 * the admin account overrides via {@link #setFactoryResetProtectionAccounts}. By default, 130 * factory reset protection is enabled. 131 * 132 * @param factoryResetProtectionEnabled Whether the policy is enabled or not. 133 * @return the same Builder instance. 134 */ 135 @NonNull setFactoryResetProtectionEnabled(boolean factoryResetProtectionEnabled)136 public Builder setFactoryResetProtectionEnabled(boolean factoryResetProtectionEnabled) { 137 mFactoryResetProtectionEnabled = factoryResetProtectionEnabled; 138 return this; 139 } 140 141 /** 142 * Combines all of the attributes that have been set on this {@code Builder} 143 * 144 * @return a new {@link FactoryResetProtectionPolicy} object. 145 */ 146 @NonNull build()147 public FactoryResetProtectionPolicy build() { 148 return new FactoryResetProtectionPolicy(mFactoryResetProtectionAccounts, 149 mFactoryResetProtectionEnabled); 150 } 151 } 152 153 @Override toString()154 public String toString() { 155 return "FactoryResetProtectionPolicy{" 156 + "mFactoryResetProtectionAccounts=" + mFactoryResetProtectionAccounts 157 + ", mFactoryResetProtectionEnabled=" + mFactoryResetProtectionEnabled 158 + '}'; 159 } 160 161 @Override writeToParcel(@onNull Parcel dest, @Nullable int flags)162 public void writeToParcel(@NonNull Parcel dest, @Nullable int flags) { 163 int accountsCount = mFactoryResetProtectionAccounts.size(); 164 dest.writeInt(accountsCount); 165 for (String account: mFactoryResetProtectionAccounts) { 166 dest.writeString(account); 167 } 168 dest.writeBoolean(mFactoryResetProtectionEnabled); 169 } 170 171 @Override describeContents()172 public int describeContents() { 173 return 0; 174 } 175 176 public static final @NonNull Creator<FactoryResetProtectionPolicy> CREATOR = 177 new Creator<FactoryResetProtectionPolicy>() { 178 179 @Override 180 public FactoryResetProtectionPolicy createFromParcel(Parcel in) { 181 List<String> factoryResetProtectionAccounts = new ArrayList<>(); 182 int accountsCount = in.readInt(); 183 for (int i = 0; i < accountsCount; i++) { 184 factoryResetProtectionAccounts.add(in.readString()); 185 } 186 boolean factoryResetProtectionEnabled = in.readBoolean(); 187 188 return new FactoryResetProtectionPolicy(factoryResetProtectionAccounts, 189 factoryResetProtectionEnabled); 190 } 191 192 @Override 193 public FactoryResetProtectionPolicy[] newArray(int size) { 194 return new FactoryResetProtectionPolicy[size]; 195 } 196 }; 197 198 /** 199 * Restore a previously saved FactoryResetProtectionPolicy from XML. 200 * <p> 201 * No validation is required on the reconstructed policy since the XML was previously 202 * created by the system server from a validated policy. 203 * @hide 204 */ 205 @Nullable readFromXml(@onNull TypedXmlPullParser parser)206 public static FactoryResetProtectionPolicy readFromXml(@NonNull TypedXmlPullParser parser) { 207 try { 208 boolean factoryResetProtectionEnabled = parser.getAttributeBoolean(null, 209 KEY_FACTORY_RESET_PROTECTION_ENABLED, false); 210 211 List<String> factoryResetProtectionAccounts = new ArrayList<>(); 212 int outerDepth = parser.getDepth(); 213 int type; 214 while ((type = parser.next()) != END_DOCUMENT 215 && (type != END_TAG || parser.getDepth() > outerDepth)) { 216 if (type == END_TAG || type == TEXT) { 217 continue; 218 } 219 if (!parser.getName().equals(KEY_FACTORY_RESET_PROTECTION_ACCOUNT)) { 220 continue; 221 } 222 factoryResetProtectionAccounts.add( 223 parser.getAttributeValue(null, ATTR_VALUE)); 224 } 225 226 return new FactoryResetProtectionPolicy(factoryResetProtectionAccounts, 227 factoryResetProtectionEnabled); 228 } catch (XmlPullParserException | IOException e) { 229 Log.w(LOG_TAG, "Reading from xml failed", e); 230 } 231 return null; 232 } 233 234 /** 235 * @hide 236 */ writeToXml(@onNull TypedXmlSerializer out)237 public void writeToXml(@NonNull TypedXmlSerializer out) throws IOException { 238 out.attributeBoolean(null, KEY_FACTORY_RESET_PROTECTION_ENABLED, 239 mFactoryResetProtectionEnabled); 240 for (String account : mFactoryResetProtectionAccounts) { 241 out.startTag(null, KEY_FACTORY_RESET_PROTECTION_ACCOUNT); 242 out.attribute(null, ATTR_VALUE, account); 243 out.endTag(null, KEY_FACTORY_RESET_PROTECTION_ACCOUNT); 244 } 245 } 246 247 /** 248 * Returns if the policy will result in factory reset protection being locked to 249 * admin-specified accounts. 250 * <p> 251 * When a device has a non-empty factory reset protection policy, trusted factory reset 252 * via Settings will no longer remove factory reset protection from the device. 253 * @hide 254 */ isNotEmpty()255 public boolean isNotEmpty() { 256 return !mFactoryResetProtectionAccounts.isEmpty() && mFactoryResetProtectionEnabled; 257 } 258 259 /** 260 * @hide 261 */ dump(IndentingPrintWriter pw)262 public void dump(IndentingPrintWriter pw) { 263 pw.print("factoryResetProtectionEnabled="); 264 pw.println(mFactoryResetProtectionEnabled); 265 266 pw.print("factoryResetProtectionAccounts="); 267 pw.increaseIndent(); 268 for (int i = 0; i < mFactoryResetProtectionAccounts.size(); i++) { 269 pw.println(mFactoryResetProtectionAccounts.get(i)); 270 } 271 pw.decreaseIndent(); 272 } 273 } 274