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