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