1 /* 2 * Copyright (C) 2021 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.tv.settings.library.settingslib; 18 19 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; 20 import static android.app.admin.DevicePolicyManager.PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.UserIdInt; 25 import android.app.AppGlobals; 26 import android.app.admin.DevicePolicyManager; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.pm.IPackageManager; 30 import android.content.pm.PackageManager; 31 import android.content.pm.UserInfo; 32 import android.content.res.TypedArray; 33 import android.graphics.drawable.Drawable; 34 import android.os.RemoteException; 35 import android.os.UserHandle; 36 import android.os.UserManager; 37 38 import androidx.annotation.VisibleForTesting; 39 40 import com.android.internal.widget.LockPatternUtils; 41 42 import java.util.List; 43 44 /** 45 * Utility class to host methods usable in adding a restricted padlock icon and showing admin 46 * support message dialog. 47 */ 48 public class RestrictedLockUtilsInternal extends RestrictedLockUtils { 49 50 private static final String LOG_TAG = "RestrictedLockUtils"; 51 52 /** 53 * @return drawables for displaying with settings that are locked by a device admin. 54 */ getRestrictedPadlock(Context context)55 public static Drawable getRestrictedPadlock(Context context) { 56 Drawable restrictedPadlock = context.getDrawable(android.R.drawable.ic_info); 57 final int iconSize = context.getResources().getDimensionPixelSize( 58 android.R.dimen.config_restrictedIconSize); 59 60 TypedArray ta = context.obtainStyledAttributes(new int[]{android.R.attr.colorAccent}); 61 int colorAccent = ta.getColor(0, 0); 62 ta.recycle(); 63 restrictedPadlock.setTint(colorAccent); 64 65 restrictedPadlock.setBounds(0, 0, iconSize, iconSize); 66 return restrictedPadlock; 67 } 68 69 /** 70 * Checks if a restriction is enforced on a user and returns the enforced admin and 71 * admin userId. 72 * 73 * @param userRestriction Restriction to check 74 * @param userId User which we need to check if restriction is enforced on. 75 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 76 * or {@code null} If the restriction is not set. If the restriction is set by both device owner 77 * and profile owner, then the admin component will be set to {@code null} and userId to 78 * {@link UserHandle#USER_NULL}. 79 */ checkIfRestrictionEnforced(Context context, String userRestriction, int userId)80 public static EnforcedAdmin checkIfRestrictionEnforced(Context context, 81 String userRestriction, int userId) { 82 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 83 if (dpm == null) { 84 return null; 85 } 86 87 final UserManager um = UserManager.get(context); 88 final List<UserManager.EnforcingUser> enforcingUsers = 89 um.getUserRestrictionSources(userRestriction, UserHandle.of(userId)); 90 91 if (enforcingUsers.isEmpty()) { 92 // Restriction is not enforced. 93 return null; 94 } else if (enforcingUsers.size() > 1) { 95 return EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction); 96 } 97 98 final int restrictionSource = enforcingUsers.get(0).getUserRestrictionSource(); 99 final int adminUserId = enforcingUsers.get(0).getUserHandle().getIdentifier(); 100 if (restrictionSource == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) { 101 // Check if it is a profile owner of the user under consideration. 102 if (adminUserId == userId) { 103 return getProfileOwner(context, userRestriction, adminUserId); 104 } else { 105 // Check if it is a profile owner of a managed profile of the current user. 106 // Otherwise it is in a separate user and we return a default EnforcedAdmin. 107 final UserInfo parentUser = um.getProfileParent(adminUserId); 108 return (parentUser != null && parentUser.id == userId) 109 ? getProfileOwner(context, userRestriction, adminUserId) 110 : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction); 111 } 112 } else if (restrictionSource == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) { 113 // When the restriction is enforced by device owner, return the device owner admin only 114 // if the admin is for the {@param userId} otherwise return a default EnforcedAdmin. 115 return adminUserId == userId 116 ? getDeviceOwner(context, userRestriction) 117 : EnforcedAdmin.createDefaultEnforcedAdminWithRestriction(userRestriction); 118 } 119 120 // If the restriction is enforced by system then return null. 121 return null; 122 } 123 hasBaseUserRestriction(Context context, String userRestriction, int userId)124 public static boolean hasBaseUserRestriction(Context context, 125 String userRestriction, int userId) { 126 final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 127 return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId)); 128 } 129 130 /** 131 * Checks whether keyguard features are disabled by policy. 132 * 133 * @param context {@link Context} for the calling user. 134 * @param keyguardFeatures Any one of keyguard features that can be 135 * disabled by {@link DevicePolicyManager#setKeyguardDisabledFeatures}. 136 * @param userId User to check enforced admin status for. 137 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 138 * or {@code null} If the notification features are not disabled. If the restriction is set by 139 * multiple admins, then the admin component will be set to {@code null} and userId to 140 * {@link UserHandle#USER_NULL}. 141 */ checkIfKeyguardFeaturesDisabled(Context context, int keyguardFeatures, final @UserIdInt int userId)142 public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context, 143 int keyguardFeatures, final @UserIdInt int userId) { 144 final LockSettingCheck check = (dpm, admin, checkUser) -> { 145 int effectiveFeatures = dpm.getKeyguardDisabledFeatures(admin, checkUser); 146 if (checkUser != userId) { 147 effectiveFeatures &= PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER; 148 } 149 return (effectiveFeatures & keyguardFeatures) != KEYGUARD_DISABLE_FEATURES_NONE; 150 }; 151 if (UserManager.get(context).getUserInfo(userId).isManagedProfile()) { 152 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 153 return findEnforcedAdmin(dpm.getActiveAdminsAsUser(userId), dpm, userId, check); 154 } 155 return checkForLockSetting(context, userId, check); 156 } 157 158 /** 159 * @return the UserHandle for a userId. Return null for USER_NULL 160 */ getUserHandleOf(@serIdInt int userId)161 private static UserHandle getUserHandleOf(@UserIdInt int userId) { 162 if (userId == UserHandle.USER_NULL) { 163 return null; 164 } else { 165 return UserHandle.of(userId); 166 } 167 } 168 169 /** 170 * Filter a set of device admins based on a predicate {@code check}. This is equivalent to 171 * {@code admins.stream().filter(check).map(x → new EnforcedAdmin(admin, userId)} except it's 172 * returning a zero/one/many-type thing. 173 * 174 * @param admins set of candidate device admins identified by {@link ComponentName}. 175 * @param userId user to create the resultant {@link EnforcedAdmin} as. 176 * @param check filter predicate. 177 * @return {@code null} if none of the {@param admins} match. 178 * An {@link EnforcedAdmin} if exactly one of the admins matches. 179 * Otherwise, {@link EnforcedAdmin#MULTIPLE_ENFORCED_ADMIN} for multiple matches. 180 */ 181 @Nullable findEnforcedAdmin(@ullable List<ComponentName> admins, @NonNull DevicePolicyManager dpm, @UserIdInt int userId, @NonNull LockSettingCheck check)182 private static EnforcedAdmin findEnforcedAdmin(@Nullable List<ComponentName> admins, 183 @NonNull DevicePolicyManager dpm, @UserIdInt int userId, 184 @NonNull LockSettingCheck check) { 185 if (admins == null) { 186 return null; 187 } 188 189 final UserHandle user = getUserHandleOf(userId); 190 EnforcedAdmin enforcedAdmin = null; 191 for (ComponentName admin : admins) { 192 if (check.isEnforcing(dpm, admin, userId)) { 193 if (enforcedAdmin == null) { 194 enforcedAdmin = new EnforcedAdmin(admin, user); 195 } else { 196 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 197 } 198 } 199 } 200 return enforcedAdmin; 201 } 202 checkIfUninstallBlocked(Context context, String packageName, int userId)203 public static EnforcedAdmin checkIfUninstallBlocked(Context context, 204 String packageName, int userId) { 205 EnforcedAdmin allAppsControlDisallowedAdmin = checkIfRestrictionEnforced(context, 206 UserManager.DISALLOW_APPS_CONTROL, userId); 207 if (allAppsControlDisallowedAdmin != null) { 208 return allAppsControlDisallowedAdmin; 209 } 210 EnforcedAdmin allAppsUninstallDisallowedAdmin = checkIfRestrictionEnforced(context, 211 UserManager.DISALLOW_UNINSTALL_APPS, userId); 212 if (allAppsUninstallDisallowedAdmin != null) { 213 return allAppsUninstallDisallowedAdmin; 214 } 215 IPackageManager ipm = AppGlobals.getPackageManager(); 216 try { 217 if (ipm.getBlockUninstallForUser(packageName, userId)) { 218 return getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 219 } 220 } catch (RemoteException e) { 221 // Nothing to do 222 } 223 return null; 224 } 225 226 /** 227 * Check if an application is suspended. 228 * 229 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 230 * or {@code null} if the application is not suspended. 231 */ checkIfApplicationIsSuspended(Context context, String packageName, int userId)232 public static EnforcedAdmin checkIfApplicationIsSuspended(Context context, String packageName, 233 int userId) { 234 IPackageManager ipm = AppGlobals.getPackageManager(); 235 try { 236 if (ipm.isPackageSuspendedForUser(packageName, userId)) { 237 return getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 238 } 239 } catch (RemoteException | IllegalArgumentException e) { 240 // Nothing to do 241 } 242 return null; 243 } 244 checkIfInputMethodDisallowed(Context context, String packageName, int userId)245 public static EnforcedAdmin checkIfInputMethodDisallowed(Context context, 246 String packageName, int userId) { 247 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 248 if (dpm == null) { 249 return null; 250 } 251 EnforcedAdmin admin = getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 252 boolean permitted = true; 253 if (admin != null) { 254 permitted = dpm.isInputMethodPermittedByAdmin(admin.component, 255 packageName, userId); 256 } 257 258 boolean permittedByParentAdmin = true; 259 EnforcedAdmin profileAdmin = null; 260 int managedProfileId = getManagedProfileId(context, userId); 261 if (managedProfileId != UserHandle.USER_NULL) { 262 profileAdmin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); 263 // If the device is an organization-owned device with a managed profile, the 264 // managedProfileId will be used instead of the affected userId. This is because 265 // isInputMethodPermittedByAdmin is called on the parent DPM instance, which will 266 // return results affecting the personal profile. 267 if (profileAdmin != null && dpm.isOrganizationOwnedDeviceWithManagedProfile()) { 268 DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, 269 UserManager.get(context).getUserInfo(managedProfileId)); 270 permittedByParentAdmin = parentDpm.isInputMethodPermittedByAdmin( 271 profileAdmin.component, packageName, managedProfileId); 272 } 273 } 274 if (!permitted && !permittedByParentAdmin) { 275 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 276 } else if (!permitted) { 277 return admin; 278 } else if (!permittedByParentAdmin) { 279 return profileAdmin; 280 } 281 return null; 282 } 283 284 /** 285 * @param userId user id of a managed profile. 286 * @return is remote contacts search disallowed. 287 */ checkIfRemoteContactSearchDisallowed(Context context, int userId)288 public static EnforcedAdmin checkIfRemoteContactSearchDisallowed(Context context, int userId) { 289 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 290 if (dpm == null) { 291 return null; 292 } 293 EnforcedAdmin admin = getProfileOwner(context, userId); 294 if (admin == null) { 295 return null; 296 } 297 UserHandle userHandle = UserHandle.of(userId); 298 if (dpm.getCrossProfileContactsSearchDisabled(userHandle) 299 && dpm.getCrossProfileCallerIdDisabled(userHandle)) { 300 return admin; 301 } 302 return null; 303 } 304 checkIfAccessibilityServiceDisallowed(Context context, String packageName, int userId)305 public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context, 306 String packageName, int userId) { 307 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 308 if (dpm == null) { 309 return null; 310 } 311 EnforcedAdmin admin = getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 312 boolean permitted = true; 313 if (admin != null) { 314 permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component, 315 packageName, userId); 316 } 317 int managedProfileId = getManagedProfileId(context, userId); 318 EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, 319 getUserHandleOf(managedProfileId)); 320 boolean permittedByProfileAdmin = true; 321 if (profileAdmin != null) { 322 permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin( 323 profileAdmin.component, packageName, managedProfileId); 324 } 325 if (!permitted && !permittedByProfileAdmin) { 326 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 327 } else if (!permitted) { 328 return admin; 329 } else if (!permittedByProfileAdmin) { 330 return profileAdmin; 331 } 332 return null; 333 } 334 getManagedProfileId(Context context, int userId)335 private static int getManagedProfileId(Context context, int userId) { 336 UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 337 List<UserInfo> userProfiles = um.getProfiles(userId); 338 for (UserInfo uInfo : userProfiles) { 339 if (uInfo.id == userId) { 340 continue; 341 } 342 if (uInfo.isManagedProfile()) { 343 return uInfo.id; 344 } 345 } 346 return UserHandle.USER_NULL; 347 } 348 349 /** 350 * Check if account management for a specific type of account is disabled by admin. 351 * Only a profile or device owner can disable account management. So, we check if account 352 * management is disabled and return profile or device owner on the calling user. 353 * 354 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 355 * or {@code null} if the account management is not disabled. 356 */ checkIfAccountManagementDisabled(Context context, String accountType, int userId)357 public static EnforcedAdmin checkIfAccountManagementDisabled(Context context, 358 String accountType, int userId) { 359 if (accountType == null) { 360 return null; 361 } 362 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 363 PackageManager pm = context.getPackageManager(); 364 if (!pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) || dpm == null) { 365 return null; 366 } 367 boolean isAccountTypeDisabled = false; 368 String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId); 369 for (String type : disabledTypes) { 370 if (accountType.equals(type)) { 371 isAccountTypeDisabled = true; 372 break; 373 } 374 } 375 if (!isAccountTypeDisabled) { 376 return null; 377 } 378 return getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 379 } 380 381 /** 382 * Check if USB data signaling (except from charging functions) is disabled by the admin. 383 * Only a device owner or a profile owner on an organization-owned managed profile can disable 384 * USB data signaling. 385 * 386 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 387 * or {@code null} if USB data signaling is not disabled. 388 */ checkIfUsbDataSignalingIsDisabled(Context context, int userId)389 public static EnforcedAdmin checkIfUsbDataSignalingIsDisabled(Context context, int userId) { 390 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 391 if (dpm == null || dpm.isUsbDataSignalingEnabled()) { 392 return null; 393 } else { 394 EnforcedAdmin admin = getProfileOrDeviceOwner(context, getUserHandleOf(userId)); 395 int managedProfileId = getManagedProfileId(context, userId); 396 if (admin == null && managedProfileId != UserHandle.USER_NULL) { 397 admin = getProfileOrDeviceOwner(context, getUserHandleOf(managedProfileId)); 398 } 399 return admin; 400 } 401 } 402 403 /** 404 * Check if {@param packageName} is restricted by the profile or device owner from using 405 * metered data. 406 * 407 * @return EnforcedAdmin object containing the enforced admin component and admin user details, 408 * or {@code null} if the {@param packageName} is not restricted. 409 */ checkIfMeteredDataRestricted(Context context, String packageName, int userId)410 public static EnforcedAdmin checkIfMeteredDataRestricted(Context context, 411 String packageName, int userId) { 412 final EnforcedAdmin enforcedAdmin = getProfileOrDeviceOwner(context, 413 getUserHandleOf(userId)); 414 if (enforcedAdmin == null) { 415 return null; 416 } 417 418 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 419 return dpm.isMeteredDataDisabledPackageForUser(enforcedAdmin.component, packageName, userId) 420 ? enforcedAdmin : null; 421 } 422 423 /** 424 * Checks if an admin has enforced minimum password quality or complexity requirements on the 425 * given user. 426 * 427 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 428 * or {@code null} if no quality requirements are set. If the requirements are set by 429 * multiple device admins, then the admin component will be set to {@code null} and userId to 430 * {@link UserHandle#USER_NULL}. 431 */ checkIfPasswordQualityIsSet(Context context, int userId)432 public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) { 433 final LockSettingCheck check = 434 (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int checkUser) -> 435 dpm.getPasswordQuality(admin, checkUser) 436 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 437 438 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 439 if (dpm == null) { 440 return null; 441 } 442 443 LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 444 final int aggregatedComplexity = dpm.getAggregatedPasswordComplexityForUser(userId); 445 if (aggregatedComplexity > DevicePolicyManager.PASSWORD_COMPLEXITY_NONE) { 446 // First, check if there's a Device Owner. If so, then only it can apply password 447 // complexity requiremnts (there can be no secondary profiles). 448 final UserHandle deviceOwnerUser = dpm.getDeviceOwnerUser(); 449 if (deviceOwnerUser != null) { 450 return new EnforcedAdmin(dpm.getDeviceOwnerComponentOnAnyUser(), deviceOwnerUser); 451 } 452 453 // The complexity could be enforced by a Profile Owner - either in the current user 454 // or the current user is the parent user that is affected by the profile owner. 455 for (UserInfo userInfo : UserManager.get(context).getProfiles(userId)) { 456 final ComponentName profileOwnerComponent = dpm.getProfileOwnerAsUser(userInfo.id); 457 if (profileOwnerComponent != null) { 458 return new EnforcedAdmin(profileOwnerComponent, getUserHandleOf(userInfo.id)); 459 } 460 } 461 462 // Should not get here: A Device Owner or Profile Owner should be found. 463 throw new IllegalStateException( 464 String.format("Could not find admin enforcing complexity %d for user %d", 465 aggregatedComplexity, userId)); 466 } 467 468 if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) { 469 // userId is managed profile and has a separate challenge, only consider 470 // the admins in that user. 471 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId); 472 if (admins == null) { 473 return null; 474 } 475 EnforcedAdmin enforcedAdmin = null; 476 final UserHandle user = getUserHandleOf(userId); 477 for (ComponentName admin : admins) { 478 if (check.isEnforcing(dpm, admin, userId)) { 479 if (enforcedAdmin == null) { 480 enforcedAdmin = new EnforcedAdmin(admin, user); 481 } else { 482 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 483 } 484 } 485 } 486 return enforcedAdmin; 487 } else { 488 return checkForLockSetting(context, userId, check); 489 } 490 } 491 492 /** 493 * Checks if any admin has set maximum time to lock. 494 * 495 * @return EnforcedAdmin Object containing the enforced admin component and admin user details, 496 * or {@code null} if no admin has set this restriction. If multiple admins has set this, then 497 * the admin component will be set to {@code null} and userId to {@link UserHandle#USER_NULL} 498 */ checkIfMaximumTimeToLockIsSet(Context context)499 public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) { 500 return checkForLockSetting(context, UserHandle.myUserId(), 501 (DevicePolicyManager dpm, ComponentName admin, @UserIdInt int userId) -> 502 dpm.getMaximumTimeToLock(admin, userId) > 0); 503 } 504 505 private interface LockSettingCheck { isEnforcing(DevicePolicyManager dpm, ComponentName admin, @UserIdInt int userId)506 boolean isEnforcing(DevicePolicyManager dpm, ComponentName admin, @UserIdInt int userId); 507 } 508 509 /** 510 * Checks whether any of the user's profiles enforce the lock setting. A managed profile is only 511 * included if it does not have a separate challenge. 512 * 513 * The user identified by {@param userId} is always included. 514 */ checkForLockSetting( Context context, @UserIdInt int userId, LockSettingCheck check)515 private static EnforcedAdmin checkForLockSetting( 516 Context context, @UserIdInt int userId, LockSettingCheck check) { 517 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 518 if (dpm == null) { 519 return null; 520 } 521 final LockPatternUtils lockPatternUtils = new LockPatternUtils(context); 522 EnforcedAdmin enforcedAdmin = null; 523 // Return all admins for this user and the profiles that are visible from this 524 // user that do not use a separate work challenge. 525 for (UserInfo userInfo : UserManager.get(context).getProfiles(userId)) { 526 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id); 527 if (admins == null) { 528 continue; 529 } 530 final UserHandle user = getUserHandleOf(userInfo.id); 531 final boolean isSeparateProfileChallengeEnabled = 532 sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userInfo.id); 533 for (ComponentName admin : admins) { 534 if (!isSeparateProfileChallengeEnabled) { 535 if (check.isEnforcing(dpm, admin, userInfo.id)) { 536 if (enforcedAdmin == null) { 537 enforcedAdmin = new EnforcedAdmin(admin, user); 538 } else { 539 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 540 } 541 // This same admins could have set policies both on the managed profile 542 // and on the parent. So, if the admin has set the policy on the 543 // managed profile here, we don't need to further check if that admin 544 // has set policy on the parent admin. 545 continue; 546 } 547 } 548 if (userInfo.isManagedProfile()) { 549 // If userInfo.id is a managed profile, we also need to look at 550 // the policies set on the parent. 551 DevicePolicyManager parentDpm = sProxy.getParentProfileInstance(dpm, userInfo); 552 if (check.isEnforcing(parentDpm, admin, userInfo.id)) { 553 if (enforcedAdmin == null) { 554 enforcedAdmin = new EnforcedAdmin(admin, user); 555 } else { 556 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; 557 } 558 } 559 } 560 } 561 } 562 return enforcedAdmin; 563 } 564 getDeviceOwner(Context context)565 public static EnforcedAdmin getDeviceOwner(Context context) { 566 return getDeviceOwner(context, null); 567 } 568 getDeviceOwner(Context context, String enforcedRestriction)569 private static EnforcedAdmin getDeviceOwner(Context context, String enforcedRestriction) { 570 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 571 if (dpm == null) { 572 return null; 573 } 574 ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); 575 if (adminComponent != null) { 576 return new EnforcedAdmin( 577 adminComponent, enforcedRestriction, dpm.getDeviceOwnerUser()); 578 } 579 return null; 580 } 581 getProfileOwner(Context context, int userId)582 private static EnforcedAdmin getProfileOwner(Context context, int userId) { 583 return getProfileOwner(context, null, userId); 584 } 585 getProfileOwner( Context context, String enforcedRestriction, int userId)586 private static EnforcedAdmin getProfileOwner( 587 Context context, String enforcedRestriction, int userId) { 588 if (userId == UserHandle.USER_NULL) { 589 return null; 590 } 591 final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 592 if (dpm == null) { 593 return null; 594 } 595 ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId); 596 if (adminComponent != null) { 597 return new EnforcedAdmin(adminComponent, enforcedRestriction, getUserHandleOf(userId)); 598 } 599 return null; 600 } 601 isAdminInCurrentUserOrProfile(Context context, ComponentName admin)602 public static boolean isAdminInCurrentUserOrProfile(Context context, ComponentName admin) { 603 DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 604 UserManager um = UserManager.get(context); 605 for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) { 606 if (dpm.isAdminActiveAsUser(admin, userInfo.id)) { 607 return true; 608 } 609 } 610 return false; 611 } 612 613 614 /** 615 * Static {@link LockPatternUtils} and {@link DevicePolicyManager} wrapper for testing purposes. 616 * {@link LockPatternUtils} is an internal API not supported by robolectric. 617 * {@link DevicePolicyManager} has a {@code getProfileParent} not yet suppored by robolectric. 618 */ 619 @VisibleForTesting 620 static Proxy sProxy = new Proxy(); 621 622 @VisibleForTesting 623 static class Proxy { isSeparateProfileChallengeEnabled(LockPatternUtils utils, int userHandle)624 public boolean isSeparateProfileChallengeEnabled(LockPatternUtils utils, int userHandle) { 625 return utils.isSeparateProfileChallengeEnabled(userHandle); 626 } 627 getParentProfileInstance(DevicePolicyManager dpm, UserInfo ui)628 public DevicePolicyManager getParentProfileInstance(DevicePolicyManager dpm, UserInfo ui) { 629 return dpm.getParentProfileInstance(ui); 630 } 631 } 632 } 633