1 /* 2 * Copyright (C) 2022 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 android.app.admin.DevicePolicyIdentifiers.PACKAGES_SUSPENDED_POLICY; 20 import static android.app.admin.DevicePolicyIdentifiers.USER_CONTROL_DISABLED_PACKAGES_POLICY; 21 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_TARGET_USER_ID; 22 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY; 23 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY; 24 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_HARDWARE_LIMITATION; 25 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_STORAGE_LIMIT_REACHED; 26 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED; 27 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET; 28 import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; 29 30 import android.Manifest; 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.app.AppGlobals; 34 import android.app.BroadcastOptions; 35 import android.app.admin.BooleanPolicyValue; 36 import android.app.admin.DevicePolicyIdentifiers; 37 import android.app.admin.DevicePolicyManager; 38 import android.app.admin.DevicePolicyState; 39 import android.app.admin.IntentFilterPolicyKey; 40 import android.app.admin.PolicyKey; 41 import android.app.admin.PolicyUpdateReceiver; 42 import android.app.admin.PolicyValue; 43 import android.app.admin.TargetUser; 44 import android.app.admin.UserRestrictionPolicyKey; 45 import android.content.ComponentName; 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.IntentFilter; 49 import android.content.pm.IPackageManager; 50 import android.content.pm.PackageManager; 51 import android.content.pm.ResolveInfo; 52 import android.content.pm.UserInfo; 53 import android.content.pm.UserProperties; 54 import android.os.Binder; 55 import android.os.Bundle; 56 import android.os.Environment; 57 import android.os.Parcel; 58 import android.os.RemoteException; 59 import android.os.UserHandle; 60 import android.os.UserManager; 61 import android.telephony.TelephonyManager; 62 import android.util.AtomicFile; 63 import android.util.IndentingPrintWriter; 64 import android.util.Log; 65 import android.util.SparseArray; 66 import android.util.Xml; 67 68 import com.android.internal.annotations.GuardedBy; 69 import com.android.internal.util.XmlUtils; 70 import com.android.modules.utils.TypedXmlPullParser; 71 import com.android.modules.utils.TypedXmlSerializer; 72 import com.android.server.utils.Slogf; 73 74 import libcore.io.IoUtils; 75 76 import org.xmlpull.v1.XmlPullParserException; 77 78 import java.io.File; 79 import java.io.FileOutputStream; 80 import java.io.IOException; 81 import java.io.InputStream; 82 import java.nio.file.Files; 83 import java.nio.file.Path; 84 import java.nio.file.StandardCopyOption; 85 import java.util.ArrayList; 86 import java.util.Collections; 87 import java.util.HashMap; 88 import java.util.HashSet; 89 import java.util.LinkedHashMap; 90 import java.util.List; 91 import java.util.Map; 92 import java.util.Objects; 93 import java.util.Set; 94 import java.util.concurrent.CompletableFuture; 95 96 /** 97 * Class responsible for setting, resolving, and enforcing policies set by multiple management 98 * admins on the device. 99 */ 100 final class DevicePolicyEngine { 101 static final String TAG = "DevicePolicyEngine"; 102 103 static final String DEVICE_LOCK_CONTROLLER_ROLE = 104 "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; 105 106 static final String SYSTEM_SUPERVISION_ROLE = "android.app.role.SYSTEM_SUPERVISION"; 107 108 private static final String CELLULAR_2G_USER_RESTRICTION_ID = 109 DevicePolicyIdentifiers.getIdentifierForUserRestriction( 110 UserManager.DISALLOW_CELLULAR_2G); 111 112 //TODO(b/295504706) : Speak to security team to decide what to set Policy_Size_Limit 113 static final int DEFAULT_POLICY_SIZE_LIMIT = -1; 114 115 private final Context mContext; 116 private final UserManager mUserManager; 117 118 // TODO(b/256849338): add more granular locks 119 private final Object mLock; 120 121 /** 122 * Map of <userId, Map<policyKey, policyState>> 123 */ 124 @GuardedBy("mLock") 125 private final SparseArray<Map<PolicyKey, PolicyState<?>>> mLocalPolicies; 126 127 /** 128 * Map of <policyKey, policyState> 129 */ 130 @GuardedBy("mLock") 131 private final Map<PolicyKey, PolicyState<?>> mGlobalPolicies; 132 133 /** 134 * Map containing the current set of admins in each user with active policies. 135 */ 136 private final SparseArray<Set<EnforcingAdmin>> mEnforcingAdmins; 137 138 private final SparseArray<HashMap<EnforcingAdmin, Integer>> mAdminPolicySize; 139 140 private int mPolicySizeLimit = DEFAULT_POLICY_SIZE_LIMIT; 141 142 private final DeviceAdminServiceController mDeviceAdminServiceController; 143 DevicePolicyEngine( @onNull Context context, @NonNull DeviceAdminServiceController deviceAdminServiceController, @NonNull Object lock)144 DevicePolicyEngine( 145 @NonNull Context context, 146 @NonNull DeviceAdminServiceController deviceAdminServiceController, 147 @NonNull Object lock) { 148 mContext = Objects.requireNonNull(context); 149 mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController); 150 mLock = Objects.requireNonNull(lock); 151 mUserManager = mContext.getSystemService(UserManager.class); 152 mLocalPolicies = new SparseArray<>(); 153 mGlobalPolicies = new HashMap<>(); 154 mEnforcingAdmins = new SparseArray<>(); 155 mAdminPolicySize = new SparseArray<>(); 156 } 157 158 @GuardedBy("mLock") forceEnforcementRefreshIfUserRestrictionLocked( @onNull PolicyDefinition<?> policyDefinition)159 private void forceEnforcementRefreshIfUserRestrictionLocked( 160 @NonNull PolicyDefinition<?> policyDefinition) { 161 try { 162 if (isUserRestrictionPolicy(policyDefinition)) { 163 // This is okay because it's only true for user restrictions which are all <Boolean> 164 forceEnforcementRefreshLocked((PolicyDefinition<Boolean>) policyDefinition); 165 } 166 } catch (Throwable e) { 167 // Catch any possible exceptions just to be on the safe side 168 Log.e(TAG, "Exception thrown during forceEnforcementRefreshIfUserRestrictionLocked", e); 169 } 170 } 171 isUserRestrictionPolicy(@onNull PolicyDefinition<?> policyDefinition)172 private boolean isUserRestrictionPolicy(@NonNull PolicyDefinition<?> policyDefinition) { 173 // These are all "not nullable" but for the purposes of maximum safety for a lightly tested 174 // change we check here 175 if (policyDefinition == null) { 176 return false; 177 } 178 PolicyKey policyKey = policyDefinition.getPolicyKey(); 179 if (policyKey == null) { 180 return false; 181 } 182 183 if (policyKey instanceof UserRestrictionPolicyKey) { 184 // b/307481299 We must force all user restrictions to re-sync local 185 // + global on each set/clear 186 return true; 187 } 188 189 return false; 190 } 191 192 @GuardedBy("mLock") forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition)193 private void forceEnforcementRefreshLocked(PolicyDefinition<Boolean> policyDefinition) { 194 Binder.withCleanCallingIdentity(() -> { 195 // Sync global state 196 PolicyValue<Boolean> globalValue = new BooleanPolicyValue(false); 197 try { 198 PolicyState<Boolean> policyState = getGlobalPolicyStateLocked(policyDefinition); 199 globalValue = policyState.getCurrentResolvedPolicy(); 200 } catch (IllegalArgumentException e) { 201 // Expected for local-only policies 202 } 203 204 enforcePolicy(policyDefinition, globalValue, UserHandle.USER_ALL); 205 206 // Loop through each user and sync that user's state 207 for (UserInfo user : mUserManager.getUsers()) { 208 PolicyValue<Boolean> localValue = new BooleanPolicyValue(false); 209 try { 210 PolicyState<Boolean> localPolicyState = getLocalPolicyStateLocked( 211 policyDefinition, user.id); 212 localValue = localPolicyState.getCurrentResolvedPolicy(); 213 } catch (IllegalArgumentException e) { 214 // Expected for global-only policies 215 } 216 217 enforcePolicy(policyDefinition, localValue, user.id); 218 } 219 }); 220 } 221 222 /** 223 * Set the policy for the provided {@code policyDefinition} (see {@link PolicyDefinition}) and 224 * {@code enforcingAdmin} to the provided {@code value}. 225 * 226 * <p>If {@code skipEnforcePolicy} is true, it sets the policies in the internal data structure 227 * but doesn't call the enforcing logic. 228 */ setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, int userId, boolean skipEnforcePolicy)229 <V> void setLocalPolicy( 230 @NonNull PolicyDefinition<V> policyDefinition, 231 @NonNull EnforcingAdmin enforcingAdmin, 232 @NonNull PolicyValue<V> value, 233 int userId, 234 boolean skipEnforcePolicy) { 235 Objects.requireNonNull(policyDefinition); 236 Objects.requireNonNull(enforcingAdmin); 237 238 synchronized (mLock) { 239 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 240 if (!handleAdminPolicySizeLimit(localPolicyState, enforcingAdmin, value, 241 policyDefinition, userId)) { 242 return; 243 } 244 245 if (policyDefinition.isNonCoexistablePolicy()) { 246 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState, 247 enforcingAdmin, value, userId, skipEnforcePolicy); 248 return; 249 } 250 251 boolean hasGlobalPolicies = hasGlobalPolicyLocked(policyDefinition); 252 boolean policyChanged; 253 if (hasGlobalPolicies) { 254 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 255 policyChanged = localPolicyState.addPolicy( 256 enforcingAdmin, 257 value, 258 globalPolicyState.getPoliciesSetByAdmins()); 259 } else { 260 policyChanged = localPolicyState.addPolicy(enforcingAdmin, value); 261 } 262 263 // No need to notify admins as no new policy is actually enforced, we're just filling in 264 // the data structures. 265 if (!skipEnforcePolicy) { 266 forceEnforcementRefreshIfUserRestrictionLocked(policyDefinition); 267 if (policyChanged) { 268 onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId); 269 } 270 boolean policyEnforced = Objects.equals( 271 localPolicyState.getCurrentResolvedPolicy(), value); 272 // TODO(b/285532044): remove hack and handle properly 273 if (!policyEnforced && shouldApplyPackageSetUnionPolicyHack(policyDefinition)) { 274 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 275 PolicyValue<Set<String>> parsedResolvedValue = 276 (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy(); 277 policyEnforced = (parsedResolvedValue != null && parsedValue != null 278 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 279 } 280 sendPolicyResultToAdmin( 281 enforcingAdmin, 282 policyDefinition, 283 // TODO: we're always sending this for now, should properly handle errors. 284 policyEnforced 285 ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY, 286 userId); 287 } 288 289 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 290 291 write(); 292 293 applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId); 294 } 295 } 296 297 /** 298 * Sets a non-coexistable policy, meaning it doesn't get resolved against other policies set 299 * by other admins, and no callbacks are sent to admins, this is just storing and 300 * enforcing the policy. 301 * 302 * <p>Passing a {@code null} value means the policy set by this admin should be removed. 303 */ 304 @GuardedBy("mLock") setNonCoexistableLocalPolicyLocked( PolicyDefinition<V> policyDefinition, PolicyState<V> localPolicyState, EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId, boolean skipEnforcePolicy)305 private <V> void setNonCoexistableLocalPolicyLocked( 306 PolicyDefinition<V> policyDefinition, 307 PolicyState<V> localPolicyState, 308 EnforcingAdmin enforcingAdmin, 309 @Nullable PolicyValue<V> value, 310 int userId, 311 boolean skipEnforcePolicy) { 312 if (value == null) { 313 localPolicyState.removePolicy(enforcingAdmin); 314 } else { 315 localPolicyState.addPolicy(enforcingAdmin, value); 316 } 317 if (!skipEnforcePolicy) { 318 enforcePolicy(policyDefinition, value, userId); 319 } 320 if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) { 321 removeLocalPolicyStateLocked(policyDefinition, userId); 322 } 323 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 324 write(); 325 applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId); 326 } 327 328 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 329 330 /** 331 * Set the policy for the provided {@code policyDefinition} 332 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 333 */ setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, int userId)334 <V> void setLocalPolicy( 335 @NonNull PolicyDefinition<V> policyDefinition, 336 @NonNull EnforcingAdmin enforcingAdmin, 337 @NonNull PolicyValue<V> value, 338 int userId) { 339 setLocalPolicy( 340 policyDefinition, enforcingAdmin, value, userId, /* skipEnforcePolicy= */ false); 341 } 342 343 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 344 345 /** 346 * Removes any previously set policy for the provided {@code policyDefinition} 347 * (see {@link PolicyDefinition}) and {@code enforcingAdmin}. 348 */ removeLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)349 <V> void removeLocalPolicy( 350 @NonNull PolicyDefinition<V> policyDefinition, 351 @NonNull EnforcingAdmin enforcingAdmin, 352 int userId) { 353 Objects.requireNonNull(policyDefinition); 354 Objects.requireNonNull(enforcingAdmin); 355 356 synchronized (mLock) { 357 forceEnforcementRefreshIfUserRestrictionLocked(policyDefinition); 358 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 359 return; 360 } 361 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 362 363 decreasePolicySizeForAdmin(localPolicyState, enforcingAdmin); 364 365 if (policyDefinition.isNonCoexistablePolicy()) { 366 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState, 367 enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false); 368 return; 369 } 370 371 boolean policyChanged; 372 if (hasGlobalPolicyLocked(policyDefinition)) { 373 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 374 policyChanged = localPolicyState.removePolicy( 375 enforcingAdmin, 376 globalPolicyState.getPoliciesSetByAdmins()); 377 } else { 378 policyChanged = localPolicyState.removePolicy(enforcingAdmin); 379 } 380 381 if (policyChanged) { 382 onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId); 383 } 384 385 // For a removePolicy to be enforced, it means no current policy exists 386 sendPolicyResultToAdmin( 387 enforcingAdmin, 388 policyDefinition, 389 // TODO: we're always sending this for now, should properly handle errors. 390 RESULT_POLICY_CLEARED, 391 userId); 392 393 if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) { 394 removeLocalPolicyStateLocked(policyDefinition, userId); 395 } 396 397 updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin); 398 399 write(); 400 401 applyToInheritableProfiles(policyDefinition, enforcingAdmin, /*value */ null, userId); 402 } 403 } 404 405 /** 406 * If any of child user has property {@link UserProperties#INHERIT_DEVICE_POLICY_FROM_PARENT} 407 * set then propagate the policy to it if value is not null 408 * else remove the policy from child. 409 */ applyToInheritableProfiles(PolicyDefinition<V> policyDefinition, EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId)410 private <V> void applyToInheritableProfiles(PolicyDefinition<V> policyDefinition, 411 EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId) { 412 if (!policyDefinition.isInheritable()) { 413 return; 414 } 415 Binder.withCleanCallingIdentity(() -> { 416 List<UserInfo> userInfos = mUserManager.getProfiles(userId); 417 for (UserInfo childUserInfo : userInfos) { 418 int childUserId = childUserInfo.getUserHandle().getIdentifier(); 419 if (isProfileOfUser(childUserId, userId) 420 && isInheritDevicePolicyFromParent(childUserInfo)) { 421 if (value != null) { 422 setLocalPolicy(policyDefinition, enforcingAdmin, value, childUserId); 423 } else { 424 removeLocalPolicy(policyDefinition, enforcingAdmin, childUserId); 425 } 426 } 427 } 428 }); 429 } 430 431 /** 432 * Checks if given parentUserId is direct parent of childUserId. 433 */ isProfileOfUser(int childUserId, int parentUserId)434 private boolean isProfileOfUser(int childUserId, int parentUserId) { 435 UserInfo parentInfo = mUserManager.getProfileParent(childUserId); 436 return childUserId != parentUserId && parentInfo != null 437 && parentInfo.getUserHandle().getIdentifier() == parentUserId; 438 } 439 isInheritDevicePolicyFromParent(UserInfo userInfo)440 private boolean isInheritDevicePolicyFromParent(UserInfo userInfo) { 441 UserProperties userProperties = mUserManager.getUserProperties(userInfo.getUserHandle()); 442 return userProperties != null && mUserManager.getUserProperties(userInfo.getUserHandle()) 443 .getInheritDevicePolicy() == INHERIT_DEVICE_POLICY_FROM_PARENT; 444 } 445 446 /** 447 * Enforces the new policy and notifies relevant admins. 448 */ 449 @GuardedBy("mLock") onLocalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)450 private <V> void onLocalPolicyChangedLocked( 451 @NonNull PolicyDefinition<V> policyDefinition, 452 @NonNull EnforcingAdmin enforcingAdmin, 453 int userId) { 454 455 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 456 enforcePolicy( 457 policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId); 458 459 // Send policy updates to admins who've set it locally 460 sendPolicyChangedToAdminsLocked( 461 localPolicyState, 462 enforcingAdmin, 463 policyDefinition, 464 // This policy change is only relevant to a single user, not the global 465 // policy value, 466 userId); 467 468 // Send policy updates to admins who've set it globally 469 if (hasGlobalPolicyLocked(policyDefinition)) { 470 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 471 sendPolicyChangedToAdminsLocked( 472 globalPolicyState, 473 enforcingAdmin, 474 policyDefinition, 475 userId); 476 } 477 sendDevicePolicyChangedToSystem(userId); 478 } 479 480 /** 481 * Set the policy for the provided {@code policyDefinition} 482 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 483 */ setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value)484 <V> void setGlobalPolicy( 485 @NonNull PolicyDefinition<V> policyDefinition, 486 @NonNull EnforcingAdmin enforcingAdmin, 487 @NonNull PolicyValue<V> value) { 488 setGlobalPolicy(policyDefinition, enforcingAdmin, value, /* skipEnforcePolicy= */ false); 489 } 490 491 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 492 493 /** 494 * Set the policy for the provided {@code policyDefinition} 495 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 496 */ setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, boolean skipEnforcePolicy)497 <V> void setGlobalPolicy( 498 @NonNull PolicyDefinition<V> policyDefinition, 499 @NonNull EnforcingAdmin enforcingAdmin, 500 @NonNull PolicyValue<V> value, 501 boolean skipEnforcePolicy) { 502 503 Objects.requireNonNull(policyDefinition); 504 Objects.requireNonNull(enforcingAdmin); 505 Objects.requireNonNull(value); 506 507 synchronized (mLock) { 508 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 509 if (!handleAdminPolicySizeLimit(globalPolicyState, enforcingAdmin, value, 510 policyDefinition, UserHandle.USER_ALL)) { 511 return; 512 } 513 // TODO(b/270999567): Move error handling for DISALLOW_CELLULAR_2G into the code 514 // that honors the restriction once there's an API available 515 if (checkFor2gFailure(policyDefinition, enforcingAdmin)) { 516 Log.i(TAG, 517 "Device does not support capabilities required to disable 2g. Not setting" 518 + " global policy state."); 519 return; 520 } 521 522 boolean policyChanged = globalPolicyState.addPolicy(enforcingAdmin, value); 523 boolean policyAppliedOnAllUsers = applyGlobalPolicyOnUsersWithLocalPoliciesLocked( 524 policyDefinition, enforcingAdmin, value, skipEnforcePolicy); 525 526 // No need to notify admins as no new policy is actually enforced, we're just filling in 527 // the data structures. 528 if (!skipEnforcePolicy) { 529 forceEnforcementRefreshIfUserRestrictionLocked(policyDefinition); 530 if (policyChanged) { 531 onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin); 532 } 533 534 boolean policyAppliedGlobally = Objects.equals( 535 globalPolicyState.getCurrentResolvedPolicy(), value); 536 // TODO(b/285532044): remove hack and handle properly 537 if (!policyAppliedGlobally 538 && shouldApplyPackageSetUnionPolicyHack(policyDefinition)) { 539 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 540 PolicyValue<Set<String>> parsedResolvedValue = 541 (PolicyValue<Set<String>>) globalPolicyState.getCurrentResolvedPolicy(); 542 policyAppliedGlobally = (parsedResolvedValue != null && parsedValue != null 543 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 544 } 545 546 boolean policyApplied = policyAppliedGlobally && policyAppliedOnAllUsers; 547 548 sendPolicyResultToAdmin( 549 enforcingAdmin, 550 policyDefinition, 551 // TODO: we're always sending this for now, should properly handle errors. 552 policyApplied ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY, 553 UserHandle.USER_ALL); 554 } 555 556 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 557 558 write(); 559 } 560 } 561 562 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 563 564 /** 565 * Removes any previously set policy for the provided {@code policyDefinition} 566 * (see {@link PolicyDefinition}) and {@code enforcingAdmin}. 567 */ removeGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)568 <V> void removeGlobalPolicy( 569 @NonNull PolicyDefinition<V> policyDefinition, 570 @NonNull EnforcingAdmin enforcingAdmin) { 571 572 Objects.requireNonNull(policyDefinition); 573 Objects.requireNonNull(enforcingAdmin); 574 575 synchronized (mLock) { 576 PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition); 577 578 decreasePolicySizeForAdmin(policyState, enforcingAdmin); 579 580 boolean policyChanged = policyState.removePolicy(enforcingAdmin); 581 582 forceEnforcementRefreshIfUserRestrictionLocked(policyDefinition); 583 if (policyChanged) { 584 onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin); 585 } 586 587 applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin, 588 /* value= */ null, /* skipEnforcePolicy= */ false); 589 590 sendPolicyResultToAdmin( 591 enforcingAdmin, 592 policyDefinition, 593 // TODO: we're always sending this for now, should properly handle errors. 594 RESULT_POLICY_CLEARED, 595 UserHandle.USER_ALL); 596 597 if (policyState.getPoliciesSetByAdmins().isEmpty()) { 598 removeGlobalPolicyStateLocked(policyDefinition); 599 } 600 601 updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin); 602 603 write(); 604 } 605 } 606 607 /** 608 * Enforces the new policy globally and notifies relevant admins. 609 */ 610 @GuardedBy("mLock") onGlobalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)611 private <V> void onGlobalPolicyChangedLocked( 612 @NonNull PolicyDefinition<V> policyDefinition, 613 @NonNull EnforcingAdmin enforcingAdmin) { 614 PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition); 615 616 enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(), 617 UserHandle.USER_ALL); 618 619 sendPolicyChangedToAdminsLocked( 620 policyState, 621 enforcingAdmin, 622 policyDefinition, 623 UserHandle.USER_ALL); 624 625 sendDevicePolicyChangedToSystem(UserHandle.USER_ALL); 626 } 627 628 /** 629 * Tries to enforce the global policy locally on all users that have the same policy set 630 * locally, this is only applicable to policies that can be set locally or globally 631 * (e.g. setCameraDisabled, setScreenCaptureDisabled) rather than 632 * policies that are global by nature (e.g. setting Wifi enabled/disabled). 633 * 634 * <p> A {@code null} policy value means the policy was removed 635 * 636 * <p>Returns {@code true} if the policy is enforced successfully on all users. 637 */ 638 @GuardedBy("mLock") applyGlobalPolicyOnUsersWithLocalPoliciesLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, boolean skipEnforcePolicy)639 private <V> boolean applyGlobalPolicyOnUsersWithLocalPoliciesLocked( 640 @NonNull PolicyDefinition<V> policyDefinition, 641 @NonNull EnforcingAdmin enforcingAdmin, 642 @Nullable PolicyValue<V> value, 643 boolean skipEnforcePolicy) { 644 // Global only policies can't be applied locally, return early. 645 if (policyDefinition.isGlobalOnlyPolicy()) { 646 return true; 647 } 648 boolean isAdminPolicyApplied = true; 649 for (int i = 0; i < mLocalPolicies.size(); i++) { 650 int userId = mLocalPolicies.keyAt(i); 651 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 652 continue; 653 } 654 655 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 656 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 657 658 boolean policyChanged = localPolicyState.resolvePolicy( 659 globalPolicyState.getPoliciesSetByAdmins()); 660 if (policyChanged && !skipEnforcePolicy) { 661 enforcePolicy( 662 policyDefinition, 663 localPolicyState.getCurrentResolvedPolicy(), 664 userId); 665 sendPolicyChangedToAdminsLocked( 666 localPolicyState, 667 enforcingAdmin, 668 policyDefinition, 669 // Even though this is caused by a global policy change, admins who've set 670 // it locally should only care about the local user state. 671 userId); 672 673 } 674 // TODO(b/285532044): remove hack and handle properly 675 if (shouldApplyPackageSetUnionPolicyHack(policyDefinition)) { 676 if (!Objects.equals(value, localPolicyState.getCurrentResolvedPolicy())) { 677 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 678 PolicyValue<Set<String>> parsedResolvedValue = 679 (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy(); 680 isAdminPolicyApplied &= (parsedResolvedValue != null && parsedValue != null 681 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 682 } 683 } else { 684 isAdminPolicyApplied &= Objects.equals( 685 value, localPolicyState.getCurrentResolvedPolicy()); 686 } 687 } 688 return isAdminPolicyApplied; 689 } 690 691 /** 692 * Retrieves the resolved policy for the provided {@code policyDefinition} and {@code userId}. 693 */ 694 @Nullable getResolvedPolicy(@onNull PolicyDefinition<V> policyDefinition, int userId)695 <V> V getResolvedPolicy(@NonNull PolicyDefinition<V> policyDefinition, int userId) { 696 PolicyValue<V> resolvedValue = getResolvedPolicyValue(policyDefinition, userId); 697 return resolvedValue == null ? null : resolvedValue.getValue(); 698 } 699 getResolvedPolicyValue(@onNull PolicyDefinition<V> policyDefinition, int userId)700 private <V> PolicyValue<V> getResolvedPolicyValue(@NonNull PolicyDefinition<V> policyDefinition, 701 int userId) { 702 Objects.requireNonNull(policyDefinition); 703 704 synchronized (mLock) { 705 PolicyValue<V> resolvedValue = null; 706 if (hasLocalPolicyLocked(policyDefinition, userId)) { 707 resolvedValue = getLocalPolicyStateLocked( 708 policyDefinition, userId).getCurrentResolvedPolicy(); 709 } else if (hasGlobalPolicyLocked(policyDefinition)) { 710 resolvedValue = getGlobalPolicyStateLocked( 711 policyDefinition).getCurrentResolvedPolicy(); 712 } 713 return resolvedValue; 714 } 715 } 716 717 /** 718 * Retrieves resolved policy for the provided {@code policyDefinition} and a list of 719 * users. 720 */ 721 @Nullable getResolvedPolicyAcrossUsers(@onNull PolicyDefinition<V> policyDefinition, List<Integer> users)722 <V> V getResolvedPolicyAcrossUsers(@NonNull PolicyDefinition<V> policyDefinition, 723 List<Integer> users) { 724 Objects.requireNonNull(policyDefinition); 725 726 List<PolicyValue<V>> adminPolicies = new ArrayList<>(); 727 synchronized (mLock) { 728 for (int userId : users) { 729 PolicyValue<V> resolvedValue = getResolvedPolicyValue(policyDefinition, userId); 730 if (resolvedValue != null) { 731 adminPolicies.add(resolvedValue); 732 } 733 } 734 } 735 // We will be aggregating PolicyValue across multiple admins across multiple users, 736 // including different policies set by the same admin on different users. This is 737 // not supported by ResolutionMechanism generically, instead we need to call the special 738 // resolve() method that doesn't care about admins who set the policy. Note that not every 739 // ResolutionMechanism supports this. 740 PolicyValue<V> resolvedValue = 741 policyDefinition.getResolutionMechanism().resolve(adminPolicies); 742 return resolvedValue == null ? null : resolvedValue.getValue(); 743 } 744 745 /** 746 * Retrieves the policy set by the admin for the provided {@code policyDefinition} and 747 * {@code userId} if one was set, otherwise returns {@code null}. 748 */ 749 @Nullable getLocalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)750 <V> V getLocalPolicySetByAdmin( 751 @NonNull PolicyDefinition<V> policyDefinition, 752 @NonNull EnforcingAdmin enforcingAdmin, 753 int userId) { 754 Objects.requireNonNull(policyDefinition); 755 Objects.requireNonNull(enforcingAdmin); 756 757 synchronized (mLock) { 758 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 759 return null; 760 } 761 PolicyValue<V> value = getLocalPolicyStateLocked(policyDefinition, userId) 762 .getPoliciesSetByAdmins().get(enforcingAdmin); 763 return value == null ? null : value.getValue(); 764 } 765 } 766 767 /** 768 * Retrieves the global policy set by the admin for the provided {@code policyDefinition} 769 * if one was set, otherwise returns {@code null}. 770 */ 771 @Nullable getGlobalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)772 <V> V getGlobalPolicySetByAdmin( 773 @NonNull PolicyDefinition<V> policyDefinition, 774 @NonNull EnforcingAdmin enforcingAdmin) { 775 Objects.requireNonNull(policyDefinition); 776 Objects.requireNonNull(enforcingAdmin); 777 778 synchronized (mLock) { 779 if (!hasGlobalPolicyLocked(policyDefinition)) { 780 return null; 781 } 782 PolicyValue<V> value = getGlobalPolicyStateLocked(policyDefinition) 783 .getPoliciesSetByAdmins().get(enforcingAdmin); 784 return value == null ? null : value.getValue(); 785 } 786 } 787 788 /** 789 * Retrieves the values set for the provided {@code policyDefinition} by each admin. 790 */ 791 @NonNull getLocalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)792 <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getLocalPoliciesSetByAdmins( 793 @NonNull PolicyDefinition<V> policyDefinition, 794 int userId) { 795 Objects.requireNonNull(policyDefinition); 796 797 synchronized (mLock) { 798 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 799 return new LinkedHashMap<>(); 800 } 801 return getLocalPolicyStateLocked(policyDefinition, userId).getPoliciesSetByAdmins(); 802 } 803 } 804 805 /** 806 * Retrieves the values set for the provided {@code policyDefinition} by each admin. 807 */ 808 @NonNull getGlobalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition)809 <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getGlobalPoliciesSetByAdmins( 810 @NonNull PolicyDefinition<V> policyDefinition) { 811 Objects.requireNonNull(policyDefinition); 812 813 synchronized (mLock) { 814 if (!hasGlobalPolicyLocked(policyDefinition)) { 815 return new LinkedHashMap<>(); 816 } 817 return getGlobalPolicyStateLocked(policyDefinition).getPoliciesSetByAdmins(); 818 } 819 } 820 821 /** 822 * Returns the policies set by the given admin that share the same 823 * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. 824 * 825 * <p>For example, getLocalPolicyKeysSetByAdmin(PERMISSION_GRANT, admin) returns all permission 826 * grants set by the given admin. 827 * 828 * <p>Note that this will always return at most one item for policies that do not require 829 * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs 830 * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). 831 */ 832 @NonNull getLocalPolicyKeysSetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)833 <V> Set<PolicyKey> getLocalPolicyKeysSetByAdmin( 834 @NonNull PolicyDefinition<V> policyDefinition, 835 @NonNull EnforcingAdmin enforcingAdmin, 836 int userId) { 837 Objects.requireNonNull(policyDefinition); 838 Objects.requireNonNull(enforcingAdmin); 839 840 synchronized (mLock) { 841 if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { 842 return Set.of(); 843 } 844 Set<PolicyKey> keys = new HashSet<>(); 845 for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { 846 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey()) 847 && mLocalPolicies.get(userId).get(key).getPoliciesSetByAdmins() 848 .containsKey(enforcingAdmin)) { 849 keys.add(key); 850 } 851 } 852 return keys; 853 } 854 } 855 856 /** 857 * Returns all the {@code policyKeys} set by any admin that share the same 858 * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. 859 * 860 * <p>For example, getLocalPolicyKeysSetByAllAdmins(PERMISSION_GRANT) returns all permission 861 * grants set by any admin. 862 * 863 * <p>Note that this will always return at most one item for policies that do not require 864 * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs 865 * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). 866 */ 867 @NonNull getLocalPolicyKeysSetByAllAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)868 <V> Set<PolicyKey> getLocalPolicyKeysSetByAllAdmins( 869 @NonNull PolicyDefinition<V> policyDefinition, 870 int userId) { 871 Objects.requireNonNull(policyDefinition); 872 873 synchronized (mLock) { 874 if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { 875 return Set.of(); 876 } 877 Set<PolicyKey> keys = new HashSet<>(); 878 for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { 879 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())) { 880 keys.add(key); 881 } 882 } 883 return keys; 884 } 885 } 886 887 /** 888 * Returns all user restriction policies set by the given admin. 889 * 890 * <p>Pass in {@link UserHandle#USER_ALL} for {@code userId} to get global restrictions set by 891 * the admin 892 */ 893 @NonNull getUserRestrictionPolicyKeysForAdmin( @onNull EnforcingAdmin admin, int userId)894 Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdmin( 895 @NonNull EnforcingAdmin admin, 896 int userId) { 897 Objects.requireNonNull(admin); 898 synchronized (mLock) { 899 if (userId == UserHandle.USER_ALL) { 900 return getUserRestrictionPolicyKeysForAdminLocked(mGlobalPolicies, admin); 901 } 902 if (!mLocalPolicies.contains(userId)) { 903 return Set.of(); 904 } 905 return getUserRestrictionPolicyKeysForAdminLocked(mLocalPolicies.get(userId), admin); 906 } 907 } 908 transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin)909 <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) { 910 synchronized (mLock) { 911 Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet()); 912 for (PolicyKey policy : globalPolicies) { 913 PolicyState<?> policyState = mGlobalPolicies.get(policy); 914 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) { 915 PolicyDefinition<V> policyDefinition = 916 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 917 PolicyValue<V> policyValue = 918 (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin); 919 setGlobalPolicy(policyDefinition, newAdmin, policyValue); 920 } 921 } 922 923 for (int i = 0; i < mLocalPolicies.size(); i++) { 924 int userId = mLocalPolicies.keyAt(i); 925 Set<PolicyKey> localPolicies = new HashSet<>( 926 mLocalPolicies.get(userId).keySet()); 927 for (PolicyKey policy : localPolicies) { 928 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 929 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) { 930 PolicyDefinition<V> policyDefinition = 931 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 932 PolicyValue<V> policyValue = 933 (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin); 934 setLocalPolicy(policyDefinition, newAdmin, policyValue, userId); 935 } 936 } 937 } 938 } 939 removePoliciesForAdmin(oldAdmin); 940 } 941 942 @GuardedBy("mLock") getUserRestrictionPolicyKeysForAdminLocked( Map<PolicyKey, PolicyState<?>> policies, EnforcingAdmin admin)943 private Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdminLocked( 944 Map<PolicyKey, PolicyState<?>> policies, 945 EnforcingAdmin admin) { 946 Set<UserRestrictionPolicyKey> keys = new HashSet<>(); 947 for (PolicyKey key : policies.keySet()) { 948 if (!policies.get(key).getPolicyDefinition().isUserRestrictionPolicy()) { 949 continue; 950 } 951 // User restriction policies are always boolean 952 PolicyValue<Boolean> value = (PolicyValue<Boolean>) policies.get(key) 953 .getPoliciesSetByAdmins().get(admin); 954 if (value == null || !value.getValue()) { 955 continue; 956 } 957 keys.add((UserRestrictionPolicyKey) key); 958 } 959 return keys; 960 } 961 962 @GuardedBy("mLock") hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId)963 private <V> boolean hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId) { 964 if (policyDefinition.isGlobalOnlyPolicy()) { 965 return false; 966 } 967 if (!mLocalPolicies.contains(userId)) { 968 return false; 969 } 970 if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) { 971 return false; 972 } 973 return !mLocalPolicies.get(userId).get(policyDefinition.getPolicyKey()) 974 .getPoliciesSetByAdmins().isEmpty(); 975 } 976 977 @GuardedBy("mLock") hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition)978 private <V> boolean hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition) { 979 if (policyDefinition.isLocalOnlyPolicy()) { 980 return false; 981 } 982 if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) { 983 return false; 984 } 985 return !mGlobalPolicies.get(policyDefinition.getPolicyKey()).getPoliciesSetByAdmins() 986 .isEmpty(); 987 } 988 989 @GuardedBy("mLock") 990 @NonNull getLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)991 private <V> PolicyState<V> getLocalPolicyStateLocked( 992 PolicyDefinition<V> policyDefinition, int userId) { 993 994 if (policyDefinition.isGlobalOnlyPolicy()) { 995 throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a global only" 996 + " policy."); 997 } 998 999 if (!mLocalPolicies.contains(userId)) { 1000 mLocalPolicies.put(userId, new HashMap<>()); 1001 } 1002 if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) { 1003 mLocalPolicies.get(userId).put( 1004 policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition)); 1005 } 1006 return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition); 1007 } 1008 1009 @GuardedBy("mLock") removeLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)1010 private <V> void removeLocalPolicyStateLocked( 1011 PolicyDefinition<V> policyDefinition, int userId) { 1012 if (!mLocalPolicies.contains(userId)) { 1013 return; 1014 } 1015 mLocalPolicies.get(userId).remove(policyDefinition.getPolicyKey()); 1016 } 1017 1018 @GuardedBy("mLock") 1019 @NonNull getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)1020 private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) { 1021 if (policyDefinition.isLocalOnlyPolicy()) { 1022 throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a local only" 1023 + " policy."); 1024 } 1025 1026 if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) { 1027 mGlobalPolicies.put( 1028 policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition)); 1029 } 1030 return getPolicyStateLocked(mGlobalPolicies, policyDefinition); 1031 } 1032 1033 @GuardedBy("mLock") removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)1034 private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) { 1035 mGlobalPolicies.remove(policyDefinition.getPolicyKey()); 1036 } 1037 1038 @GuardedBy("mLock") getPolicyStateLocked( Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition)1039 private static <V> PolicyState<V> getPolicyStateLocked( 1040 Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) { 1041 try { 1042 // This will not throw an exception because policyDefinition is of type V, so unless 1043 // we've created two policies with the same key but different types - we can only have 1044 // stored a PolicyState of the right type. 1045 PolicyState<V> policyState = (PolicyState<V>) policies.get( 1046 policyDefinition.getPolicyKey()); 1047 return policyState; 1048 } catch (ClassCastException exception) { 1049 // TODO: handle exception properly 1050 throw new IllegalArgumentException(); 1051 } 1052 } 1053 enforcePolicy(PolicyDefinition<V> policyDefinition, @Nullable PolicyValue<V> policyValue, int userId)1054 private <V> CompletableFuture<Boolean> enforcePolicy(PolicyDefinition<V> policyDefinition, 1055 @Nullable PolicyValue<V> policyValue, int userId) { 1056 // null policyValue means remove any enforced policies, ensure callbacks handle this 1057 // properly 1058 return policyDefinition.enforcePolicy( 1059 policyValue == null ? null : policyValue.getValue(), mContext, userId); 1060 } 1061 sendDevicePolicyChangedToSystem(int userId)1062 private void sendDevicePolicyChangedToSystem(int userId) { 1063 Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 1064 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 1065 Bundle options = new BroadcastOptions() 1066 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 1067 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE) 1068 .toBundle(); 1069 Binder.withCleanCallingIdentity(() -> mContext.sendBroadcastAsUser( 1070 intent, 1071 new UserHandle(userId), 1072 /* receiverPermissions= */ null, 1073 options)); 1074 } 1075 sendPolicyResultToAdmin( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId)1076 private <V> void sendPolicyResultToAdmin( 1077 EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId) { 1078 Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_SET_RESULT); 1079 intent.setPackage(admin.getPackageName()); 1080 1081 Binder.withCleanCallingIdentity(() -> { 1082 List<ResolveInfo> receivers = 1083 mContext.getPackageManager().queryBroadcastReceiversAsUser( 1084 intent, 1085 PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), 1086 admin.getUserId()); 1087 if (receivers.isEmpty()) { 1088 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_SET_RESULT" 1089 + " in package " + admin.getPackageName()); 1090 return; 1091 } 1092 1093 Bundle extras = new Bundle(); 1094 policyDefinition.getPolicyKey().writeToBundle(extras); 1095 extras.putInt( 1096 EXTRA_POLICY_TARGET_USER_ID, 1097 getTargetUser(admin.getUserId(), userId)); 1098 extras.putInt( 1099 EXTRA_POLICY_UPDATE_RESULT_KEY, 1100 result); 1101 1102 intent.putExtras(extras); 1103 1104 maybeSendIntentToAdminReceivers(intent, UserHandle.of(admin.getUserId()), receivers); 1105 }); 1106 } 1107 1108 // TODO(b/261430877): Finalise the decision on which admins to send the updates to. 1109 @GuardedBy("mLock") sendPolicyChangedToAdminsLocked( PolicyState<V> policyState, EnforcingAdmin callingAdmin, PolicyDefinition<V> policyDefinition, int userId)1110 private <V> void sendPolicyChangedToAdminsLocked( 1111 PolicyState<V> policyState, 1112 EnforcingAdmin callingAdmin, 1113 PolicyDefinition<V> policyDefinition, 1114 int userId) { 1115 for (EnforcingAdmin admin : policyState.getPoliciesSetByAdmins().keySet()) { 1116 // We're sending a separate broadcast for the calling admin with the result. 1117 if (admin.equals(callingAdmin)) { 1118 continue; 1119 } 1120 int result = Objects.equals( 1121 policyState.getPoliciesSetByAdmins().get(admin), 1122 policyState.getCurrentResolvedPolicy()) 1123 ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY; 1124 maybeSendOnPolicyChanged( 1125 admin, policyDefinition, result, userId); 1126 } 1127 } 1128 maybeSendOnPolicyChanged( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason, int userId)1129 private <V> void maybeSendOnPolicyChanged( 1130 EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason, 1131 int userId) { 1132 Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_CHANGED); 1133 intent.setPackage(admin.getPackageName()); 1134 1135 Binder.withCleanCallingIdentity(() -> { 1136 List<ResolveInfo> receivers = 1137 mContext.getPackageManager().queryBroadcastReceiversAsUser( 1138 intent, 1139 PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), 1140 admin.getUserId()); 1141 if (receivers.isEmpty()) { 1142 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_CHANGED" 1143 + " in package " + admin.getPackageName()); 1144 return; 1145 } 1146 1147 Bundle extras = new Bundle(); 1148 policyDefinition.getPolicyKey().writeToBundle(extras); 1149 extras.putInt( 1150 EXTRA_POLICY_TARGET_USER_ID, 1151 getTargetUser(admin.getUserId(), userId)); 1152 extras.putInt(EXTRA_POLICY_UPDATE_RESULT_KEY, reason); 1153 intent.putExtras(extras); 1154 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1155 1156 maybeSendIntentToAdminReceivers( 1157 intent, UserHandle.of(admin.getUserId()), receivers); 1158 }); 1159 } 1160 maybeSendIntentToAdminReceivers( Intent intent, UserHandle userHandle, List<ResolveInfo> receivers)1161 private void maybeSendIntentToAdminReceivers( 1162 Intent intent, UserHandle userHandle, List<ResolveInfo> receivers) { 1163 for (ResolveInfo resolveInfo : receivers) { 1164 if (!Manifest.permission.BIND_DEVICE_ADMIN.equals( 1165 resolveInfo.activityInfo.permission)) { 1166 Log.w(TAG, "Receiver " + resolveInfo.activityInfo + " is not protected by " 1167 + "BIND_DEVICE_ADMIN permission!"); 1168 continue; 1169 } 1170 // TODO: If admins are always bound to, do I still need to set 1171 // "BroadcastOptions.setBackgroundActivityStartsAllowed"? 1172 // TODO: maybe protect it with a permission that is granted to the role so that we 1173 // don't accidentally send a broadcast to an admin that no longer holds the role. 1174 mContext.sendBroadcastAsUser(intent, userHandle); 1175 } 1176 } 1177 getTargetUser(int adminUserId, int targetUserId)1178 private int getTargetUser(int adminUserId, int targetUserId) { 1179 if (targetUserId == UserHandle.USER_ALL) { 1180 return TargetUser.GLOBAL_USER_ID; 1181 } 1182 if (adminUserId == targetUserId) { 1183 return TargetUser.LOCAL_USER_ID; 1184 } 1185 if (getProfileParentId(adminUserId) == targetUserId) { 1186 return TargetUser.PARENT_USER_ID; 1187 } 1188 return TargetUser.UNKNOWN_USER_ID; 1189 } 1190 getProfileParentId(int userId)1191 private int getProfileParentId(int userId) { 1192 return Binder.withCleanCallingIdentity(() -> { 1193 UserInfo parentUser = mUserManager.getProfileParent(userId); 1194 return parentUser != null ? parentUser.id : userId; 1195 }); 1196 } 1197 1198 /** 1199 * Starts/Stops the services that handle {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} 1200 * in the enforcing admins for the given {@code userId}. 1201 */ updateDeviceAdminsServicesForUser( int userId, boolean enable, @NonNull String actionForLog)1202 private void updateDeviceAdminsServicesForUser( 1203 int userId, boolean enable, @NonNull String actionForLog) { 1204 if (!enable) { 1205 mDeviceAdminServiceController.stopServicesForUser( 1206 userId, actionForLog); 1207 } else { 1208 for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) { 1209 // DPCs are handled separately in DPMS, no need to reestablish the connection here. 1210 if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1211 continue; 1212 } 1213 mDeviceAdminServiceController.startServiceForAdmin( 1214 admin.getPackageName(), userId, actionForLog); 1215 } 1216 } 1217 } 1218 1219 /** 1220 * Handles internal state related to a user getting started. 1221 */ handleStartUser(int userId)1222 void handleStartUser(int userId) { 1223 updateDeviceAdminsServicesForUser( 1224 userId, /* enable= */ true, /* actionForLog= */ "start-user"); 1225 } 1226 1227 /** 1228 * Handles internal state related to a user getting started. 1229 */ handleUnlockUser(int userId)1230 void handleUnlockUser(int userId) { 1231 updateDeviceAdminsServicesForUser( 1232 userId, /* enable= */ true, /* actionForLog= */ "unlock-user"); 1233 } 1234 1235 /** 1236 * Handles internal state related to a user getting stopped. 1237 */ handleStopUser(int userId)1238 void handleStopUser(int userId) { 1239 updateDeviceAdminsServicesForUser( 1240 userId, /* enable= */ false, /* actionForLog= */ "stop-user"); 1241 } 1242 1243 /** 1244 * Handles internal state related to packages getting updated. 1245 */ handlePackageChanged( @ullable String updatedPackage, int userId, @Nullable String removedDpcPackage)1246 void handlePackageChanged( 1247 @Nullable String updatedPackage, int userId, @Nullable String removedDpcPackage) { 1248 Binder.withCleanCallingIdentity(() -> { 1249 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1250 if (removedDpcPackage != null) { 1251 for (EnforcingAdmin admin : admins) { 1252 if (removedDpcPackage.equals(admin.getPackageName())) { 1253 removePoliciesForAdmin(admin); 1254 return; 1255 } 1256 } 1257 } 1258 for (EnforcingAdmin admin : admins) { 1259 // No need to make changes to system enforcing admins. 1260 if (admin.isSystemAuthority()) break; 1261 if (updatedPackage == null || updatedPackage.equals(admin.getPackageName())) { 1262 if (!isPackageInstalled(admin.getPackageName(), userId)) { 1263 Slogf.i(TAG, String.format( 1264 "Admin package %s not found for user %d, removing admin policies", 1265 admin.getPackageName(), userId)); 1266 // remove policies for the uninstalled package 1267 removePoliciesForAdmin(admin); 1268 return; 1269 } 1270 } 1271 } 1272 if (updatedPackage != null) { 1273 updateDeviceAdminServiceOnPackageChanged(updatedPackage, userId); 1274 removePersistentPreferredActivityPoliciesForPackage(updatedPackage, userId); 1275 } 1276 }); 1277 } 1278 removePersistentPreferredActivityPoliciesForPackage( @onNull String packageName, int userId)1279 private void removePersistentPreferredActivityPoliciesForPackage( 1280 @NonNull String packageName, int userId) { 1281 Set<PolicyKey> policyKeys = getLocalPolicyKeysSetByAllAdmins( 1282 PolicyDefinition.GENERIC_PERSISTENT_PREFERRED_ACTIVITY, userId); 1283 for (PolicyKey key : policyKeys) { 1284 if (!(key instanceof IntentFilterPolicyKey)) { 1285 throw new IllegalStateException("PolicyKey for " 1286 + "PERSISTENT_PREFERRED_ACTIVITY is not of type " 1287 + "IntentFilterPolicyKey"); 1288 } 1289 IntentFilterPolicyKey parsedKey = 1290 (IntentFilterPolicyKey) key; 1291 IntentFilter intentFilter = Objects.requireNonNull(parsedKey.getIntentFilter()); 1292 PolicyDefinition<ComponentName> policyDefinition = 1293 PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(intentFilter); 1294 LinkedHashMap<EnforcingAdmin, PolicyValue<ComponentName>> policies = 1295 getLocalPoliciesSetByAdmins( 1296 policyDefinition, 1297 userId); 1298 IPackageManager packageManager = AppGlobals.getPackageManager(); 1299 for (EnforcingAdmin admin : policies.keySet()) { 1300 if (policies.get(admin).getValue() != null 1301 && policies.get(admin).getValue().getPackageName().equals(packageName)) { 1302 try { 1303 if (packageManager.getPackageInfo(packageName, 0, userId) == null 1304 || packageManager.getActivityInfo( 1305 policies.get(admin).getValue(), 0, userId) == null) { 1306 Slogf.e(TAG, String.format( 1307 "Persistent preferred activity in package %s not found for " 1308 + "user %d, removing policy for admin", 1309 packageName, userId)); 1310 removeLocalPolicy(policyDefinition, admin, userId); 1311 } 1312 } catch (RemoteException re) { 1313 // Shouldn't happen. 1314 Slogf.wtf(TAG, "Error handling package changes", re); 1315 } 1316 } 1317 } 1318 } 1319 } 1320 isPackageInstalled(String packageName, int userId)1321 private boolean isPackageInstalled(String packageName, int userId) { 1322 try { 1323 return AppGlobals.getPackageManager().getPackageInfo( 1324 packageName, 0, userId) != null; 1325 } catch (RemoteException re) { 1326 // Shouldn't happen. 1327 Slogf.wtf(TAG, "Error handling package changes", re); 1328 return true; 1329 } 1330 } 1331 1332 /** 1333 * Handles internal state related to a user getting removed. 1334 */ handleUserRemoved(int userId)1335 void handleUserRemoved(int userId) { 1336 removeLocalPoliciesForUser(userId); 1337 removePoliciesForAdminsOnUser(userId); 1338 } 1339 1340 /** 1341 * Handles internal state related to a user getting created. 1342 */ handleUserCreated(UserInfo user)1343 void handleUserCreated(UserInfo user) { 1344 enforcePoliciesOnInheritableProfilesIfApplicable(user); 1345 } 1346 1347 /** 1348 * Handles internal state related to roles getting updated. 1349 */ handleRoleChanged(@onNull String roleName, int userId)1350 void handleRoleChanged(@NonNull String roleName, int userId) { 1351 // TODO(b/256852787): handle all roles changing. 1352 if (!DEVICE_LOCK_CONTROLLER_ROLE.equals(roleName)) { 1353 // We only support device lock controller role for now. 1354 return; 1355 } 1356 String roleAuthority = EnforcingAdmin.getRoleAuthorityOf(roleName); 1357 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1358 for (EnforcingAdmin admin : admins) { 1359 if (admin.hasAuthority(roleAuthority)) { 1360 admin.reloadRoleAuthorities(); 1361 // remove admin policies if role was lost 1362 if (!admin.hasAuthority(roleAuthority)) { 1363 removePoliciesForAdmin(admin); 1364 } 1365 } 1366 } 1367 } 1368 enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user)1369 private void enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user) { 1370 if (!user.isProfile()) { 1371 return; 1372 } 1373 1374 Binder.withCleanCallingIdentity(() -> { 1375 UserProperties userProperties = mUserManager.getUserProperties(user.getUserHandle()); 1376 if (userProperties == null || userProperties.getInheritDevicePolicy() 1377 != INHERIT_DEVICE_POLICY_FROM_PARENT) { 1378 return; 1379 } 1380 1381 int userId = user.id; 1382 // Apply local policies present on parent to newly created child profile. 1383 UserInfo parentInfo = mUserManager.getProfileParent(userId); 1384 if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) { 1385 return; 1386 } 1387 synchronized (mLock) { 1388 if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) { 1389 return; 1390 } 1391 for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get( 1392 parentInfo.getUserHandle().getIdentifier()).entrySet()) { 1393 enforcePolicyOnUserLocked(userId, entry.getValue()); 1394 } 1395 } 1396 }); 1397 } 1398 1399 @GuardedBy("mLock") enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState)1400 private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) { 1401 if (!policyState.getPolicyDefinition().isInheritable()) { 1402 return; 1403 } 1404 for (Map.Entry<EnforcingAdmin, PolicyValue<V>> enforcingAdminEntry : 1405 policyState.getPoliciesSetByAdmins().entrySet()) { 1406 setLocalPolicy(policyState.getPolicyDefinition(), 1407 enforcingAdminEntry.getKey(), 1408 enforcingAdminEntry.getValue(), 1409 userId); 1410 } 1411 } 1412 1413 /** 1414 * Returns all current enforced policies set on the device, and the individual values set by 1415 * each admin. Global policies are returned under {@link UserHandle#ALL}. 1416 */ 1417 @NonNull getDevicePolicyState()1418 DevicePolicyState getDevicePolicyState() { 1419 synchronized (mLock) { 1420 Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies = 1421 new HashMap<>(); 1422 for (int i = 0; i < mLocalPolicies.size(); i++) { 1423 UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i)); 1424 policies.put(user, new HashMap<>()); 1425 for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) { 1426 policies.get(user).put( 1427 policyKey, 1428 mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState()); 1429 } 1430 } 1431 if (!mGlobalPolicies.isEmpty()) { 1432 policies.put(UserHandle.ALL, new HashMap<>()); 1433 for (PolicyKey policyKey : mGlobalPolicies.keySet()) { 1434 policies.get(UserHandle.ALL).put( 1435 policyKey, 1436 mGlobalPolicies.get(policyKey).getParcelablePolicyState()); 1437 } 1438 } 1439 return new DevicePolicyState(policies); 1440 } 1441 } 1442 1443 /** 1444 * Removes all local and global policies set by that admin. 1445 */ removePoliciesForAdmin(EnforcingAdmin admin)1446 void removePoliciesForAdmin(EnforcingAdmin admin) { 1447 synchronized (mLock) { 1448 Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet()); 1449 for (PolicyKey policy : globalPolicies) { 1450 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1451 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) { 1452 removeGlobalPolicy(policyState.getPolicyDefinition(), admin); 1453 } 1454 } 1455 1456 for (int i = 0; i < mLocalPolicies.size(); i++) { 1457 // New users are potentially added to mLocalPolicies during the loop body 1458 // (see b/374511959). 1459 int userId = mLocalPolicies.keyAt(i); 1460 Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet()); 1461 for (PolicyKey policy : localPolicies) { 1462 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1463 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) { 1464 removeLocalPolicy( 1465 policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i)); 1466 } 1467 } 1468 } 1469 } 1470 } 1471 1472 /** 1473 * Removes all local policies for the provided {@code userId}. 1474 */ removeLocalPoliciesForUser(int userId)1475 private void removeLocalPoliciesForUser(int userId) { 1476 synchronized (mLock) { 1477 if (!mLocalPolicies.contains(userId)) { 1478 // No policies on user 1479 return; 1480 } 1481 1482 Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet()); 1483 for (PolicyKey policy : localPolicies) { 1484 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1485 Set<EnforcingAdmin> admins = new HashSet<>( 1486 policyState.getPoliciesSetByAdmins().keySet()); 1487 for (EnforcingAdmin admin : admins) { 1488 removeLocalPolicy( 1489 policyState.getPolicyDefinition(), admin, userId); 1490 } 1491 } 1492 1493 mLocalPolicies.remove(userId); 1494 } 1495 } 1496 1497 /** 1498 * Removes all local and global policies for admins installed in the provided 1499 * {@code userId}. 1500 */ removePoliciesForAdminsOnUser(int userId)1501 private void removePoliciesForAdminsOnUser(int userId) { 1502 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1503 1504 for (EnforcingAdmin admin : admins) { 1505 removePoliciesForAdmin(admin); 1506 } 1507 } 1508 1509 /** 1510 * Reestablishes the service that handles 1511 * {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} in the enforcing admin if the package 1512 * was updated, as a package update results in the persistent connection getting reset. 1513 */ updateDeviceAdminServiceOnPackageChanged( @onNull String updatedPackage, int userId)1514 private void updateDeviceAdminServiceOnPackageChanged( 1515 @NonNull String updatedPackage, int userId) { 1516 for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) { 1517 // DPCs are handled separately in DPMS, no need to reestablish the connection here. 1518 if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1519 continue; 1520 } 1521 if (updatedPackage.equals(admin.getPackageName())) { 1522 mDeviceAdminServiceController.startServiceForAdmin( 1523 updatedPackage, userId, /* actionForLog= */ "package-broadcast"); 1524 } 1525 } 1526 } 1527 1528 /** 1529 * Called after an admin policy has been added to start binding to the admin if a connection 1530 * was not already established. 1531 */ 1532 @GuardedBy("mLock") updateDeviceAdminServiceOnPolicyAddLocked(@onNull EnforcingAdmin enforcingAdmin)1533 private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) { 1534 int userId = enforcingAdmin.getUserId(); 1535 1536 if (mEnforcingAdmins.contains(userId) 1537 && mEnforcingAdmins.get(userId).contains(enforcingAdmin)) { 1538 return; 1539 } 1540 1541 if (!mEnforcingAdmins.contains(enforcingAdmin.getUserId())) { 1542 mEnforcingAdmins.put(enforcingAdmin.getUserId(), new HashSet<>()); 1543 } 1544 mEnforcingAdmins.get(enforcingAdmin.getUserId()).add(enforcingAdmin); 1545 1546 // A connection is established with DPCs as soon as they are provisioned, so no need to 1547 // connect when a policy is set. 1548 if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1549 return; 1550 } 1551 mDeviceAdminServiceController.startServiceForAdmin( 1552 enforcingAdmin.getPackageName(), 1553 userId, 1554 /* actionForLog= */ "policy-added"); 1555 } 1556 1557 /** 1558 * Called after an admin policy has been removed to stop binding to the admin if they no longer 1559 * have any policies set. 1560 */ 1561 @GuardedBy("mLock") updateDeviceAdminServiceOnPolicyRemoveLocked( @onNull EnforcingAdmin enforcingAdmin)1562 private void updateDeviceAdminServiceOnPolicyRemoveLocked( 1563 @NonNull EnforcingAdmin enforcingAdmin) { 1564 if (doesAdminHavePoliciesLocked(enforcingAdmin)) { 1565 return; 1566 } 1567 int userId = enforcingAdmin.getUserId(); 1568 if (mEnforcingAdmins.contains(userId)) { 1569 mEnforcingAdmins.get(userId).remove(enforcingAdmin); 1570 if (mEnforcingAdmins.get(userId).isEmpty()) { 1571 mEnforcingAdmins.remove(enforcingAdmin.getUserId()); 1572 } 1573 } 1574 1575 // TODO(b/263364434): centralise handling in one place. 1576 // DPCs rely on a constant connection being established as soon as they are provisioned, 1577 // so we shouldn't disconnect it even if they no longer have policies set. 1578 if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1579 return; 1580 } 1581 mDeviceAdminServiceController.stopServiceForAdmin( 1582 enforcingAdmin.getPackageName(), 1583 userId, 1584 /* actionForLog= */ "policy-removed"); 1585 } 1586 1587 @GuardedBy("mLock") doesAdminHavePoliciesLocked(@onNull EnforcingAdmin enforcingAdmin)1588 private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) { 1589 for (PolicyKey policy : mGlobalPolicies.keySet()) { 1590 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1591 if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) { 1592 return true; 1593 } 1594 } 1595 for (int i = 0; i < mLocalPolicies.size(); i++) { 1596 for (PolicyKey policy : mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet()) { 1597 PolicyState<?> policyState = mLocalPolicies.get( 1598 mLocalPolicies.keyAt(i)).get(policy); 1599 if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) { 1600 return true; 1601 } 1602 } 1603 } 1604 return false; 1605 } 1606 1607 @NonNull getEnforcingAdminsOnUser(int userId)1608 private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) { 1609 synchronized (mLock) { 1610 return mEnforcingAdmins.contains(userId) 1611 ? new HashSet<>(mEnforcingAdmins.get(userId)) : Collections.emptySet(); 1612 } 1613 } 1614 1615 /** 1616 * Calculate the size of a policy in bytes 1617 */ sizeOf(PolicyValue<V> value)1618 private static <V> int sizeOf(PolicyValue<V> value) { 1619 try { 1620 Parcel parcel = Parcel.obtain(); 1621 parcel.writeParcelable(value, /* flags= */ 0); 1622 1623 parcel.setDataPosition(0); 1624 1625 byte[] bytes; 1626 1627 bytes = parcel.marshall(); 1628 return bytes.length; 1629 } catch (Exception e) { 1630 Log.e(TAG, "Error calculating size of policy: " + e); 1631 return 0; 1632 } 1633 } 1634 1635 /** 1636 * Checks if the policy already exists and removes the current size to prevent recording the 1637 * same policy twice. 1638 * 1639 * Checks if the new sum of the size of all policies is less than the maximum sum of policies 1640 * size per admin and returns true. 1641 * 1642 * If the policy size limit is reached then send policy result to admin and return false. 1643 */ handleAdminPolicySizeLimit(PolicyState<V> policyState, EnforcingAdmin admin, PolicyValue<V> value, PolicyDefinition<V> policyDefinition, int userId)1644 private <V> boolean handleAdminPolicySizeLimit(PolicyState<V> policyState, EnforcingAdmin admin, 1645 PolicyValue<V> value, PolicyDefinition<V> policyDefinition, int userId) { 1646 int currentAdminPoliciesSize = 0; 1647 int existingPolicySize = 0; 1648 if (mAdminPolicySize.contains(admin.getUserId()) 1649 && mAdminPolicySize.get( 1650 admin.getUserId()).containsKey(admin)) { 1651 currentAdminPoliciesSize = mAdminPolicySize.get(admin.getUserId()).get(admin); 1652 } 1653 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) { 1654 existingPolicySize = sizeOf(policyState.getPoliciesSetByAdmins().get(admin)); 1655 } 1656 int policySize = sizeOf(value); 1657 1658 // Policy size limit is disabled if mPolicySizeLimit is -1. 1659 if (mPolicySizeLimit == -1 1660 || currentAdminPoliciesSize + policySize - existingPolicySize < mPolicySizeLimit) { 1661 increasePolicySizeForAdmin( 1662 admin, /* policySizeDiff = */ policySize - existingPolicySize); 1663 return true; 1664 } else { 1665 Log.w(TAG, "Admin " + admin + "reached max allowed storage limit."); 1666 sendPolicyResultToAdmin( 1667 admin, 1668 policyDefinition, 1669 RESULT_FAILURE_STORAGE_LIMIT_REACHED, 1670 userId); 1671 return false; 1672 } 1673 } 1674 1675 /** 1676 * Increase the int in mAdminPolicySize representing the size of the sum of all 1677 * active policies for that admin. 1678 */ increasePolicySizeForAdmin(EnforcingAdmin admin, int policySizeDiff)1679 private <V> void increasePolicySizeForAdmin(EnforcingAdmin admin, int policySizeDiff) { 1680 if (!mAdminPolicySize.contains(admin.getUserId())) { 1681 mAdminPolicySize.put(admin.getUserId(), new HashMap<>()); 1682 } 1683 if (!mAdminPolicySize.get(admin.getUserId()).containsKey(admin)) { 1684 mAdminPolicySize.get(admin.getUserId()).put(admin, /* size= */ 0); 1685 } 1686 mAdminPolicySize.get(admin.getUserId()).put(admin, 1687 mAdminPolicySize.get(admin.getUserId()).get(admin) + policySizeDiff); 1688 } 1689 1690 /** 1691 * Decrease the int in mAdminPolicySize representing the size of the sum of all 1692 * active policies for that admin. 1693 */ decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin)1694 private <V> void decreasePolicySizeForAdmin(PolicyState<V> policyState, EnforcingAdmin admin) { 1695 if (!policyState.getPoliciesSetByAdmins().containsKey(admin) 1696 || !mAdminPolicySize.contains(admin.getUserId()) 1697 || !mAdminPolicySize.get(admin.getUserId()).containsKey(admin)) { 1698 return; 1699 } 1700 mAdminPolicySize.get(admin.getUserId()).put(admin, 1701 mAdminPolicySize.get(admin.getUserId()).get(admin) - sizeOf( 1702 policyState.getPoliciesSetByAdmins().get(admin))); 1703 if (mAdminPolicySize.get(admin.getUserId()).get(admin) <= 0) { 1704 mAdminPolicySize.get(admin.getUserId()).remove(admin); 1705 } 1706 if (mAdminPolicySize.get(admin.getUserId()).isEmpty()) { 1707 mAdminPolicySize.remove(admin.getUserId()); 1708 } 1709 } 1710 1711 /** 1712 * Updates the max allowed size limit for policies per admin. Setting it to -1, disables 1713 * the limitation. 1714 */ setMaxPolicyStorageLimit(int storageLimit)1715 void setMaxPolicyStorageLimit(int storageLimit) { 1716 mPolicySizeLimit = storageLimit; 1717 } 1718 1719 /** 1720 * Returns the max allowed size limit for policies per admin. -1 means the limitation is 1721 * disabled. 1722 */ getMaxPolicyStorageLimit()1723 int getMaxPolicyStorageLimit() { 1724 return mPolicySizeLimit; 1725 } 1726 getPolicySizeForAdmin(EnforcingAdmin admin)1727 int getPolicySizeForAdmin(EnforcingAdmin admin) { 1728 if (mAdminPolicySize.contains(admin.getUserId()) 1729 && mAdminPolicySize.get( 1730 admin.getUserId()).containsKey(admin)) { 1731 return mAdminPolicySize.get(admin.getUserId()).get(admin); 1732 } 1733 return 0; 1734 } 1735 dump(IndentingPrintWriter pw)1736 public void dump(IndentingPrintWriter pw) { 1737 synchronized (mLock) { 1738 pw.println("Local Policies: "); 1739 pw.increaseIndent(); 1740 for (int i = 0; i < mLocalPolicies.size(); i++) { 1741 int userId = mLocalPolicies.keyAt(i); 1742 pw.printf("User %d:\n", userId); 1743 pw.increaseIndent(); 1744 for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) { 1745 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1746 policyState.dump(pw); 1747 pw.println(); 1748 } 1749 pw.decreaseIndent(); 1750 } 1751 pw.decreaseIndent(); 1752 pw.println(); 1753 1754 pw.println("Global Policies: "); 1755 pw.increaseIndent(); 1756 for (PolicyKey policy : mGlobalPolicies.keySet()) { 1757 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1758 policyState.dump(pw); 1759 pw.println(); 1760 } 1761 pw.decreaseIndent(); 1762 pw.println(); 1763 1764 pw.println("Default admin policy size limit: " + DEFAULT_POLICY_SIZE_LIMIT); 1765 pw.println("Current admin policy size limit: " + mPolicySizeLimit); 1766 pw.println("Admin Policies size: "); 1767 for (int i = 0; i < mAdminPolicySize.size(); i++) { 1768 int userId = mAdminPolicySize.keyAt(i); 1769 pw.printf("User %d:\n", userId); 1770 pw.increaseIndent(); 1771 for (EnforcingAdmin admin : mAdminPolicySize.get(userId).keySet()) { 1772 pw.printf("Admin : " + admin + " : " + mAdminPolicySize.get(userId).get( 1773 admin)); 1774 pw.println(); 1775 } 1776 pw.decreaseIndent(); 1777 } 1778 pw.decreaseIndent(); 1779 } 1780 } 1781 write()1782 private void write() { 1783 synchronized (mLock) { 1784 Log.d(TAG, "Writing device policies to file."); 1785 new DevicePoliciesReaderWriter().writeToFileLocked(); 1786 } 1787 } 1788 1789 // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated 1790 // and could result in a different enforced policy load()1791 void load() { 1792 Log.d(TAG, "Reading device policies from file."); 1793 synchronized (mLock) { 1794 clear(); 1795 new DevicePoliciesReaderWriter().readFromFileLocked(); 1796 } 1797 } 1798 1799 /** 1800 * Create a backup of the policy engine XML file, so that we can recover previous state 1801 * in case some data-loss bug is triggered e.g. during migration. 1802 * 1803 * Backup is only created if one with the same ID does not exist yet. 1804 */ createBackup(String backupId)1805 void createBackup(String backupId) { 1806 synchronized (mLock) { 1807 DevicePoliciesReaderWriter.createBackup(backupId); 1808 } 1809 } 1810 1811 @GuardedBy("mLock") reapplyAllPoliciesOnBootLocked()1812 <V> void reapplyAllPoliciesOnBootLocked() { 1813 for (PolicyKey policy : mGlobalPolicies.keySet()) { 1814 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1815 // Policy definition and value will always be of the same type 1816 PolicyDefinition<V> policyDefinition = 1817 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 1818 if (!policyDefinition.shouldSkipEnforcementIfNotChanged()) { 1819 PolicyValue<V> policyValue = 1820 (PolicyValue<V>) policyState.getCurrentResolvedPolicy(); 1821 enforcePolicy(policyDefinition, policyValue, UserHandle.USER_ALL); 1822 } 1823 } 1824 for (int i = 0; i < mLocalPolicies.size(); i++) { 1825 int userId = mLocalPolicies.keyAt(i); 1826 for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) { 1827 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1828 // Policy definition and value will always be of the same type 1829 PolicyDefinition<V> policyDefinition = 1830 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 1831 if (!policyDefinition.shouldSkipEnforcementIfNotChanged()) { 1832 PolicyValue<V> policyValue = 1833 (PolicyValue<V>) policyState.getCurrentResolvedPolicy(); 1834 enforcePolicy(policyDefinition, policyValue, userId); 1835 } 1836 } 1837 } 1838 } 1839 1840 /** 1841 * Clear all policies set in the policy engine. 1842 * 1843 * <p>Note that this doesn't clear any enforcements, it only clears the data structures. 1844 */ clearAllPolicies()1845 void clearAllPolicies() { 1846 clear(); 1847 write(); 1848 } 1849 clear()1850 private void clear() { 1851 synchronized (mLock) { 1852 mGlobalPolicies.clear(); 1853 mLocalPolicies.clear(); 1854 mEnforcingAdmins.clear(); 1855 mAdminPolicySize.clear(); 1856 } 1857 } 1858 checkFor2gFailure(@onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)1859 private <V> boolean checkFor2gFailure(@NonNull PolicyDefinition<V> policyDefinition, 1860 @NonNull EnforcingAdmin enforcingAdmin) { 1861 if (!policyDefinition.getPolicyKey().getIdentifier().equals( 1862 CELLULAR_2G_USER_RESTRICTION_ID)) { 1863 return false; 1864 } 1865 1866 boolean isCapabilitySupported; 1867 try { 1868 isCapabilitySupported = mContext.getSystemService( 1869 TelephonyManager.class).isRadioInterfaceCapabilitySupported( 1870 TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK); 1871 } catch (IllegalStateException e) { 1872 // isRadioInterfaceCapabilitySupported can throw if there is no Telephony 1873 // service initialized. 1874 isCapabilitySupported = false; 1875 } 1876 1877 if (!isCapabilitySupported) { 1878 sendPolicyResultToAdmin( 1879 enforcingAdmin, 1880 policyDefinition, 1881 RESULT_FAILURE_HARDWARE_LIMITATION, 1882 UserHandle.USER_ALL); 1883 return true; 1884 } 1885 1886 return false; 1887 } 1888 1889 /** 1890 * For PackageSetUnion policies, we can't simply compare the resolved policy against the admin's 1891 * policy for equality to determine if the admin has applied the policy successfully, instead 1892 * the admin's policy should be considered applied successfully as long as its policy is subset 1893 * of the resolved policy. This method controls which policies should use this special logic. 1894 */ shouldApplyPackageSetUnionPolicyHack(PolicyDefinition<V> policy)1895 private <V> boolean shouldApplyPackageSetUnionPolicyHack(PolicyDefinition<V> policy) { 1896 String policyKey = policy.getPolicyKey().getIdentifier(); 1897 return policyKey.equals(USER_CONTROL_DISABLED_PACKAGES_POLICY) 1898 || policyKey.equals(PACKAGES_SUSPENDED_POLICY); 1899 } 1900 1901 private class DevicePoliciesReaderWriter { 1902 private static final String DEVICE_POLICIES_XML = "device_policy_state.xml"; 1903 private static final String BACKUP_DIRECTORY = "device_policy_backups"; 1904 private static final String BACKUP_FILENAME = "device_policy_state.%s.xml"; 1905 private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry"; 1906 private static final String TAG_GLOBAL_POLICY_ENTRY = "global-policy-entry"; 1907 private static final String TAG_POLICY_STATE_ENTRY = "policy-state-entry"; 1908 private static final String TAG_POLICY_KEY_ENTRY = "policy-key-entry"; 1909 private static final String TAG_ENFORCING_ADMINS_ENTRY = "enforcing-admins-entry"; 1910 private static final String TAG_ENFORCING_ADMIN_AND_SIZE = "enforcing-admin-and-size"; 1911 private static final String TAG_ENFORCING_ADMIN = "enforcing-admin"; 1912 private static final String TAG_POLICY_SUM_SIZE = "policy-sum-size"; 1913 private static final String TAG_MAX_POLICY_SIZE_LIMIT = "max-policy-size-limit"; 1914 private static final String ATTR_USER_ID = "user-id"; 1915 private static final String ATTR_POLICY_SUM_SIZE = "size"; 1916 1917 private final File mFile; 1918 getFileName()1919 private static File getFileName() { 1920 return new File(Environment.getDataSystemDirectory(), DEVICE_POLICIES_XML); 1921 } 1922 DevicePoliciesReaderWriter()1923 private DevicePoliciesReaderWriter() { 1924 mFile = getFileName(); 1925 } 1926 createBackup(String backupId)1927 public static void createBackup(String backupId) { 1928 try { 1929 File backupDirectory = new File(Environment.getDataSystemDirectory(), 1930 BACKUP_DIRECTORY); 1931 backupDirectory.mkdir(); 1932 Path backupPath = Path.of(backupDirectory.getPath(), 1933 BACKUP_FILENAME.formatted(backupId)); 1934 if (backupPath.toFile().exists()) { 1935 Log.w(TAG, "Backup already exist: " + backupPath); 1936 } else { 1937 Files.copy(getFileName().toPath(), backupPath, 1938 StandardCopyOption.REPLACE_EXISTING); 1939 Log.i(TAG, "Backup created at " + backupPath); 1940 } 1941 } catch (Exception e) { 1942 Log.e(TAG, "Cannot create backup " + backupId, e); 1943 } 1944 } 1945 1946 @GuardedBy("mLock") writeToFileLocked()1947 void writeToFileLocked() { 1948 Log.d(TAG, "Writing to " + mFile); 1949 1950 AtomicFile f = new AtomicFile(mFile); 1951 FileOutputStream outputStream = null; 1952 try { 1953 outputStream = f.startWrite(); 1954 TypedXmlSerializer out = Xml.resolveSerializer(outputStream); 1955 1956 out.startDocument(null, true); 1957 1958 // Actual content 1959 writeInnerLocked(out); 1960 1961 out.endDocument(); 1962 out.flush(); 1963 1964 // Commit the content. 1965 f.finishWrite(outputStream); 1966 outputStream = null; 1967 1968 } catch (IOException e) { 1969 Log.e(TAG, "Exception when writing", e); 1970 if (outputStream != null) { 1971 f.failWrite(outputStream); 1972 } 1973 } 1974 } 1975 1976 @GuardedBy("mLock") 1977 // TODO(b/256846294): Add versioning to read/write writeInnerLocked(TypedXmlSerializer serializer)1978 void writeInnerLocked(TypedXmlSerializer serializer) throws IOException { 1979 writeLocalPoliciesInnerLocked(serializer); 1980 writeGlobalPoliciesInnerLocked(serializer); 1981 writeEnforcingAdminsInnerLocked(serializer); 1982 writeEnforcingAdminSizeInnerLocked(serializer); 1983 writeMaxPolicySizeInnerLocked(serializer); 1984 } 1985 1986 @GuardedBy("mLock") writeLocalPoliciesInnerLocked(TypedXmlSerializer serializer)1987 private void writeLocalPoliciesInnerLocked(TypedXmlSerializer serializer) 1988 throws IOException { 1989 if (mLocalPolicies != null) { 1990 for (int i = 0; i < mLocalPolicies.size(); i++) { 1991 int userId = mLocalPolicies.keyAt(i); 1992 for (Map.Entry<PolicyKey, PolicyState<?>> policy : mLocalPolicies.get( 1993 userId).entrySet()) { 1994 serializer.startTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY); 1995 1996 serializer.attributeInt(/* namespace= */ null, ATTR_USER_ID, userId); 1997 1998 serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 1999 policy.getKey().saveToXml(serializer); 2000 serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 2001 2002 serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 2003 policy.getValue().saveToXml(serializer); 2004 serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 2005 2006 serializer.endTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY); 2007 } 2008 } 2009 } 2010 } 2011 2012 @GuardedBy("mLock") writeGlobalPoliciesInnerLocked(TypedXmlSerializer serializer)2013 private void writeGlobalPoliciesInnerLocked(TypedXmlSerializer serializer) 2014 throws IOException { 2015 if (mGlobalPolicies != null) { 2016 for (Map.Entry<PolicyKey, PolicyState<?>> policy : mGlobalPolicies.entrySet()) { 2017 serializer.startTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY); 2018 2019 serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 2020 policy.getKey().saveToXml(serializer); 2021 serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 2022 2023 serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 2024 policy.getValue().saveToXml(serializer); 2025 serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 2026 2027 serializer.endTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY); 2028 } 2029 } 2030 } 2031 2032 @GuardedBy("mLock") writeEnforcingAdminsInnerLocked(TypedXmlSerializer serializer)2033 private void writeEnforcingAdminsInnerLocked(TypedXmlSerializer serializer) 2034 throws IOException { 2035 if (mEnforcingAdmins != null) { 2036 for (int i = 0; i < mEnforcingAdmins.size(); i++) { 2037 int userId = mEnforcingAdmins.keyAt(i); 2038 for (EnforcingAdmin admin : mEnforcingAdmins.get(userId)) { 2039 serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY); 2040 admin.saveToXml(serializer); 2041 serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY); 2042 } 2043 } 2044 } 2045 } 2046 2047 @GuardedBy("mLock") writeEnforcingAdminSizeInnerLocked(TypedXmlSerializer serializer)2048 private void writeEnforcingAdminSizeInnerLocked(TypedXmlSerializer serializer) 2049 throws IOException { 2050 if (mAdminPolicySize != null) { 2051 for (int i = 0; i < mAdminPolicySize.size(); i++) { 2052 int userId = mAdminPolicySize.keyAt(i); 2053 for (EnforcingAdmin admin : mAdminPolicySize.get( 2054 userId).keySet()) { 2055 serializer.startTag(/* namespace= */ null, 2056 TAG_ENFORCING_ADMIN_AND_SIZE); 2057 serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN); 2058 admin.saveToXml(serializer); 2059 serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMIN); 2060 serializer.startTag(/* namespace= */ null, TAG_POLICY_SUM_SIZE); 2061 serializer.attributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE, 2062 mAdminPolicySize.get(userId).get(admin)); 2063 serializer.endTag(/* namespace= */ null, TAG_POLICY_SUM_SIZE); 2064 serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_AND_SIZE); 2065 } 2066 } 2067 } 2068 } 2069 2070 @GuardedBy("mLock") writeMaxPolicySizeInnerLocked(TypedXmlSerializer serializer)2071 private void writeMaxPolicySizeInnerLocked(TypedXmlSerializer serializer) 2072 throws IOException { 2073 serializer.startTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT); 2074 serializer.attributeInt( 2075 /* namespace= */ null, ATTR_POLICY_SUM_SIZE, mPolicySizeLimit); 2076 serializer.endTag(/* namespace= */ null, TAG_MAX_POLICY_SIZE_LIMIT); 2077 } 2078 2079 @GuardedBy("mLock") readFromFileLocked()2080 void readFromFileLocked() { 2081 if (!mFile.exists()) { 2082 Log.d(TAG, "" + mFile + " doesn't exist"); 2083 return; 2084 } 2085 2086 Log.d(TAG, "Reading from " + mFile); 2087 AtomicFile f = new AtomicFile(mFile); 2088 InputStream input = null; 2089 try { 2090 input = f.openRead(); 2091 TypedXmlPullParser parser = Xml.resolvePullParser(input); 2092 2093 readInnerLocked(parser); 2094 2095 } catch (XmlPullParserException | IOException | ClassNotFoundException e) { 2096 Slogf.wtf(TAG, "Error parsing resources file", e); 2097 } finally { 2098 IoUtils.closeQuietly(input); 2099 } 2100 } 2101 2102 @GuardedBy("mLock") readInnerLocked(TypedXmlPullParser parser)2103 private void readInnerLocked(TypedXmlPullParser parser) 2104 throws IOException, XmlPullParserException, ClassNotFoundException { 2105 int outerDepth = parser.getDepth(); 2106 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2107 String tag = parser.getName(); 2108 switch (tag) { 2109 case TAG_LOCAL_POLICY_ENTRY: 2110 int userId = parser.getAttributeInt(/* namespace= */ null, ATTR_USER_ID); 2111 if (!mLocalPolicies.contains(userId)) { 2112 mLocalPolicies.put(userId, new HashMap<>()); 2113 } 2114 readPoliciesInner(parser, mLocalPolicies.get(userId)); 2115 break; 2116 case TAG_GLOBAL_POLICY_ENTRY: 2117 readPoliciesInner(parser, mGlobalPolicies); 2118 break; 2119 case TAG_ENFORCING_ADMINS_ENTRY: 2120 readEnforcingAdminsInner(parser); 2121 break; 2122 case TAG_ENFORCING_ADMIN_AND_SIZE: 2123 readEnforcingAdminAndSizeInner(parser); 2124 break; 2125 case TAG_MAX_POLICY_SIZE_LIMIT: 2126 readMaxPolicySizeInner(parser); 2127 break; 2128 default: 2129 Slogf.wtf(TAG, "Unknown tag " + tag); 2130 } 2131 } 2132 } 2133 readPoliciesInner( TypedXmlPullParser parser, Map<PolicyKey, PolicyState<?>> policyStateMap)2134 private static void readPoliciesInner( 2135 TypedXmlPullParser parser, Map<PolicyKey, PolicyState<?>> policyStateMap) 2136 throws IOException, XmlPullParserException { 2137 PolicyKey policyKey = null; 2138 PolicyDefinition<?> policyDefinition = null; 2139 PolicyState<?> policyState = null; 2140 int outerDepth = parser.getDepth(); 2141 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2142 String tag = parser.getName(); 2143 switch (tag) { 2144 case TAG_POLICY_KEY_ENTRY: 2145 policyDefinition = PolicyDefinition.readFromXml(parser); 2146 if (policyDefinition != null) { 2147 policyKey = policyDefinition.getPolicyKey(); 2148 } 2149 break; 2150 case TAG_POLICY_STATE_ENTRY: 2151 if (policyDefinition == null) { 2152 Slogf.w(TAG, "Skipping policy state - unknown policy definition"); 2153 } else { 2154 policyState = PolicyState.readFromXml(policyDefinition, parser); 2155 } 2156 break; 2157 default: 2158 Slogf.wtf(TAG, "Unknown tag for policy entry" + tag); 2159 } 2160 } 2161 2162 if (policyKey == null || policyState == null) { 2163 Slogf.wtf(TAG, "Error parsing policy, policyKey is %s, and policyState is %s.", 2164 policyKey, policyState); 2165 return; 2166 } 2167 2168 policyStateMap.put(policyKey, policyState); 2169 } 2170 readEnforcingAdminsInner(TypedXmlPullParser parser)2171 private void readEnforcingAdminsInner(TypedXmlPullParser parser) 2172 throws XmlPullParserException { 2173 EnforcingAdmin admin = EnforcingAdmin.readFromXml(parser); 2174 if (admin == null) { 2175 Slogf.wtf(TAG, "Error parsing enforcingAdmins, EnforcingAdmin is null."); 2176 return; 2177 } 2178 if (!mEnforcingAdmins.contains(admin.getUserId())) { 2179 mEnforcingAdmins.put(admin.getUserId(), new HashSet<>()); 2180 } 2181 mEnforcingAdmins.get(admin.getUserId()).add(admin); 2182 } 2183 readEnforcingAdminAndSizeInner(TypedXmlPullParser parser)2184 private void readEnforcingAdminAndSizeInner(TypedXmlPullParser parser) 2185 throws XmlPullParserException, IOException { 2186 int outerDepth = parser.getDepth(); 2187 EnforcingAdmin admin = null; 2188 int size = 0; 2189 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 2190 String tag = parser.getName(); 2191 switch (tag) { 2192 case TAG_ENFORCING_ADMIN: 2193 admin = EnforcingAdmin.readFromXml(parser); 2194 break; 2195 case TAG_POLICY_SUM_SIZE: 2196 size = parser.getAttributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE); 2197 break; 2198 default: 2199 Slogf.wtf(TAG, "Unknown tag " + tag); 2200 } 2201 } 2202 if (admin == null) { 2203 Slogf.wtf(TAG, "Error parsing enforcingAdmins, EnforcingAdmin is null."); 2204 return; 2205 } 2206 if (size <= 0) { 2207 Slogf.wtf(TAG, "Error parsing policy size, size is " + size); 2208 return; 2209 } 2210 if (!mAdminPolicySize.contains(admin.getUserId())) { 2211 mAdminPolicySize.put(admin.getUserId(), new HashMap<>()); 2212 } 2213 mAdminPolicySize.get(admin.getUserId()).put(admin, size); 2214 } 2215 readMaxPolicySizeInner(TypedXmlPullParser parser)2216 private void readMaxPolicySizeInner(TypedXmlPullParser parser) 2217 throws XmlPullParserException, IOException { 2218 mPolicySizeLimit = parser.getAttributeInt(/* namespace= */ null, ATTR_POLICY_SUM_SIZE); 2219 } 2220 } 2221 } 2222