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.USER_CONTROL_DISABLED_PACKAGES_POLICY; 20 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_TARGET_USER_ID; 21 import static android.app.admin.PolicyUpdateReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY; 22 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_CONFLICTING_ADMIN_POLICY; 23 import static android.app.admin.PolicyUpdateResult.RESULT_FAILURE_HARDWARE_LIMITATION; 24 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_CLEARED; 25 import static android.app.admin.PolicyUpdateResult.RESULT_POLICY_SET; 26 import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; 27 28 import android.Manifest; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.app.AppGlobals; 32 import android.app.BroadcastOptions; 33 import android.app.admin.DevicePolicyIdentifiers; 34 import android.app.admin.DevicePolicyManager; 35 import android.app.admin.DevicePolicyState; 36 import android.app.admin.IntentFilterPolicyKey; 37 import android.app.admin.PolicyKey; 38 import android.app.admin.PolicyUpdateReceiver; 39 import android.app.admin.PolicyValue; 40 import android.app.admin.TargetUser; 41 import android.app.admin.UserRestrictionPolicyKey; 42 import android.content.ComponentName; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.pm.IPackageManager; 47 import android.content.pm.PackageManager; 48 import android.content.pm.ResolveInfo; 49 import android.content.pm.UserInfo; 50 import android.content.pm.UserProperties; 51 import android.os.Binder; 52 import android.os.Bundle; 53 import android.os.Environment; 54 import android.os.RemoteException; 55 import android.os.UserHandle; 56 import android.os.UserManager; 57 import android.telephony.TelephonyManager; 58 import android.util.AtomicFile; 59 import android.util.Log; 60 import android.util.SparseArray; 61 import android.util.Xml; 62 63 import com.android.internal.util.XmlUtils; 64 import com.android.modules.utils.TypedXmlPullParser; 65 import com.android.modules.utils.TypedXmlSerializer; 66 import com.android.server.utils.Slogf; 67 68 import libcore.io.IoUtils; 69 70 import org.xmlpull.v1.XmlPullParserException; 71 72 import java.io.File; 73 import java.io.FileOutputStream; 74 import java.io.IOException; 75 import java.io.InputStream; 76 import java.util.Collections; 77 import java.util.HashMap; 78 import java.util.HashSet; 79 import java.util.LinkedHashMap; 80 import java.util.List; 81 import java.util.Map; 82 import java.util.Objects; 83 import java.util.Set; 84 85 /** 86 * Class responsible for setting, resolving, and enforcing policies set by multiple management 87 * admins on the device. 88 */ 89 final class DevicePolicyEngine { 90 static final String TAG = "DevicePolicyEngine"; 91 92 // TODO(b/281701062): reference role name from role manager once its exposed. 93 static final String DEVICE_LOCK_CONTROLLER_ROLE = 94 "android.app.role.SYSTEM_FINANCED_DEVICE_CONTROLLER"; 95 96 private static final String CELLULAR_2G_USER_RESTRICTION_ID = 97 DevicePolicyIdentifiers.getIdentifierForUserRestriction( 98 UserManager.DISALLOW_CELLULAR_2G); 99 100 private final Context mContext; 101 private final UserManager mUserManager; 102 103 // TODO(b/256849338): add more granular locks 104 private final Object mLock; 105 106 /** 107 * Map of <userId, Map<policyKey, policyState>> 108 */ 109 private final SparseArray<Map<PolicyKey, PolicyState<?>>> mLocalPolicies; 110 111 /** 112 * Map of <policyKey, policyState> 113 */ 114 private final Map<PolicyKey, PolicyState<?>> mGlobalPolicies; 115 116 /** 117 * Map containing the current set of admins in each user with active policies. 118 */ 119 private final SparseArray<Set<EnforcingAdmin>> mEnforcingAdmins; 120 121 private final DeviceAdminServiceController mDeviceAdminServiceController; 122 DevicePolicyEngine( @onNull Context context, @NonNull DeviceAdminServiceController deviceAdminServiceController, @NonNull Object lock)123 DevicePolicyEngine( 124 @NonNull Context context, 125 @NonNull DeviceAdminServiceController deviceAdminServiceController, 126 @NonNull Object lock) { 127 mContext = Objects.requireNonNull(context); 128 mDeviceAdminServiceController = Objects.requireNonNull(deviceAdminServiceController); 129 mLock = Objects.requireNonNull(lock); 130 mUserManager = mContext.getSystemService(UserManager.class); 131 mLocalPolicies = new SparseArray<>(); 132 mGlobalPolicies = new HashMap<>(); 133 mEnforcingAdmins = new SparseArray<>(); 134 } 135 136 /** 137 * Set the policy for the provided {@code policyDefinition} (see {@link PolicyDefinition}) and 138 * {@code enforcingAdmin} to the provided {@code value}. 139 * 140 * <p>If {@code skipEnforcePolicy} is true, it sets the policies in the internal data structure 141 * but doesn't call the enforcing logic. 142 * 143 */ setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId, boolean skipEnforcePolicy)144 <V> void setLocalPolicy( 145 @NonNull PolicyDefinition<V> policyDefinition, 146 @NonNull EnforcingAdmin enforcingAdmin, 147 @Nullable PolicyValue<V> value, 148 int userId, 149 boolean skipEnforcePolicy) { 150 Objects.requireNonNull(policyDefinition); 151 Objects.requireNonNull(enforcingAdmin); 152 153 synchronized (mLock) { 154 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 155 156 if (policyDefinition.isNonCoexistablePolicy()) { 157 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState, 158 enforcingAdmin, value, userId, skipEnforcePolicy); 159 return; 160 } 161 162 boolean hasGlobalPolicies = hasGlobalPolicyLocked(policyDefinition); 163 boolean policyChanged; 164 if (hasGlobalPolicies) { 165 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 166 policyChanged = localPolicyState.addPolicy( 167 enforcingAdmin, 168 value, 169 globalPolicyState.getPoliciesSetByAdmins()); 170 } else { 171 policyChanged = localPolicyState.addPolicy(enforcingAdmin, value); 172 } 173 174 // No need to notify admins as no new policy is actually enforced, we're just filling in 175 // the data structures. 176 if (!skipEnforcePolicy) { 177 if (policyChanged) { 178 onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId); 179 } 180 boolean policyEnforced = Objects.equals( 181 localPolicyState.getCurrentResolvedPolicy(), value); 182 // TODO(b/285532044): remove hack and handle properly 183 if (!policyEnforced 184 && policyDefinition.getPolicyKey().getIdentifier().equals( 185 USER_CONTROL_DISABLED_PACKAGES_POLICY)) { 186 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 187 PolicyValue<Set<String>> parsedResolvedValue = 188 (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy(); 189 policyEnforced = (parsedResolvedValue != null && parsedValue != null 190 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 191 } 192 sendPolicyResultToAdmin( 193 enforcingAdmin, 194 policyDefinition, 195 // TODO: we're always sending this for now, should properly handle errors. 196 policyEnforced 197 ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY, 198 userId); 199 } 200 201 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 202 203 write(); 204 205 applyToInheritableProfiles(policyDefinition, enforcingAdmin, value, userId); 206 } 207 } 208 209 /** 210 * Sets a non-coexistable policy, meaning it doesn't get resolved against other policies set 211 * by other admins, and no callbacks are sent to admins, this is just storing and 212 * enforcing the policy. 213 * 214 * <p>Passing a {@code null} value means the policy set by this admin should be removed. 215 */ setNonCoexistableLocalPolicyLocked( PolicyDefinition<V> policyDefinition, PolicyState<V> localPolicyState, EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, int userId, boolean skipEnforcePolicy)216 private <V> void setNonCoexistableLocalPolicyLocked( 217 PolicyDefinition<V> policyDefinition, 218 PolicyState<V> localPolicyState, 219 EnforcingAdmin enforcingAdmin, 220 @Nullable PolicyValue<V> value, 221 int userId, 222 boolean skipEnforcePolicy) { 223 if (value == null) { 224 localPolicyState.removePolicy(enforcingAdmin); 225 } else { 226 localPolicyState.addPolicy(enforcingAdmin, value); 227 } 228 if (!skipEnforcePolicy) { 229 enforcePolicy(policyDefinition, value, userId); 230 } 231 if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) { 232 removeLocalPolicyStateLocked(policyDefinition, userId); 233 } 234 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 235 write(); 236 } 237 238 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 239 /** 240 * Set the policy for the provided {@code policyDefinition} 241 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 242 */ setLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, int userId)243 <V> void setLocalPolicy( 244 @NonNull PolicyDefinition<V> policyDefinition, 245 @NonNull EnforcingAdmin enforcingAdmin, 246 @NonNull PolicyValue<V> value, 247 int userId) { 248 setLocalPolicy( 249 policyDefinition, enforcingAdmin, value, userId, /* skipEnforcePolicy= */ false); 250 } 251 252 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 253 /** 254 * Removes any previously set policy for the provided {@code policyDefinition} 255 * (see {@link PolicyDefinition}) and {@code enforcingAdmin}. 256 */ removeLocalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)257 <V> void removeLocalPolicy( 258 @NonNull PolicyDefinition<V> policyDefinition, 259 @NonNull EnforcingAdmin enforcingAdmin, 260 int userId) { 261 Objects.requireNonNull(policyDefinition); 262 Objects.requireNonNull(enforcingAdmin); 263 264 synchronized (mLock) { 265 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 266 return; 267 } 268 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 269 270 if (policyDefinition.isNonCoexistablePolicy()) { 271 setNonCoexistableLocalPolicyLocked(policyDefinition, localPolicyState, 272 enforcingAdmin, /* value= */ null, userId, /* skipEnforcePolicy= */ false); 273 return; 274 } 275 276 boolean policyChanged; 277 if (hasGlobalPolicyLocked(policyDefinition)) { 278 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 279 policyChanged = localPolicyState.removePolicy( 280 enforcingAdmin, 281 globalPolicyState.getPoliciesSetByAdmins()); 282 } else { 283 policyChanged = localPolicyState.removePolicy(enforcingAdmin); 284 } 285 286 if (policyChanged) { 287 onLocalPolicyChangedLocked(policyDefinition, enforcingAdmin, userId); 288 } 289 290 // For a removePolicy to be enforced, it means no current policy exists 291 sendPolicyResultToAdmin( 292 enforcingAdmin, 293 policyDefinition, 294 // TODO: we're always sending this for now, should properly handle errors. 295 RESULT_POLICY_CLEARED, 296 userId); 297 298 if (localPolicyState.getPoliciesSetByAdmins().isEmpty()) { 299 removeLocalPolicyStateLocked(policyDefinition, userId); 300 } 301 302 updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin); 303 304 write(); 305 306 applyToInheritableProfiles(policyDefinition, enforcingAdmin, /*value */ null, userId); 307 } 308 } 309 310 /** 311 * If any of child user has property {@link UserProperties#INHERIT_DEVICE_POLICY_FROM_PARENT} 312 * set then propagate the policy to it if value is not null 313 * else remove the policy from child. 314 */ applyToInheritableProfiles(PolicyDefinition<V> policyDefinition, EnforcingAdmin enforcingAdmin, PolicyValue<V> value, int userId)315 private <V> void applyToInheritableProfiles(PolicyDefinition<V> policyDefinition, 316 EnforcingAdmin enforcingAdmin, PolicyValue<V> value, int userId) { 317 if (policyDefinition.isInheritable()) { 318 Binder.withCleanCallingIdentity(() -> { 319 List<UserInfo> userInfos = mUserManager.getProfiles(userId); 320 for (UserInfo childUserInfo : userInfos) { 321 int childUserId = childUserInfo.getUserHandle().getIdentifier(); 322 if (isProfileOfUser(childUserId, userId) 323 && isInheritDevicePolicyFromParent(childUserInfo)) { 324 if (value != null) { 325 setLocalPolicy(policyDefinition, enforcingAdmin, value, childUserId); 326 } else { 327 removeLocalPolicy(policyDefinition, enforcingAdmin, childUserId); 328 } 329 } 330 } 331 }); 332 } 333 } 334 335 /** 336 * Checks if given parentUserId is direct parent of childUserId. 337 */ isProfileOfUser(int childUserId, int parentUserId)338 private boolean isProfileOfUser(int childUserId, int parentUserId) { 339 UserInfo parentInfo = mUserManager.getProfileParent(childUserId); 340 return childUserId != parentUserId && parentInfo != null 341 && parentInfo.getUserHandle().getIdentifier() == parentUserId; 342 } 343 isInheritDevicePolicyFromParent(UserInfo userInfo)344 private boolean isInheritDevicePolicyFromParent(UserInfo userInfo) { 345 UserProperties userProperties = mUserManager.getUserProperties(userInfo.getUserHandle()); 346 return userProperties != null && mUserManager.getUserProperties(userInfo.getUserHandle()) 347 .getInheritDevicePolicy() == INHERIT_DEVICE_POLICY_FROM_PARENT; 348 } 349 350 /** 351 * Enforces the new policy and notifies relevant admins. 352 */ onLocalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)353 private <V> void onLocalPolicyChangedLocked( 354 @NonNull PolicyDefinition<V> policyDefinition, 355 @NonNull EnforcingAdmin enforcingAdmin, 356 int userId) { 357 358 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 359 enforcePolicy( 360 policyDefinition, localPolicyState.getCurrentResolvedPolicy(), userId); 361 362 // Send policy updates to admins who've set it locally 363 sendPolicyChangedToAdminsLocked( 364 localPolicyState, 365 enforcingAdmin, 366 policyDefinition, 367 // This policy change is only relevant to a single user, not the global 368 // policy value, 369 userId); 370 371 // Send policy updates to admins who've set it globally 372 if (hasGlobalPolicyLocked(policyDefinition)) { 373 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 374 sendPolicyChangedToAdminsLocked( 375 globalPolicyState, 376 enforcingAdmin, 377 policyDefinition, 378 userId); 379 } 380 sendDevicePolicyChangedToSystem(userId); 381 } 382 383 /** 384 * Set the policy for the provided {@code policyDefinition} 385 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 386 */ setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value)387 <V> void setGlobalPolicy( 388 @NonNull PolicyDefinition<V> policyDefinition, 389 @NonNull EnforcingAdmin enforcingAdmin, 390 @NonNull PolicyValue<V> value) { 391 setGlobalPolicy(policyDefinition, enforcingAdmin, value, /* skipEnforcePolicy= */ false); 392 } 393 394 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 395 /** 396 * Set the policy for the provided {@code policyDefinition} 397 * (see {@link PolicyDefinition}) and {@code enforcingAdmin} to the provided {@code value}. 398 */ setGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @NonNull PolicyValue<V> value, boolean skipEnforcePolicy)399 <V> void setGlobalPolicy( 400 @NonNull PolicyDefinition<V> policyDefinition, 401 @NonNull EnforcingAdmin enforcingAdmin, 402 @NonNull PolicyValue<V> value, 403 boolean skipEnforcePolicy) { 404 405 Objects.requireNonNull(policyDefinition); 406 Objects.requireNonNull(enforcingAdmin); 407 Objects.requireNonNull(value); 408 409 synchronized (mLock) { 410 // TODO(b/270999567): Move error handling for DISALLOW_CELLULAR_2G into the code 411 // that honors the restriction once there's an API available 412 if (checkFor2gFailure(policyDefinition, enforcingAdmin)) { 413 Log.i(TAG, 414 "Device does not support capabilities required to disable 2g. Not setting" 415 + " global policy state."); 416 return; 417 } 418 419 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 420 421 boolean policyChanged = globalPolicyState.addPolicy(enforcingAdmin, value); 422 boolean policyAppliedOnAllUsers = applyGlobalPolicyOnUsersWithLocalPoliciesLocked( 423 policyDefinition, enforcingAdmin, value, skipEnforcePolicy); 424 425 // No need to notify admins as no new policy is actually enforced, we're just filling in 426 // the data structures. 427 if (!skipEnforcePolicy) { 428 if (policyChanged) { 429 onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin); 430 } 431 432 boolean policyAppliedGlobally = Objects.equals( 433 globalPolicyState.getCurrentResolvedPolicy(), value); 434 // TODO(b/285532044): remove hack and handle properly 435 if (!policyAppliedGlobally 436 && policyDefinition.getPolicyKey().getIdentifier().equals( 437 USER_CONTROL_DISABLED_PACKAGES_POLICY)) { 438 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 439 PolicyValue<Set<String>> parsedResolvedValue = 440 (PolicyValue<Set<String>>) globalPolicyState.getCurrentResolvedPolicy(); 441 policyAppliedGlobally = (parsedResolvedValue != null && parsedValue != null 442 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 443 } 444 445 boolean policyApplied = policyAppliedGlobally && policyAppliedOnAllUsers; 446 447 sendPolicyResultToAdmin( 448 enforcingAdmin, 449 policyDefinition, 450 // TODO: we're always sending this for now, should properly handle errors. 451 policyApplied ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY, 452 UserHandle.USER_ALL); 453 } 454 455 updateDeviceAdminServiceOnPolicyAddLocked(enforcingAdmin); 456 457 write(); 458 } 459 } 460 461 // TODO: add more documentation on broadcasts/callbacks to use to get current enforced values 462 /** 463 * Removes any previously set policy for the provided {@code policyDefinition} 464 * (see {@link PolicyDefinition}) and {@code enforcingAdmin}. 465 */ removeGlobalPolicy( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)466 <V> void removeGlobalPolicy( 467 @NonNull PolicyDefinition<V> policyDefinition, 468 @NonNull EnforcingAdmin enforcingAdmin) { 469 470 Objects.requireNonNull(policyDefinition); 471 Objects.requireNonNull(enforcingAdmin); 472 473 synchronized (mLock) { 474 PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition); 475 boolean policyChanged = policyState.removePolicy(enforcingAdmin); 476 477 if (policyChanged) { 478 onGlobalPolicyChangedLocked(policyDefinition, enforcingAdmin); 479 } 480 481 applyGlobalPolicyOnUsersWithLocalPoliciesLocked(policyDefinition, enforcingAdmin, 482 /* value= */ null, /* skipEnforcePolicy= */ false); 483 484 sendPolicyResultToAdmin( 485 enforcingAdmin, 486 policyDefinition, 487 // TODO: we're always sending this for now, should properly handle errors. 488 RESULT_POLICY_CLEARED, 489 UserHandle.USER_ALL); 490 491 if (policyState.getPoliciesSetByAdmins().isEmpty()) { 492 removeGlobalPolicyStateLocked(policyDefinition); 493 } 494 495 updateDeviceAdminServiceOnPolicyRemoveLocked(enforcingAdmin); 496 497 write(); 498 } 499 } 500 501 /** 502 * Enforces the new policy globally and notifies relevant admins. 503 */ onGlobalPolicyChangedLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)504 private <V> void onGlobalPolicyChangedLocked( 505 @NonNull PolicyDefinition<V> policyDefinition, 506 @NonNull EnforcingAdmin enforcingAdmin) { 507 PolicyState<V> policyState = getGlobalPolicyStateLocked(policyDefinition); 508 509 enforcePolicy(policyDefinition, policyState.getCurrentResolvedPolicy(), 510 UserHandle.USER_ALL); 511 512 sendPolicyChangedToAdminsLocked( 513 policyState, 514 enforcingAdmin, 515 policyDefinition, 516 UserHandle.USER_ALL); 517 518 sendDevicePolicyChangedToSystem(UserHandle.USER_ALL); 519 } 520 521 /** 522 * Tries to enforce the global policy locally on all users that have the same policy set 523 * locally, this is only applicable to policies that can be set locally or globally 524 * (e.g. setCameraDisabled, setScreenCaptureDisabled) rather than 525 * policies that are global by nature (e.g. setting Wifi enabled/disabled). 526 * 527 * <p> A {@code null} policy value means the policy was removed 528 * 529 * <p>Returns {@code true} if the policy is enforced successfully on all users. 530 */ applyGlobalPolicyOnUsersWithLocalPoliciesLocked( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, @Nullable PolicyValue<V> value, boolean skipEnforcePolicy)531 private <V> boolean applyGlobalPolicyOnUsersWithLocalPoliciesLocked( 532 @NonNull PolicyDefinition<V> policyDefinition, 533 @NonNull EnforcingAdmin enforcingAdmin, 534 @Nullable PolicyValue<V> value, 535 boolean skipEnforcePolicy) { 536 // Global only policies can't be applied locally, return early. 537 if (policyDefinition.isGlobalOnlyPolicy()) { 538 return true; 539 } 540 boolean isAdminPolicyApplied = true; 541 for (int i = 0; i < mLocalPolicies.size(); i++) { 542 int userId = mLocalPolicies.keyAt(i); 543 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 544 continue; 545 } 546 547 PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId); 548 PolicyState<V> globalPolicyState = getGlobalPolicyStateLocked(policyDefinition); 549 550 boolean policyChanged = localPolicyState.resolvePolicy( 551 globalPolicyState.getPoliciesSetByAdmins()); 552 if (policyChanged && !skipEnforcePolicy) { 553 enforcePolicy( 554 policyDefinition, 555 localPolicyState.getCurrentResolvedPolicy(), 556 userId); 557 sendPolicyChangedToAdminsLocked( 558 localPolicyState, 559 enforcingAdmin, 560 policyDefinition, 561 // Even though this is caused by a global policy change, admins who've set 562 // it locally should only care about the local user state. 563 userId); 564 565 } 566 // TODO(b/285532044): remove hack and handle properly 567 if (policyDefinition.getPolicyKey().getIdentifier().equals( 568 USER_CONTROL_DISABLED_PACKAGES_POLICY)) { 569 if (!Objects.equals(value, localPolicyState.getCurrentResolvedPolicy())) { 570 PolicyValue<Set<String>> parsedValue = (PolicyValue<Set<String>>) value; 571 PolicyValue<Set<String>> parsedResolvedValue = 572 (PolicyValue<Set<String>>) localPolicyState.getCurrentResolvedPolicy(); 573 isAdminPolicyApplied &= (parsedResolvedValue != null && parsedValue != null 574 && parsedResolvedValue.getValue().containsAll(parsedValue.getValue())); 575 } 576 } else { 577 isAdminPolicyApplied &= Objects.equals( 578 value, localPolicyState.getCurrentResolvedPolicy()); 579 } 580 } 581 return isAdminPolicyApplied; 582 } 583 584 /** 585 * Retrieves the resolved policy for the provided {@code policyDefinition} and {@code userId}. 586 */ 587 @Nullable getResolvedPolicy(@onNull PolicyDefinition<V> policyDefinition, int userId)588 <V> V getResolvedPolicy(@NonNull PolicyDefinition<V> policyDefinition, int userId) { 589 Objects.requireNonNull(policyDefinition); 590 591 synchronized (mLock) { 592 PolicyValue<V> resolvedValue = null; 593 if (hasLocalPolicyLocked(policyDefinition, userId)) { 594 resolvedValue = getLocalPolicyStateLocked( 595 policyDefinition, userId).getCurrentResolvedPolicy(); 596 } else if (hasGlobalPolicyLocked(policyDefinition)) { 597 resolvedValue = getGlobalPolicyStateLocked( 598 policyDefinition).getCurrentResolvedPolicy(); 599 } 600 return resolvedValue == null ? null : resolvedValue.getValue(); 601 } 602 } 603 604 /** 605 * Retrieves the policy set by the admin for the provided {@code policyDefinition} and 606 * {@code userId} if one was set, otherwise returns {@code null}. 607 */ 608 @Nullable getLocalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)609 <V> V getLocalPolicySetByAdmin( 610 @NonNull PolicyDefinition<V> policyDefinition, 611 @NonNull EnforcingAdmin enforcingAdmin, 612 int userId) { 613 Objects.requireNonNull(policyDefinition); 614 Objects.requireNonNull(enforcingAdmin); 615 616 synchronized (mLock) { 617 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 618 return null; 619 } 620 PolicyValue<V> value = getLocalPolicyStateLocked(policyDefinition, userId) 621 .getPoliciesSetByAdmins().get(enforcingAdmin); 622 return value == null ? null : value.getValue(); 623 } 624 } 625 626 /** 627 * Retrieves the global policy set by the admin for the provided {@code policyDefinition} and 628 * if one was set, otherwise returns {@code null}. 629 */ 630 @Nullable getGlobalPolicySetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)631 <V> V getGlobalPolicySetByAdmin( 632 @NonNull PolicyDefinition<V> policyDefinition, 633 @NonNull EnforcingAdmin enforcingAdmin) { 634 Objects.requireNonNull(policyDefinition); 635 Objects.requireNonNull(enforcingAdmin); 636 637 synchronized (mLock) { 638 if (!hasGlobalPolicyLocked(policyDefinition)) { 639 return null; 640 } 641 PolicyValue<V> value = getGlobalPolicyStateLocked(policyDefinition) 642 .getPoliciesSetByAdmins().get(enforcingAdmin); 643 return value == null ? null : value.getValue(); 644 } 645 } 646 647 /** 648 * Retrieves the values set for the provided {@code policyDefinition} by each admin. 649 */ 650 @NonNull getLocalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)651 <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getLocalPoliciesSetByAdmins( 652 @NonNull PolicyDefinition<V> policyDefinition, 653 int userId) { 654 Objects.requireNonNull(policyDefinition); 655 656 synchronized (mLock) { 657 if (!hasLocalPolicyLocked(policyDefinition, userId)) { 658 return new LinkedHashMap<>(); 659 } 660 return getLocalPolicyStateLocked(policyDefinition, userId).getPoliciesSetByAdmins(); 661 } 662 } 663 664 /** 665 * Retrieves the values set for the provided {@code policyDefinition} by each admin. 666 */ 667 @NonNull getGlobalPoliciesSetByAdmins( @onNull PolicyDefinition<V> policyDefinition)668 <V> LinkedHashMap<EnforcingAdmin, PolicyValue<V>> getGlobalPoliciesSetByAdmins( 669 @NonNull PolicyDefinition<V> policyDefinition) { 670 Objects.requireNonNull(policyDefinition); 671 672 synchronized (mLock) { 673 if (!hasGlobalPolicyLocked(policyDefinition)) { 674 return new LinkedHashMap<>(); 675 } 676 return getGlobalPolicyStateLocked(policyDefinition).getPoliciesSetByAdmins(); 677 } 678 } 679 680 /** 681 * Returns the policies set by the given admin that share the same 682 * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. 683 * 684 * <p>For example, getLocalPolicyKeysSetByAdmin(PERMISSION_GRANT, admin) returns all permission 685 * grants set by the given admin. 686 * 687 * <p>Note that this will always return at most one item for policies that do not require 688 * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs 689 * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). 690 * 691 */ 692 @NonNull getLocalPolicyKeysSetByAdmin( @onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin, int userId)693 <V> Set<PolicyKey> getLocalPolicyKeysSetByAdmin( 694 @NonNull PolicyDefinition<V> policyDefinition, 695 @NonNull EnforcingAdmin enforcingAdmin, 696 int userId) { 697 Objects.requireNonNull(policyDefinition); 698 Objects.requireNonNull(enforcingAdmin); 699 700 synchronized (mLock) { 701 if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { 702 return Set.of(); 703 } 704 Set<PolicyKey> keys = new HashSet<>(); 705 for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { 706 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey()) 707 && mLocalPolicies.get(userId).get(key).getPoliciesSetByAdmins() 708 .containsKey(enforcingAdmin)) { 709 keys.add(key); 710 } 711 } 712 return keys; 713 } 714 } 715 716 /** 717 * Returns all the {@code policyKeys} set by any admin that share the same 718 * {@link PolicyKey#getIdentifier()} as the provided {@code policyDefinition}. 719 * 720 * <p>For example, getLocalPolicyKeysSetByAllAdmins(PERMISSION_GRANT) returns all permission 721 * grants set by any admin. 722 * 723 * <p>Note that this will always return at most one item for policies that do not require 724 * additional params (e.g. {@link PolicyDefinition#LOCK_TASK} vs 725 * {@link PolicyDefinition#PERMISSION_GRANT(String, String)}). 726 * 727 */ 728 @NonNull getLocalPolicyKeysSetByAllAdmins( @onNull PolicyDefinition<V> policyDefinition, int userId)729 <V> Set<PolicyKey> getLocalPolicyKeysSetByAllAdmins( 730 @NonNull PolicyDefinition<V> policyDefinition, 731 int userId) { 732 Objects.requireNonNull(policyDefinition); 733 734 synchronized (mLock) { 735 if (policyDefinition.isGlobalOnlyPolicy() || !mLocalPolicies.contains(userId)) { 736 return Set.of(); 737 } 738 Set<PolicyKey> keys = new HashSet<>(); 739 for (PolicyKey key : mLocalPolicies.get(userId).keySet()) { 740 if (key.hasSameIdentifierAs(policyDefinition.getPolicyKey())) { 741 keys.add(key); 742 } 743 } 744 return keys; 745 } 746 } 747 748 /** 749 * Returns all user restriction policies set by the given admin. 750 * 751 * <p>Pass in {@link UserHandle#USER_ALL} for {@code userId} to get global restrictions set by 752 * the admin 753 */ 754 @NonNull getUserRestrictionPolicyKeysForAdmin( @onNull EnforcingAdmin admin, int userId)755 Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdmin( 756 @NonNull EnforcingAdmin admin, 757 int userId) { 758 Objects.requireNonNull(admin); 759 synchronized (mLock) { 760 if (userId == UserHandle.USER_ALL) { 761 return getUserRestrictionPolicyKeysForAdminLocked(mGlobalPolicies, admin); 762 } 763 if (!mLocalPolicies.contains(userId)) { 764 return Set.of(); 765 } 766 return getUserRestrictionPolicyKeysForAdminLocked(mLocalPolicies.get(userId), admin); 767 } 768 } 769 transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin)770 <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) { 771 synchronized (mLock) { 772 Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet()); 773 for (PolicyKey policy : globalPolicies) { 774 PolicyState<?> policyState = mGlobalPolicies.get(policy); 775 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) { 776 PolicyDefinition<V> policyDefinition = 777 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 778 PolicyValue<V> policyValue = 779 (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin); 780 setGlobalPolicy(policyDefinition, newAdmin, policyValue); 781 } 782 } 783 784 for (int i = 0; i < mLocalPolicies.size(); i++) { 785 int userId = mLocalPolicies.keyAt(i); 786 Set<PolicyKey> localPolicies = new HashSet<>( 787 mLocalPolicies.get(userId).keySet()); 788 for (PolicyKey policy : localPolicies) { 789 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 790 if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) { 791 PolicyDefinition<V> policyDefinition = 792 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 793 PolicyValue<V> policyValue = 794 (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin); 795 setLocalPolicy(policyDefinition, newAdmin, policyValue, userId); 796 } 797 } 798 } 799 } 800 removePoliciesForAdmin(oldAdmin); 801 } 802 getUserRestrictionPolicyKeysForAdminLocked( Map<PolicyKey, PolicyState<?>> policies, EnforcingAdmin admin)803 private Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdminLocked( 804 Map<PolicyKey, PolicyState<?>> policies, 805 EnforcingAdmin admin) { 806 Set<UserRestrictionPolicyKey> keys = new HashSet<>(); 807 for (PolicyKey key : policies.keySet()) { 808 if (!policies.get(key).getPolicyDefinition().isUserRestrictionPolicy()) { 809 continue; 810 } 811 // User restriction policies are always boolean 812 PolicyValue<Boolean> value = (PolicyValue<Boolean>) policies.get(key) 813 .getPoliciesSetByAdmins().get(admin); 814 if (value == null || !value.getValue()) { 815 continue; 816 } 817 keys.add((UserRestrictionPolicyKey) key); 818 } 819 return keys; 820 } 821 hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId)822 private <V> boolean hasLocalPolicyLocked(PolicyDefinition<V> policyDefinition, int userId) { 823 if (policyDefinition.isGlobalOnlyPolicy()) { 824 return false; 825 } 826 if (!mLocalPolicies.contains(userId)) { 827 return false; 828 } 829 if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) { 830 return false; 831 } 832 return !mLocalPolicies.get(userId).get(policyDefinition.getPolicyKey()) 833 .getPoliciesSetByAdmins().isEmpty(); 834 } 835 hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition)836 private <V> boolean hasGlobalPolicyLocked(PolicyDefinition<V> policyDefinition) { 837 if (policyDefinition.isLocalOnlyPolicy()) { 838 return false; 839 } 840 if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) { 841 return false; 842 } 843 return !mGlobalPolicies.get(policyDefinition.getPolicyKey()).getPoliciesSetByAdmins() 844 .isEmpty(); 845 } 846 847 @NonNull getLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)848 private <V> PolicyState<V> getLocalPolicyStateLocked( 849 PolicyDefinition<V> policyDefinition, int userId) { 850 851 if (policyDefinition.isGlobalOnlyPolicy()) { 852 throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a global only" 853 + " policy."); 854 } 855 856 if (!mLocalPolicies.contains(userId)) { 857 mLocalPolicies.put(userId, new HashMap<>()); 858 } 859 if (!mLocalPolicies.get(userId).containsKey(policyDefinition.getPolicyKey())) { 860 mLocalPolicies.get(userId).put( 861 policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition)); 862 } 863 return getPolicyStateLocked(mLocalPolicies.get(userId), policyDefinition); 864 } 865 removeLocalPolicyStateLocked( PolicyDefinition<V> policyDefinition, int userId)866 private <V> void removeLocalPolicyStateLocked( 867 PolicyDefinition<V> policyDefinition, int userId) { 868 if (!mLocalPolicies.contains(userId)) { 869 return; 870 } 871 mLocalPolicies.get(userId).remove(policyDefinition.getPolicyKey()); 872 } 873 874 @NonNull getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)875 private <V> PolicyState<V> getGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) { 876 if (policyDefinition.isLocalOnlyPolicy()) { 877 throw new IllegalArgumentException(policyDefinition.getPolicyKey() + " is a local only" 878 + " policy."); 879 } 880 881 if (!mGlobalPolicies.containsKey(policyDefinition.getPolicyKey())) { 882 mGlobalPolicies.put( 883 policyDefinition.getPolicyKey(), new PolicyState<>(policyDefinition)); 884 } 885 return getPolicyStateLocked(mGlobalPolicies, policyDefinition); 886 } 887 removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition)888 private <V> void removeGlobalPolicyStateLocked(PolicyDefinition<V> policyDefinition) { 889 mGlobalPolicies.remove(policyDefinition.getPolicyKey()); 890 } 891 getPolicyStateLocked( Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition)892 private static <V> PolicyState<V> getPolicyStateLocked( 893 Map<PolicyKey, PolicyState<?>> policies, PolicyDefinition<V> policyDefinition) { 894 try { 895 // This will not throw an exception because policyDefinition is of type V, so unless 896 // we've created two policies with the same key but different types - we can only have 897 // stored a PolicyState of the right type. 898 PolicyState<V> policyState = (PolicyState<V>) policies.get( 899 policyDefinition.getPolicyKey()); 900 return policyState; 901 } catch (ClassCastException exception) { 902 // TODO: handle exception properly 903 throw new IllegalArgumentException(); 904 } 905 } 906 enforcePolicy(PolicyDefinition<V> policyDefinition, @Nullable PolicyValue<V> policyValue, int userId)907 private <V> void enforcePolicy(PolicyDefinition<V> policyDefinition, 908 @Nullable PolicyValue<V> policyValue, int userId) { 909 // null policyValue means remove any enforced policies, ensure callbacks handle this 910 // properly 911 policyDefinition.enforcePolicy( 912 policyValue == null ? null : policyValue.getValue(), mContext, userId); 913 } 914 sendDevicePolicyChangedToSystem(int userId)915 private void sendDevicePolicyChangedToSystem(int userId) { 916 Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); 917 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 918 Bundle options = new BroadcastOptions() 919 .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT) 920 .setDeferralPolicy(BroadcastOptions.DEFERRAL_POLICY_UNTIL_ACTIVE) 921 .toBundle(); 922 Binder.withCleanCallingIdentity(() -> mContext.sendBroadcastAsUser( 923 intent, 924 new UserHandle(userId), 925 /* receiverPermissions= */ null, 926 options)); 927 } 928 sendPolicyResultToAdmin( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId)929 private <V> void sendPolicyResultToAdmin( 930 EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int result, int userId) { 931 Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_SET_RESULT); 932 intent.setPackage(admin.getPackageName()); 933 934 Binder.withCleanCallingIdentity(() -> { 935 List<ResolveInfo> receivers = 936 mContext.getPackageManager().queryBroadcastReceiversAsUser( 937 intent, 938 PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), 939 admin.getUserId()); 940 if (receivers.isEmpty()) { 941 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_SET_RESULT" 942 + " in package " + admin.getPackageName()); 943 return; 944 } 945 946 Bundle extras = new Bundle(); 947 policyDefinition.getPolicyKey().writeToBundle(extras); 948 extras.putInt( 949 EXTRA_POLICY_TARGET_USER_ID, 950 getTargetUser(admin.getUserId(), userId)); 951 extras.putInt( 952 EXTRA_POLICY_UPDATE_RESULT_KEY, 953 result); 954 955 intent.putExtras(extras); 956 957 maybeSendIntentToAdminReceivers(intent, UserHandle.of(admin.getUserId()), receivers); 958 }); 959 } 960 961 // 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)962 private <V> void sendPolicyChangedToAdminsLocked( 963 PolicyState<V> policyState, 964 EnforcingAdmin callingAdmin, 965 PolicyDefinition<V> policyDefinition, 966 int userId) { 967 for (EnforcingAdmin admin: policyState.getPoliciesSetByAdmins().keySet()) { 968 // We're sending a separate broadcast for the calling admin with the result. 969 if (admin.equals(callingAdmin)) { 970 continue; 971 } 972 int result = Objects.equals( 973 policyState.getPoliciesSetByAdmins().get(admin), 974 policyState.getCurrentResolvedPolicy()) 975 ? RESULT_POLICY_SET : RESULT_FAILURE_CONFLICTING_ADMIN_POLICY; 976 maybeSendOnPolicyChanged( 977 admin, policyDefinition, result, userId); 978 } 979 } 980 maybeSendOnPolicyChanged( EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason, int userId)981 private <V> void maybeSendOnPolicyChanged( 982 EnforcingAdmin admin, PolicyDefinition<V> policyDefinition, int reason, 983 int userId) { 984 Intent intent = new Intent(PolicyUpdateReceiver.ACTION_DEVICE_POLICY_CHANGED); 985 intent.setPackage(admin.getPackageName()); 986 987 Binder.withCleanCallingIdentity(() -> { 988 List<ResolveInfo> receivers = 989 mContext.getPackageManager().queryBroadcastReceiversAsUser( 990 intent, 991 PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), 992 admin.getUserId()); 993 if (receivers.isEmpty()) { 994 Log.i(TAG, "Couldn't find any receivers that handle ACTION_DEVICE_POLICY_CHANGED" 995 + " in package " + admin.getPackageName()); 996 return; 997 } 998 999 Bundle extras = new Bundle(); 1000 policyDefinition.getPolicyKey().writeToBundle(extras); 1001 extras.putInt( 1002 EXTRA_POLICY_TARGET_USER_ID, 1003 getTargetUser(admin.getUserId(), userId)); 1004 extras.putInt(EXTRA_POLICY_UPDATE_RESULT_KEY, reason); 1005 intent.putExtras(extras); 1006 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1007 1008 maybeSendIntentToAdminReceivers( 1009 intent, UserHandle.of(admin.getUserId()), receivers); 1010 }); 1011 } 1012 maybeSendIntentToAdminReceivers( Intent intent, UserHandle userHandle, List<ResolveInfo> receivers)1013 private void maybeSendIntentToAdminReceivers( 1014 Intent intent, UserHandle userHandle, List<ResolveInfo> receivers) { 1015 for (ResolveInfo resolveInfo : receivers) { 1016 if (!Manifest.permission.BIND_DEVICE_ADMIN.equals( 1017 resolveInfo.activityInfo.permission)) { 1018 Log.w(TAG, "Receiver " + resolveInfo.activityInfo + " is not protected by " 1019 + "BIND_DEVICE_ADMIN permission!"); 1020 continue; 1021 } 1022 // TODO: If admins are always bound to, do I still need to set 1023 // "BroadcastOptions.setBackgroundActivityStartsAllowed"? 1024 // TODO: maybe protect it with a permission that is granted to the role so that we 1025 // don't accidentally send a broadcast to an admin that no longer holds the role. 1026 mContext.sendBroadcastAsUser(intent, userHandle); 1027 } 1028 } 1029 getTargetUser(int adminUserId, int targetUserId)1030 private int getTargetUser(int adminUserId, int targetUserId) { 1031 if (targetUserId == UserHandle.USER_ALL) { 1032 return TargetUser.GLOBAL_USER_ID; 1033 } 1034 if (adminUserId == targetUserId) { 1035 return TargetUser.LOCAL_USER_ID; 1036 } 1037 if (getProfileParentId(adminUserId) == targetUserId) { 1038 return TargetUser.PARENT_USER_ID; 1039 } 1040 return TargetUser.UNKNOWN_USER_ID; 1041 } 1042 getProfileParentId(int userId)1043 private int getProfileParentId(int userId) { 1044 return Binder.withCleanCallingIdentity(() -> { 1045 UserInfo parentUser = mUserManager.getProfileParent(userId); 1046 return parentUser != null ? parentUser.id : userId; 1047 }); 1048 } 1049 1050 /** 1051 * Starts/Stops the services that handle {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} 1052 * in the enforcing admins for the given {@code userId}. 1053 */ updateDeviceAdminsServicesForUser( int userId, boolean enable, @NonNull String actionForLog)1054 private void updateDeviceAdminsServicesForUser( 1055 int userId, boolean enable, @NonNull String actionForLog) { 1056 if (!enable) { 1057 mDeviceAdminServiceController.stopServicesForUser( 1058 userId, actionForLog); 1059 } else { 1060 for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) { 1061 // DPCs are handled separately in DPMS, no need to reestablish the connection here. 1062 if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1063 continue; 1064 } 1065 mDeviceAdminServiceController.startServiceForAdmin( 1066 admin.getPackageName(), userId, actionForLog); 1067 } 1068 } 1069 } 1070 1071 /** 1072 * Handles internal state related to a user getting started. 1073 */ handleStartUser(int userId)1074 void handleStartUser(int userId) { 1075 updateDeviceAdminsServicesForUser( 1076 userId, /* enable= */ true, /* actionForLog= */ "start-user"); 1077 } 1078 1079 /** 1080 * Handles internal state related to a user getting started. 1081 */ handleUnlockUser(int userId)1082 void handleUnlockUser(int userId) { 1083 updateDeviceAdminsServicesForUser( 1084 userId, /* enable= */ true, /* actionForLog= */ "unlock-user"); 1085 } 1086 1087 /** 1088 * Handles internal state related to a user getting stopped. 1089 */ handleStopUser(int userId)1090 void handleStopUser(int userId) { 1091 updateDeviceAdminsServicesForUser( 1092 userId, /* enable= */ false, /* actionForLog= */ "stop-user"); 1093 } 1094 1095 /** 1096 * Handles internal state related to packages getting updated. 1097 */ handlePackageChanged( @ullable String updatedPackage, int userId, @Nullable String removedDpcPackage)1098 void handlePackageChanged( 1099 @Nullable String updatedPackage, int userId, @Nullable String removedDpcPackage) { 1100 Binder.withCleanCallingIdentity(() -> { 1101 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1102 if (removedDpcPackage != null) { 1103 for (EnforcingAdmin admin : admins) { 1104 if (removedDpcPackage.equals(admin.getPackageName())) { 1105 removePoliciesForAdmin(admin); 1106 return; 1107 } 1108 } 1109 } 1110 for (EnforcingAdmin admin : admins) { 1111 if (updatedPackage == null || updatedPackage.equals(admin.getPackageName())) { 1112 if (!isPackageInstalled(admin.getPackageName(), userId)) { 1113 Slogf.i(TAG, String.format( 1114 "Admin package %s not found for user %d, removing admin policies", 1115 admin.getPackageName(), userId)); 1116 // remove policies for the uninstalled package 1117 removePoliciesForAdmin(admin); 1118 return; 1119 } 1120 } 1121 } 1122 if (updatedPackage != null) { 1123 updateDeviceAdminServiceOnPackageChanged(updatedPackage, userId); 1124 removePersistentPreferredActivityPoliciesForPackage(updatedPackage, userId); 1125 } 1126 }); 1127 } 1128 removePersistentPreferredActivityPoliciesForPackage( @onNull String packageName, int userId)1129 private void removePersistentPreferredActivityPoliciesForPackage( 1130 @NonNull String packageName, int userId) { 1131 Set<PolicyKey> policyKeys = getLocalPolicyKeysSetByAllAdmins( 1132 PolicyDefinition.GENERIC_PERSISTENT_PREFERRED_ACTIVITY, userId); 1133 for (PolicyKey key : policyKeys) { 1134 if (!(key instanceof IntentFilterPolicyKey)) { 1135 throw new IllegalStateException("PolicyKey for " 1136 + "PERSISTENT_PREFERRED_ACTIVITY is not of type " 1137 + "IntentFilterPolicyKey"); 1138 } 1139 IntentFilterPolicyKey parsedKey = 1140 (IntentFilterPolicyKey) key; 1141 IntentFilter intentFilter = Objects.requireNonNull(parsedKey.getIntentFilter()); 1142 PolicyDefinition<ComponentName> policyDefinition = 1143 PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(intentFilter); 1144 LinkedHashMap<EnforcingAdmin, PolicyValue<ComponentName>> policies = 1145 getLocalPoliciesSetByAdmins( 1146 policyDefinition, 1147 userId); 1148 IPackageManager packageManager = AppGlobals.getPackageManager(); 1149 for (EnforcingAdmin admin : policies.keySet()) { 1150 if (policies.get(admin).getValue() != null 1151 && policies.get(admin).getValue().getPackageName().equals(packageName)) { 1152 try { 1153 if (packageManager.getPackageInfo(packageName, 0, userId) == null 1154 || packageManager.getActivityInfo( 1155 policies.get(admin).getValue(), 0, userId) == null) { 1156 Slogf.e(TAG, String.format( 1157 "Persistent preferred activity in package %s not found for " 1158 + "user %d, removing policy for admin", 1159 packageName, userId)); 1160 removeLocalPolicy(policyDefinition, admin, userId); 1161 } 1162 } catch (RemoteException re) { 1163 // Shouldn't happen. 1164 Slogf.wtf(TAG, "Error handling package changes", re); 1165 } 1166 } 1167 } 1168 } 1169 } 1170 isPackageInstalled(String packageName, int userId)1171 private boolean isPackageInstalled(String packageName, int userId) { 1172 try { 1173 return AppGlobals.getPackageManager().getPackageInfo( 1174 packageName, 0, userId) != null; 1175 } catch (RemoteException re) { 1176 // Shouldn't happen. 1177 Slogf.wtf(TAG, "Error handling package changes", re); 1178 return true; 1179 } 1180 } 1181 1182 /** 1183 * Handles internal state related to a user getting removed. 1184 */ handleUserRemoved(int userId)1185 void handleUserRemoved(int userId) { 1186 removeLocalPoliciesForUser(userId); 1187 removePoliciesForAdminsOnUser(userId); 1188 } 1189 1190 /** 1191 * Handles internal state related to a user getting created. 1192 */ handleUserCreated(UserInfo user)1193 void handleUserCreated(UserInfo user) { 1194 enforcePoliciesOnInheritableProfilesIfApplicable(user); 1195 } 1196 1197 /** 1198 * Handles internal state related to roles getting updated. 1199 */ handleRoleChanged(@onNull String roleName, int userId)1200 void handleRoleChanged(@NonNull String roleName, int userId) { 1201 // TODO(b/256852787): handle all roles changing. 1202 if (!DEVICE_LOCK_CONTROLLER_ROLE.equals(roleName)) { 1203 // We only support device lock controller role for now. 1204 return; 1205 } 1206 String roleAuthority = EnforcingAdmin.getRoleAuthorityOf(roleName); 1207 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1208 for (EnforcingAdmin admin : admins) { 1209 if (admin.hasAuthority(roleAuthority)) { 1210 admin.reloadRoleAuthorities(); 1211 // remove admin policies if role was lost 1212 if (!admin.hasAuthority(roleAuthority)) { 1213 removePoliciesForAdmin(admin); 1214 } 1215 } 1216 } 1217 } 1218 enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user)1219 private void enforcePoliciesOnInheritableProfilesIfApplicable(UserInfo user) { 1220 if (!user.isProfile()) { 1221 return; 1222 } 1223 1224 Binder.withCleanCallingIdentity(() -> { 1225 UserProperties userProperties = mUserManager.getUserProperties(user.getUserHandle()); 1226 if (userProperties == null || userProperties.getInheritDevicePolicy() 1227 != INHERIT_DEVICE_POLICY_FROM_PARENT) { 1228 return; 1229 } 1230 1231 int userId = user.id; 1232 // Apply local policies present on parent to newly created child profile. 1233 UserInfo parentInfo = mUserManager.getProfileParent(userId); 1234 if (parentInfo == null || parentInfo.getUserHandle().getIdentifier() == userId) { 1235 return; 1236 } 1237 synchronized (mLock) { 1238 if (!mLocalPolicies.contains(parentInfo.getUserHandle().getIdentifier())) { 1239 return; 1240 } 1241 for (Map.Entry<PolicyKey, PolicyState<?>> entry : mLocalPolicies.get( 1242 parentInfo.getUserHandle().getIdentifier()).entrySet()) { 1243 enforcePolicyOnUserLocked(userId, entry.getValue()); 1244 } 1245 } 1246 }); 1247 } 1248 enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState)1249 private <V> void enforcePolicyOnUserLocked(int userId, PolicyState<V> policyState) { 1250 if (!policyState.getPolicyDefinition().isInheritable()) { 1251 return; 1252 } 1253 for (Map.Entry<EnforcingAdmin, PolicyValue<V>> enforcingAdminEntry : 1254 policyState.getPoliciesSetByAdmins().entrySet()) { 1255 setLocalPolicy(policyState.getPolicyDefinition(), 1256 enforcingAdminEntry.getKey(), 1257 enforcingAdminEntry.getValue(), 1258 userId); 1259 } 1260 } 1261 1262 /** 1263 * Returns all current enforced policies set on the device, and the individual values set by 1264 * each admin. Global policies are returned under {@link UserHandle#ALL}. 1265 */ 1266 @NonNull getDevicePolicyState()1267 DevicePolicyState getDevicePolicyState() { 1268 synchronized (mLock) { 1269 Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies = 1270 new HashMap<>(); 1271 for (int i = 0; i < mLocalPolicies.size(); i++) { 1272 UserHandle user = UserHandle.of(mLocalPolicies.keyAt(i)); 1273 policies.put(user, new HashMap<>()); 1274 for (PolicyKey policyKey : mLocalPolicies.valueAt(i).keySet()) { 1275 policies.get(user).put( 1276 policyKey, 1277 mLocalPolicies.valueAt(i).get(policyKey).getParcelablePolicyState()); 1278 } 1279 } 1280 if (!mGlobalPolicies.isEmpty()) { 1281 policies.put(UserHandle.ALL, new HashMap<>()); 1282 for (PolicyKey policyKey : mGlobalPolicies.keySet()) { 1283 policies.get(UserHandle.ALL).put( 1284 policyKey, 1285 mGlobalPolicies.get(policyKey).getParcelablePolicyState()); 1286 } 1287 } 1288 return new DevicePolicyState(policies); 1289 } 1290 } 1291 1292 1293 /** 1294 * Removes all local and global policies set by that admin. 1295 */ removePoliciesForAdmin(EnforcingAdmin admin)1296 void removePoliciesForAdmin(EnforcingAdmin admin) { 1297 synchronized (mLock) { 1298 Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet()); 1299 for (PolicyKey policy : globalPolicies) { 1300 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1301 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) { 1302 removeGlobalPolicy(policyState.getPolicyDefinition(), admin); 1303 } 1304 } 1305 1306 for (int i = 0; i < mLocalPolicies.size(); i++) { 1307 Set<PolicyKey> localPolicies = new HashSet<>( 1308 mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet()); 1309 for (PolicyKey policy : localPolicies) { 1310 PolicyState<?> policyState = mLocalPolicies.get( 1311 mLocalPolicies.keyAt(i)).get(policy); 1312 if (policyState.getPoliciesSetByAdmins().containsKey(admin)) { 1313 removeLocalPolicy( 1314 policyState.getPolicyDefinition(), admin, mLocalPolicies.keyAt(i)); 1315 } 1316 } 1317 } 1318 } 1319 } 1320 1321 /** 1322 * Removes all local policies for the provided {@code userId}. 1323 */ removeLocalPoliciesForUser(int userId)1324 private void removeLocalPoliciesForUser(int userId) { 1325 synchronized (mLock) { 1326 if (!mLocalPolicies.contains(userId)) { 1327 // No policies on user 1328 return; 1329 } 1330 1331 Set<PolicyKey> localPolicies = new HashSet<>(mLocalPolicies.get(userId).keySet()); 1332 for (PolicyKey policy : localPolicies) { 1333 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1334 Set<EnforcingAdmin> admins = new HashSet<>( 1335 policyState.getPoliciesSetByAdmins().keySet()); 1336 for (EnforcingAdmin admin : admins) { 1337 removeLocalPolicy( 1338 policyState.getPolicyDefinition(), admin, userId); 1339 } 1340 } 1341 1342 mLocalPolicies.remove(userId); 1343 } 1344 } 1345 1346 /** 1347 * Removes all local and global policies for admins installed in the provided 1348 * {@code userId}. 1349 */ removePoliciesForAdminsOnUser(int userId)1350 private void removePoliciesForAdminsOnUser(int userId) { 1351 Set<EnforcingAdmin> admins = getEnforcingAdminsOnUser(userId); 1352 1353 for (EnforcingAdmin admin : admins) { 1354 removePoliciesForAdmin(admin); 1355 } 1356 } 1357 1358 /** 1359 * Reestablishes the service that handles 1360 * {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} in the enforcing admin if the package 1361 * was updated, as a package update results in the persistent connection getting reset. 1362 */ updateDeviceAdminServiceOnPackageChanged( @onNull String updatedPackage, int userId)1363 private void updateDeviceAdminServiceOnPackageChanged( 1364 @NonNull String updatedPackage, int userId) { 1365 for (EnforcingAdmin admin : getEnforcingAdminsOnUser(userId)) { 1366 // DPCs are handled separately in DPMS, no need to reestablish the connection here. 1367 if (admin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1368 continue; 1369 } 1370 if (updatedPackage.equals(admin.getPackageName())) { 1371 mDeviceAdminServiceController.startServiceForAdmin( 1372 updatedPackage, userId, /* actionForLog= */ "package-broadcast"); 1373 } 1374 } 1375 } 1376 1377 /** 1378 * Called after an admin policy has been added to start binding to the admin if a connection 1379 * was not already established. 1380 */ updateDeviceAdminServiceOnPolicyAddLocked(@onNull EnforcingAdmin enforcingAdmin)1381 private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) { 1382 int userId = enforcingAdmin.getUserId(); 1383 1384 if (mEnforcingAdmins.contains(userId) 1385 && mEnforcingAdmins.get(userId).contains(enforcingAdmin)) { 1386 return; 1387 } 1388 1389 if (!mEnforcingAdmins.contains(enforcingAdmin.getUserId())) { 1390 mEnforcingAdmins.put(enforcingAdmin.getUserId(), new HashSet<>()); 1391 } 1392 mEnforcingAdmins.get(enforcingAdmin.getUserId()).add(enforcingAdmin); 1393 1394 // A connection is established with DPCs as soon as they are provisioned, so no need to 1395 // connect when a policy is set. 1396 if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1397 return; 1398 } 1399 mDeviceAdminServiceController.startServiceForAdmin( 1400 enforcingAdmin.getPackageName(), 1401 userId, 1402 /* actionForLog= */ "policy-added"); 1403 } 1404 1405 /** 1406 * Called after an admin policy has been removed to stop binding to the admin if they no longer 1407 * have any policies set. 1408 */ updateDeviceAdminServiceOnPolicyRemoveLocked( @onNull EnforcingAdmin enforcingAdmin)1409 private void updateDeviceAdminServiceOnPolicyRemoveLocked( 1410 @NonNull EnforcingAdmin enforcingAdmin) { 1411 if (doesAdminHavePoliciesLocked(enforcingAdmin)) { 1412 return; 1413 } 1414 int userId = enforcingAdmin.getUserId(); 1415 if (mEnforcingAdmins.contains(userId)) { 1416 mEnforcingAdmins.get(userId).remove(enforcingAdmin); 1417 if (mEnforcingAdmins.get(userId).isEmpty()) { 1418 mEnforcingAdmins.remove(enforcingAdmin.getUserId()); 1419 } 1420 } 1421 1422 // TODO(b/263364434): centralise handling in one place. 1423 // DPCs rely on a constant connection being established as soon as they are provisioned, 1424 // so we shouldn't disconnect it even if they no longer have policies set. 1425 if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { 1426 return; 1427 } 1428 mDeviceAdminServiceController.stopServiceForAdmin( 1429 enforcingAdmin.getPackageName(), 1430 userId, 1431 /* actionForLog= */ "policy-removed"); 1432 } 1433 doesAdminHavePoliciesLocked(@onNull EnforcingAdmin enforcingAdmin)1434 private boolean doesAdminHavePoliciesLocked(@NonNull EnforcingAdmin enforcingAdmin) { 1435 for (PolicyKey policy : mGlobalPolicies.keySet()) { 1436 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1437 if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) { 1438 return true; 1439 } 1440 } 1441 for (int i = 0; i < mLocalPolicies.size(); i++) { 1442 for (PolicyKey policy : mLocalPolicies.get(mLocalPolicies.keyAt(i)).keySet()) { 1443 PolicyState<?> policyState = mLocalPolicies.get( 1444 mLocalPolicies.keyAt(i)).get(policy); 1445 if (policyState.getPoliciesSetByAdmins().containsKey(enforcingAdmin)) { 1446 return true; 1447 } 1448 } 1449 } 1450 return false; 1451 } 1452 1453 @NonNull getEnforcingAdminsOnUser(int userId)1454 private Set<EnforcingAdmin> getEnforcingAdminsOnUser(int userId) { 1455 synchronized (mLock) { 1456 return mEnforcingAdmins.contains(userId) 1457 ? mEnforcingAdmins.get(userId) : Collections.emptySet(); 1458 } 1459 } 1460 write()1461 private void write() { 1462 synchronized (mLock) { 1463 Log.d(TAG, "Writing device policies to file."); 1464 new DevicePoliciesReaderWriter().writeToFileLocked(); 1465 } 1466 } 1467 1468 // TODO(b/256852787): trigger resolving logic after loading policies as roles are recalculated 1469 // and could result in a different enforced policy load()1470 void load() { 1471 Log.d(TAG, "Reading device policies from file."); 1472 synchronized (mLock) { 1473 clear(); 1474 new DevicePoliciesReaderWriter().readFromFileLocked(); 1475 } 1476 } 1477 reapplyAllPoliciesLocked()1478 <V> void reapplyAllPoliciesLocked() { 1479 for (PolicyKey policy : mGlobalPolicies.keySet()) { 1480 PolicyState<?> policyState = mGlobalPolicies.get(policy); 1481 // Policy definition and value will always be of the same type 1482 PolicyDefinition<V> policyDefinition = 1483 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 1484 PolicyValue<V> policyValue = (PolicyValue<V>) policyState.getCurrentResolvedPolicy(); 1485 enforcePolicy(policyDefinition, policyValue, UserHandle.USER_ALL); 1486 } 1487 for (int i = 0; i < mLocalPolicies.size(); i++) { 1488 int userId = mLocalPolicies.keyAt(i); 1489 for (PolicyKey policy : mLocalPolicies.get(userId).keySet()) { 1490 PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy); 1491 // Policy definition and value will always be of the same type 1492 PolicyDefinition<V> policyDefinition = 1493 (PolicyDefinition<V>) policyState.getPolicyDefinition(); 1494 PolicyValue<V> policyValue = 1495 (PolicyValue<V>) policyState.getCurrentResolvedPolicy(); 1496 enforcePolicy(policyDefinition, policyValue, userId); 1497 1498 } 1499 } 1500 } 1501 1502 /** 1503 * Clear all policies set in the policy engine. 1504 * 1505 * <p>Note that this doesn't clear any enforcements, it only clears the data structures. 1506 */ clearAllPolicies()1507 void clearAllPolicies() { 1508 clear(); 1509 write(); 1510 } clear()1511 private void clear() { 1512 synchronized (mLock) { 1513 mGlobalPolicies.clear(); 1514 mLocalPolicies.clear(); 1515 mEnforcingAdmins.clear(); 1516 } 1517 } 1518 checkFor2gFailure(@onNull PolicyDefinition<V> policyDefinition, @NonNull EnforcingAdmin enforcingAdmin)1519 private <V> boolean checkFor2gFailure(@NonNull PolicyDefinition<V> policyDefinition, 1520 @NonNull EnforcingAdmin enforcingAdmin) { 1521 if (!policyDefinition.getPolicyKey().getIdentifier().equals( 1522 CELLULAR_2G_USER_RESTRICTION_ID)) { 1523 return false; 1524 } 1525 1526 boolean isCapabilitySupported; 1527 try { 1528 isCapabilitySupported = mContext.getSystemService( 1529 TelephonyManager.class).isRadioInterfaceCapabilitySupported( 1530 TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK); 1531 } catch (IllegalStateException e) { 1532 // isRadioInterfaceCapabilitySupported can throw if there is no Telephony 1533 // service initialized. 1534 isCapabilitySupported = false; 1535 } 1536 1537 if (!isCapabilitySupported) { 1538 sendPolicyResultToAdmin( 1539 enforcingAdmin, 1540 policyDefinition, 1541 RESULT_FAILURE_HARDWARE_LIMITATION, 1542 UserHandle.USER_ALL); 1543 return true; 1544 } 1545 1546 return false; 1547 } 1548 1549 private class DevicePoliciesReaderWriter { 1550 private static final String DEVICE_POLICIES_XML = "device_policy_state.xml"; 1551 private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry"; 1552 private static final String TAG_GLOBAL_POLICY_ENTRY = "global-policy-entry"; 1553 private static final String TAG_POLICY_STATE_ENTRY = "policy-state-entry"; 1554 private static final String TAG_POLICY_KEY_ENTRY = "policy-key-entry"; 1555 private static final String TAG_ENFORCING_ADMINS_ENTRY = "enforcing-admins-entry"; 1556 private static final String ATTR_USER_ID = "user-id"; 1557 1558 private final File mFile; 1559 DevicePoliciesReaderWriter()1560 private DevicePoliciesReaderWriter() { 1561 mFile = new File(Environment.getDataSystemDirectory(), DEVICE_POLICIES_XML); 1562 } 1563 writeToFileLocked()1564 void writeToFileLocked() { 1565 Log.d(TAG, "Writing to " + mFile); 1566 1567 AtomicFile f = new AtomicFile(mFile); 1568 FileOutputStream outputStream = null; 1569 try { 1570 outputStream = f.startWrite(); 1571 TypedXmlSerializer out = Xml.resolveSerializer(outputStream); 1572 1573 out.startDocument(null, true); 1574 1575 // Actual content 1576 writeInner(out); 1577 1578 out.endDocument(); 1579 out.flush(); 1580 1581 // Commit the content. 1582 f.finishWrite(outputStream); 1583 outputStream = null; 1584 1585 } catch (IOException e) { 1586 Log.e(TAG, "Exception when writing", e); 1587 if (outputStream != null) { 1588 f.failWrite(outputStream); 1589 } 1590 } 1591 } 1592 1593 // TODO(b/256846294): Add versioning to read/write writeInner(TypedXmlSerializer serializer)1594 void writeInner(TypedXmlSerializer serializer) throws IOException { 1595 writeLocalPoliciesInner(serializer); 1596 writeGlobalPoliciesInner(serializer); 1597 writeEnforcingAdminsInner(serializer); 1598 } 1599 writeLocalPoliciesInner(TypedXmlSerializer serializer)1600 private void writeLocalPoliciesInner(TypedXmlSerializer serializer) throws IOException { 1601 if (mLocalPolicies != null) { 1602 for (int i = 0; i < mLocalPolicies.size(); i++) { 1603 int userId = mLocalPolicies.keyAt(i); 1604 for (Map.Entry<PolicyKey, PolicyState<?>> policy : mLocalPolicies.get( 1605 userId).entrySet()) { 1606 serializer.startTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY); 1607 1608 serializer.attributeInt(/* namespace= */ null, ATTR_USER_ID, userId); 1609 1610 serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 1611 policy.getKey().saveToXml(serializer); 1612 serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 1613 1614 serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 1615 policy.getValue().saveToXml(serializer); 1616 serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 1617 1618 serializer.endTag(/* namespace= */ null, TAG_LOCAL_POLICY_ENTRY); 1619 } 1620 } 1621 } 1622 } 1623 writeGlobalPoliciesInner(TypedXmlSerializer serializer)1624 private void writeGlobalPoliciesInner(TypedXmlSerializer serializer) throws IOException { 1625 if (mGlobalPolicies != null) { 1626 for (Map.Entry<PolicyKey, PolicyState<?>> policy : mGlobalPolicies.entrySet()) { 1627 serializer.startTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY); 1628 1629 serializer.startTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 1630 policy.getKey().saveToXml(serializer); 1631 serializer.endTag(/* namespace= */ null, TAG_POLICY_KEY_ENTRY); 1632 1633 serializer.startTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 1634 policy.getValue().saveToXml(serializer); 1635 serializer.endTag(/* namespace= */ null, TAG_POLICY_STATE_ENTRY); 1636 1637 serializer.endTag(/* namespace= */ null, TAG_GLOBAL_POLICY_ENTRY); 1638 } 1639 } 1640 } 1641 writeEnforcingAdminsInner(TypedXmlSerializer serializer)1642 private void writeEnforcingAdminsInner(TypedXmlSerializer serializer) throws IOException { 1643 if (mEnforcingAdmins != null) { 1644 for (int i = 0; i < mEnforcingAdmins.size(); i++) { 1645 int userId = mEnforcingAdmins.keyAt(i); 1646 for (EnforcingAdmin admin : mEnforcingAdmins.get(userId)) { 1647 serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY); 1648 admin.saveToXml(serializer); 1649 serializer.endTag(/* namespace= */ null, TAG_ENFORCING_ADMINS_ENTRY); 1650 } 1651 } 1652 } 1653 } 1654 readFromFileLocked()1655 void readFromFileLocked() { 1656 if (!mFile.exists()) { 1657 Log.d(TAG, "" + mFile + " doesn't exist"); 1658 return; 1659 } 1660 1661 Log.d(TAG, "Reading from " + mFile); 1662 AtomicFile f = new AtomicFile(mFile); 1663 InputStream input = null; 1664 try { 1665 input = f.openRead(); 1666 TypedXmlPullParser parser = Xml.resolvePullParser(input); 1667 1668 readInner(parser); 1669 1670 } catch (XmlPullParserException | IOException | ClassNotFoundException e) { 1671 Slogf.wtf(TAG, "Error parsing resources file", e); 1672 } finally { 1673 IoUtils.closeQuietly(input); 1674 } 1675 } 1676 readInner(TypedXmlPullParser parser)1677 private void readInner(TypedXmlPullParser parser) 1678 throws IOException, XmlPullParserException, ClassNotFoundException { 1679 int outerDepth = parser.getDepth(); 1680 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1681 String tag = parser.getName(); 1682 switch (tag) { 1683 case TAG_LOCAL_POLICY_ENTRY: 1684 readLocalPoliciesInner(parser); 1685 break; 1686 case TAG_GLOBAL_POLICY_ENTRY: 1687 readGlobalPoliciesInner(parser); 1688 break; 1689 case TAG_ENFORCING_ADMINS_ENTRY: 1690 readEnforcingAdminsInner(parser); 1691 break; 1692 default: 1693 Slogf.wtf(TAG, "Unknown tag " + tag); 1694 } 1695 } 1696 } 1697 readLocalPoliciesInner(TypedXmlPullParser parser)1698 private void readLocalPoliciesInner(TypedXmlPullParser parser) 1699 throws XmlPullParserException, IOException { 1700 int userId = parser.getAttributeInt(/* namespace= */ null, ATTR_USER_ID); 1701 PolicyKey policyKey = null; 1702 PolicyState<?> policyState = null; 1703 int outerDepth = parser.getDepth(); 1704 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1705 String tag = parser.getName(); 1706 switch (tag) { 1707 case TAG_POLICY_KEY_ENTRY: 1708 policyKey = PolicyDefinition.readPolicyKeyFromXml(parser); 1709 break; 1710 case TAG_POLICY_STATE_ENTRY: 1711 policyState = PolicyState.readFromXml(parser); 1712 break; 1713 default: 1714 Slogf.wtf(TAG, "Unknown tag for local policy entry" + tag); 1715 } 1716 } 1717 1718 if (policyKey != null && policyState != null) { 1719 if (!mLocalPolicies.contains(userId)) { 1720 mLocalPolicies.put(userId, new HashMap<>()); 1721 } 1722 mLocalPolicies.get(userId).put(policyKey, policyState); 1723 } else { 1724 Slogf.wtf(TAG, "Error parsing local policy, policyKey is " 1725 + (policyKey == null ? "null" : policyKey) + ", and policyState is " 1726 + (policyState == null ? "null" : policyState) + "."); 1727 } 1728 } 1729 readGlobalPoliciesInner(TypedXmlPullParser parser)1730 private void readGlobalPoliciesInner(TypedXmlPullParser parser) 1731 throws IOException, XmlPullParserException { 1732 PolicyKey policyKey = null; 1733 PolicyState<?> policyState = null; 1734 int outerDepth = parser.getDepth(); 1735 while (XmlUtils.nextElementWithin(parser, outerDepth)) { 1736 String tag = parser.getName(); 1737 switch (tag) { 1738 case TAG_POLICY_KEY_ENTRY: 1739 policyKey = PolicyDefinition.readPolicyKeyFromXml(parser); 1740 break; 1741 case TAG_POLICY_STATE_ENTRY: 1742 policyState = PolicyState.readFromXml(parser); 1743 break; 1744 default: 1745 Slogf.wtf(TAG, "Unknown tag for local policy entry" + tag); 1746 } 1747 } 1748 1749 if (policyKey != null && policyState != null) { 1750 mGlobalPolicies.put(policyKey, policyState); 1751 } else { 1752 Slogf.wtf(TAG, "Error parsing global policy, policyKey is " 1753 + (policyKey == null ? "null" : policyKey) + ", and policyState is " 1754 + (policyState == null ? "null" : policyState) + "."); 1755 } 1756 } 1757 readEnforcingAdminsInner(TypedXmlPullParser parser)1758 private void readEnforcingAdminsInner(TypedXmlPullParser parser) 1759 throws XmlPullParserException { 1760 EnforcingAdmin admin = EnforcingAdmin.readFromXml(parser); 1761 if (admin == null) { 1762 Slogf.wtf(TAG, "Error parsing enforcingAdmins, EnforcingAdmin is null."); 1763 return; 1764 } 1765 if (!mEnforcingAdmins.contains(admin.getUserId())) { 1766 mEnforcingAdmins.put(admin.getUserId(), new HashSet<>()); 1767 } 1768 mEnforcingAdmins.get(admin.getUserId()).add(admin); 1769 } 1770 } 1771 } 1772