1 package org.robolectric.shadows; 2 3 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; 4 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS; 5 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW; 6 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 7 import static android.os.Build.VERSION_CODES.M; 8 import static android.os.Build.VERSION_CODES.N; 9 import static android.os.Build.VERSION_CODES.N_MR1; 10 import static android.os.Build.VERSION_CODES.O; 11 import static android.os.Build.VERSION_CODES.P; 12 import static android.os.Build.VERSION_CODES.Q; 13 import static android.os.Build.VERSION_CODES.R; 14 import static android.os.Build.VERSION_CODES.S; 15 import static android.os.Build.VERSION_CODES.S_V2; 16 import static android.os.Build.VERSION_CODES.TIRAMISU; 17 import static org.robolectric.Shadows.shadowOf; 18 import static org.robolectric.shadow.api.Shadow.invokeConstructor; 19 import static org.robolectric.util.ReflectionHelpers.ClassParameter.from; 20 import static org.robolectric.util.reflector.Reflector.reflector; 21 22 import android.accounts.Account; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SuppressLint; 25 import android.annotation.SystemApi; 26 import android.app.ApplicationPackageManager; 27 import android.app.KeyguardManager; 28 import android.app.admin.DeviceAdminReceiver; 29 import android.app.admin.DevicePolicyManager; 30 import android.app.admin.DevicePolicyManager.NearbyStreamingPolicy; 31 import android.app.admin.DevicePolicyManager.PasswordComplexity; 32 import android.app.admin.DevicePolicyManager.UserProvisioningState; 33 import android.app.admin.DevicePolicyState; 34 import android.app.admin.IDevicePolicyManager; 35 import android.app.admin.SystemUpdateInfo; 36 import android.app.admin.SystemUpdatePolicy; 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.IntentFilter; 41 import android.content.ServiceConnection; 42 import android.content.pm.PackageInfo; 43 import android.content.pm.PackageManager; 44 import android.content.pm.PackageManager.NameNotFoundException; 45 import android.os.Build; 46 import android.os.Build.VERSION_CODES; 47 import android.os.Bundle; 48 import android.os.Handler; 49 import android.os.PersistableBundle; 50 import android.os.Process; 51 import android.os.UserHandle; 52 import android.text.TextUtils; 53 import com.android.internal.util.Preconditions; 54 import com.google.common.collect.ImmutableList; 55 import com.google.common.collect.ImmutableSet; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.Collection; 59 import java.util.Collections; 60 import java.util.HashMap; 61 import java.util.HashSet; 62 import java.util.List; 63 import java.util.Map; 64 import java.util.Objects; 65 import java.util.Set; 66 import javax.annotation.Nonnull; 67 import javax.annotation.Nullable; 68 import org.robolectric.RuntimeEnvironment; 69 import org.robolectric.annotation.ClassName; 70 import org.robolectric.annotation.Implementation; 71 import org.robolectric.annotation.Implements; 72 import org.robolectric.annotation.RealObject; 73 import org.robolectric.annotation.Resetter; 74 import org.robolectric.shadow.api.Shadow; 75 import org.robolectric.util.reflector.ForType; 76 import org.robolectric.util.reflector.Static; 77 import org.robolectric.versioning.AndroidVersions.U; 78 79 /** Shadow for {@link DevicePolicyManager}. */ 80 @Implements(DevicePolicyManager.class) 81 @SuppressLint("NewApi") 82 public class ShadowDevicePolicyManager { 83 /** 84 * @see 85 * https://developer.android.com/reference/android/app/admin/DevicePolicyManager.html#setOrganizationColor(android.content.ComponentName, 86 * int) 87 */ 88 private final Map<PackageAndPermission, Boolean> appPermissionGrantedMap = new HashMap<>(); 89 90 private final Map<PackageAndPermission, Integer> appPermissionGrantStateMap = new HashMap<>(); 91 private final Map<ComponentName, byte[]> passwordResetTokens = new HashMap<>(); 92 private final List<ComponentName> deviceAdmins = new ArrayList<>(); 93 private final Map<Integer, String> profileOwnerNamesMap = new HashMap<>(); 94 private final Map<String, Bundle> applicationRestrictionsMap = new HashMap<>(); 95 private List<String> permittedAccessibilityServices = new ArrayList<>(); 96 private List<String> permittedInputMethods = new ArrayList<>(); 97 private Collection<String> packagesToFailForSetApplicationHidden = Collections.emptySet(); 98 private Context context; 99 private List<UserHandle> bindDeviceAdminTargetUsers = ImmutableList.of(); 100 private @RealObject DevicePolicyManager realObject; 101 102 private static final int DEFAULT_ORGANIZATION_COLOR = 0xFF008080; // teal 103 private static final Set<String> wasHiddenPackages = new HashSet<>(); 104 private static final Set<String> accountTypesWithManagementDisabled = new HashSet<>(); 105 private static final Set<String> systemAppsEnabled = new HashSet<>(); 106 private static final Set<String> uninstallBlockedPackages = new HashSet<>(); 107 private static final Set<String> suspendedPackages = new HashSet<>(); 108 private static final Set<String> affiliationIds = new HashSet<>(); 109 private static final Map<String, Set<String>> delegatedScopePackagesMap = new HashMap<>(); 110 private static final Map<ComponentName, Set<Integer>> adminPolicyGrantedMap = new HashMap<>(); 111 private static final Map<ComponentName, CharSequence> shortSupportMessageMap = new HashMap<>(); 112 private static final Map<ComponentName, CharSequence> longSupportMessageMap = new HashMap<>(); 113 private static final Set<ComponentName> componentsWithActivatedTokens = new HashSet<>(); 114 private static final List<String> lockTaskPackages = new ArrayList<>(); 115 private static final Map<UserHandle, Account> finalizedWorkProfileProvisioningMap = 116 new HashMap<>(); 117 private static final Map<Integer, Integer> userProvisioningStatesMap = new HashMap<>(); 118 private static ComponentName deviceOwner; 119 private static ComponentName profileOwner; 120 private static CharSequence organizationName; 121 private static int organizationColor; 122 private static boolean isAutoTimeEnabled; 123 private static boolean isAutoTimeRequired; 124 private static boolean isAutoTimeZoneEnabled; 125 private static String timeZone; 126 private static int keyguardDisabledFeatures; 127 private static String lastSetPassword; 128 private static int requiredPasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 129 private static int passwordMinimumLength; 130 private static int passwordMinimumLetters = 1; 131 private static int passwordMinimumLowerCase; 132 private static int passwordMinimumUpperCase; 133 private static int passwordMinimumNonLetter; 134 private static int passwordMinimumNumeric = 1; 135 private static int passwordMinimumSymbols = 1; 136 private static int passwordHistoryLength = 0; 137 private static long passwordExpiration = 0; 138 private static long passwordExpirationTimeout = 0; 139 private static int maximumFailedPasswordsForWipe = 0; 140 private static long maximumTimeToLock = 0; 141 private static boolean cameraDisabled; 142 private static boolean isActivePasswordSufficient; 143 private static boolean isUniqueDeviceAttestationSupported; 144 @PasswordComplexity private static int passwordComplexity; 145 private static int wipeCalled; 146 private static int storageEncryptionStatus; 147 private static int permissionPolicy; 148 private static boolean storageEncryptionRequested; 149 private static int lockTaskFeatures; 150 private static ApplicationPackageManager applicationPackageManager; 151 private static SystemUpdatePolicy policy; 152 private static boolean isDeviceProvisioned; 153 private static boolean isDeviceProvisioningConfigApplied; 154 private static volatile boolean organizationOwnedDeviceWithManagedProfile = false; 155 private static int nearbyNotificationStreamingPolicy = 156 DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY; 157 private static int nearbyAppStreamingPolicy = 158 DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY; 159 private static boolean isUsbDataSignalingEnabled = true; 160 @Nullable private static String devicePolicyManagementRoleHolderPackage; 161 private static List<UserHandle> policyManagedProfiles = new ArrayList<>(); 162 @Nullable private static PersistableBundle lastTransferOwnershipBundle; 163 private static Object /* DevicePolicyState */ devicePolicyState; 164 @Nullable private static SystemUpdateInfo systemUpdateInfo; 165 166 @Resetter reset()167 public static void reset() { 168 deviceOwner = null; 169 profileOwner = null; 170 organizationName = null; 171 organizationColor = DEFAULT_ORGANIZATION_COLOR; 172 isAutoTimeEnabled = false; 173 isAutoTimeRequired = false; 174 isAutoTimeZoneEnabled = false; 175 timeZone = null; 176 keyguardDisabledFeatures = 0; 177 lastSetPassword = null; 178 requiredPasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 179 180 passwordMinimumLength = 0; 181 passwordMinimumLetters = 1; 182 passwordMinimumLowerCase = 0; 183 passwordMinimumUpperCase = 0; 184 passwordMinimumNonLetter = 0; 185 passwordMinimumNumeric = 1; 186 passwordMinimumSymbols = 1; 187 passwordHistoryLength = 0; 188 passwordExpiration = 0; 189 passwordExpirationTimeout = 0; 190 maximumFailedPasswordsForWipe = 0; 191 maximumTimeToLock = 0; 192 cameraDisabled = false; 193 isActivePasswordSufficient = false; 194 isUniqueDeviceAttestationSupported = false; 195 passwordComplexity = 0; 196 197 wipeCalled = 0; 198 storageEncryptionStatus = DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 199 permissionPolicy = 0; 200 storageEncryptionRequested = false; 201 wasHiddenPackages.clear(); 202 accountTypesWithManagementDisabled.clear(); 203 systemAppsEnabled.clear(); 204 uninstallBlockedPackages.clear(); 205 suspendedPackages.clear(); 206 affiliationIds.clear(); 207 delegatedScopePackagesMap.clear(); 208 adminPolicyGrantedMap.clear(); 209 shortSupportMessageMap.clear(); 210 longSupportMessageMap.clear(); 211 componentsWithActivatedTokens.clear(); 212 lockTaskFeatures = 0; 213 lockTaskPackages.clear(); 214 policy = null; 215 isDeviceProvisioned = false; 216 isDeviceProvisioningConfigApplied = false; 217 organizationOwnedDeviceWithManagedProfile = false; 218 nearbyNotificationStreamingPolicy = 219 DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY; 220 nearbyAppStreamingPolicy = DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY; 221 isUsbDataSignalingEnabled = true; 222 devicePolicyManagementRoleHolderPackage = null; 223 finalizedWorkProfileProvisioningMap.clear(); 224 policyManagedProfiles = new ArrayList<>(); 225 userProvisioningStatesMap.clear(); 226 lastTransferOwnershipBundle = null; 227 } 228 229 private static class PackageAndPermission { 230 PackageAndPermission(String packageName, String permission)231 public PackageAndPermission(String packageName, String permission) { 232 this.packageName = packageName; 233 this.permission = permission; 234 } 235 236 private String packageName; 237 private String permission; 238 239 @Override equals(Object o)240 public boolean equals(Object o) { 241 if (!(o instanceof PackageAndPermission)) { 242 return false; 243 } 244 PackageAndPermission other = (PackageAndPermission) o; 245 return packageName.equals(other.packageName) && permission.equals(other.permission); 246 } 247 248 @Override hashCode()249 public int hashCode() { 250 int result = packageName.hashCode(); 251 result = 31 * result + permission.hashCode(); 252 return result; 253 } 254 } 255 256 @Implementation(maxSdk = M) __constructor__(Context context, Handler handler)257 protected void __constructor__(Context context, Handler handler) { 258 init(context); 259 invokeConstructor( 260 DevicePolicyManager.class, 261 realObject, 262 from(Context.class, context), 263 from(Handler.class, handler)); 264 } 265 266 @Implementation(minSdk = N, maxSdk = N_MR1) __constructor__(Context context, boolean parentInstance)267 protected void __constructor__(Context context, boolean parentInstance) { 268 init(context); 269 } 270 271 @Implementation(minSdk = O) __constructor__(Context context, IDevicePolicyManager service)272 protected void __constructor__(Context context, IDevicePolicyManager service) { 273 init(context); 274 } 275 init(Context context)276 private void init(Context context) { 277 this.context = context; 278 this.applicationPackageManager = 279 (ApplicationPackageManager) context.getApplicationContext().getPackageManager(); 280 organizationColor = DEFAULT_ORGANIZATION_COLOR; 281 storageEncryptionStatus = DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; 282 } 283 284 @Implementation isDeviceOwnerApp(String packageName)285 protected boolean isDeviceOwnerApp(String packageName) { 286 return deviceOwner != null && deviceOwner.getPackageName().equals(packageName); 287 } 288 289 @Implementation isProfileOwnerApp(String packageName)290 protected boolean isProfileOwnerApp(String packageName) { 291 return profileOwner != null && profileOwner.getPackageName().equals(packageName); 292 } 293 294 @Implementation isAdminActive(ComponentName who)295 protected boolean isAdminActive(ComponentName who) { 296 return who != null && deviceAdmins.contains(who); 297 } 298 299 @Implementation getActiveAdmins()300 protected List<ComponentName> getActiveAdmins() { 301 return deviceAdmins; 302 } 303 304 @Implementation addUserRestriction(ComponentName admin, String key)305 protected void addUserRestriction(ComponentName admin, String key) { 306 enforceActiveAdmin(admin); 307 getShadowUserManager().setUserRestriction(Process.myUserHandle(), key, true); 308 } 309 310 @Implementation clearUserRestriction(ComponentName admin, String key)311 protected void clearUserRestriction(ComponentName admin, String key) { 312 enforceActiveAdmin(admin); 313 getShadowUserManager().setUserRestriction(Process.myUserHandle(), key, false); 314 } 315 316 @Implementation setApplicationHidden(ComponentName admin, String packageName, boolean hidden)317 protected boolean setApplicationHidden(ComponentName admin, String packageName, boolean hidden) { 318 if (admin != null) { 319 enforceActiveAdmin(admin); 320 } else { 321 enforceCallerDelegated(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS); 322 } 323 if (packagesToFailForSetApplicationHidden.contains(packageName)) { 324 return false; 325 } 326 if (hidden) { 327 wasHiddenPackages.add(packageName); 328 } 329 return applicationPackageManager.setApplicationHiddenSettingAsUser( 330 packageName, hidden, Process.myUserHandle()); 331 } 332 333 /** 334 * Set package names for witch {@link DevicePolicyManager#setApplicationHidden} should fail. 335 * 336 * @param packagesToFail collection of package names or {@code null} to clear the packages. 337 */ failSetApplicationHiddenFor(Collection<String> packagesToFail)338 public void failSetApplicationHiddenFor(Collection<String> packagesToFail) { 339 if (packagesToFail == null) { 340 packagesToFail = Collections.emptySet(); 341 } 342 packagesToFailForSetApplicationHidden = packagesToFail; 343 } 344 345 @Implementation isApplicationHidden(ComponentName admin, String packageName)346 protected boolean isApplicationHidden(ComponentName admin, String packageName) { 347 if (admin != null) { 348 enforceActiveAdmin(admin); 349 } else { 350 enforceCallerDelegated(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS); 351 } 352 return applicationPackageManager.getApplicationHiddenSettingAsUser( 353 packageName, Process.myUserHandle()); 354 } 355 356 /** Returns {@code true} if the given {@code packageName} was ever hidden. */ wasPackageEverHidden(String packageName)357 public boolean wasPackageEverHidden(String packageName) { 358 return wasHiddenPackages.contains(packageName); 359 } 360 361 @Implementation enableSystemApp(ComponentName admin, String packageName)362 protected void enableSystemApp(ComponentName admin, String packageName) { 363 enforceActiveAdmin(admin); 364 systemAppsEnabled.add(packageName); 365 } 366 367 /** Returns {@code true} if the given {@code packageName} was a system app and was enabled. */ wasSystemAppEnabled(String packageName)368 public boolean wasSystemAppEnabled(String packageName) { 369 return systemAppsEnabled.contains(packageName); 370 } 371 372 @Implementation setUninstallBlocked( ComponentName admin, String packageName, boolean uninstallBlocked)373 protected void setUninstallBlocked( 374 ComponentName admin, String packageName, boolean uninstallBlocked) { 375 enforceActiveAdmin(admin); 376 if (uninstallBlocked) { 377 uninstallBlockedPackages.add(packageName); 378 } else { 379 uninstallBlockedPackages.remove(packageName); 380 } 381 } 382 383 @Implementation isUninstallBlocked(@ullable ComponentName admin, String packageName)384 protected boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) { 385 if (admin == null) { 386 // Starting from LOLLIPOP_MR1, the behavior of this API is changed such that passing null as 387 // the admin parameter will return if any admin has blocked the uninstallation. Before L MR1, 388 // passing null will cause a NullPointerException to be raised. 389 if (Build.VERSION.SDK_INT < LOLLIPOP_MR1) { 390 throw new NullPointerException("ComponentName is null"); 391 } 392 } else { 393 enforceActiveAdmin(admin); 394 } 395 return uninstallBlockedPackages.contains(packageName); 396 } 397 setIsUniqueDeviceAttestationSupported(boolean supported)398 public void setIsUniqueDeviceAttestationSupported(boolean supported) { 399 isUniqueDeviceAttestationSupported = supported; 400 } 401 402 @Implementation(minSdk = R) isUniqueDeviceAttestationSupported()403 protected boolean isUniqueDeviceAttestationSupported() { 404 return isUniqueDeviceAttestationSupported; 405 } 406 407 /** Sets USB signaling device restriction. */ setIsUsbDataSignalingEnabled(boolean isEnabled)408 public void setIsUsbDataSignalingEnabled(boolean isEnabled) { 409 isUsbDataSignalingEnabled = isEnabled; 410 } 411 412 @Implementation(minSdk = S) isUsbDataSignalingEnabled()413 protected boolean isUsbDataSignalingEnabled() { 414 return isUsbDataSignalingEnabled; 415 } 416 417 /** 418 * @see #setDeviceOwner(ComponentName) 419 */ 420 @Implementation getDeviceOwner()421 protected String getDeviceOwner() { 422 return deviceOwner != null ? deviceOwner.getPackageName() : null; 423 } 424 425 /** 426 * @see #setDeviceOwner(ComponentName) 427 */ 428 @Implementation(minSdk = N) isDeviceManaged()429 public boolean isDeviceManaged() { 430 return getDeviceOwner() != null; 431 } 432 433 /** 434 * @see #setProfileOwner(ComponentName) 435 */ 436 @Implementation getProfileOwner()437 protected ComponentName getProfileOwner() { 438 return profileOwner; 439 } 440 441 /** 442 * Returns the human-readable name of the profile owner for a user if set using {@link 443 * #setProfileOwnerName}, otherwise null. 444 */ 445 @Implementation getProfileOwnerNameAsUser(int userId)446 protected String getProfileOwnerNameAsUser(int userId) { 447 return profileOwnerNamesMap.get(userId); 448 } 449 450 @Implementation(minSdk = P) transferOwnership( ComponentName admin, ComponentName target, @Nullable PersistableBundle bundle)451 protected void transferOwnership( 452 ComponentName admin, ComponentName target, @Nullable PersistableBundle bundle) { 453 Objects.requireNonNull(admin, "ComponentName is null"); 454 Objects.requireNonNull(target, "Target cannot be null."); 455 Preconditions.checkArgument( 456 !admin.equals(target), "Provided administrator and target are the same object."); 457 Preconditions.checkArgument( 458 !admin.getPackageName().equals(target.getPackageName()), 459 "Provided administrator and target have the same package name."); 460 try { 461 context.getPackageManager().getReceiverInfo(target, 0); 462 } catch (PackageManager.NameNotFoundException e) { 463 throw new IllegalArgumentException("Unknown admin: " + target); 464 } 465 if (admin.equals(deviceOwner)) { 466 deviceOwner = target; 467 } else if (admin.equals(profileOwner)) { 468 profileOwner = target; 469 } else { 470 throw new SecurityException("Calling identity is not authorized"); 471 } 472 lastTransferOwnershipBundle = bundle; 473 } 474 475 @Implementation(minSdk = P) 476 @Nullable getTransferOwnershipBundle()477 protected PersistableBundle getTransferOwnershipBundle() { 478 return lastTransferOwnershipBundle; 479 } 480 getShadowUserManager()481 private ShadowUserManager getShadowUserManager() { 482 return Shadow.extract(context.getSystemService(Context.USER_SERVICE)); 483 } 484 485 /** 486 * Sets the admin as active admin and device owner. 487 * 488 * @see DevicePolicyManager#getDeviceOwner() 489 */ 490 @Implementation(minSdk = N, maxSdk = S_V2) setDeviceOwner(ComponentName admin)491 public boolean setDeviceOwner(ComponentName admin) { 492 setActiveAdmin(admin); 493 deviceOwner = admin; 494 return true; 495 } 496 497 /** 498 * Sets the admin as active admin and profile owner. 499 * 500 * @see DevicePolicyManager#getProfileOwner() 501 */ setProfileOwner(ComponentName admin)502 public void setProfileOwner(ComponentName admin) { 503 setActiveAdmin(admin); 504 profileOwner = admin; 505 } 506 setProfileOwnerName(int userId, String name)507 public void setProfileOwnerName(int userId, String name) { 508 profileOwnerNamesMap.put(userId, name); 509 } 510 511 /** Sets the given {@code componentName} as one of the active admins. */ setActiveAdmin(ComponentName componentName)512 public void setActiveAdmin(ComponentName componentName) { 513 deviceAdmins.add(componentName); 514 } 515 516 @Implementation removeActiveAdmin(ComponentName admin)517 protected void removeActiveAdmin(ComponentName admin) { 518 deviceAdmins.remove(admin); 519 } 520 521 @Implementation clearProfileOwner(ComponentName admin)522 protected void clearProfileOwner(ComponentName admin) { 523 profileOwner = null; 524 lastTransferOwnershipBundle = null; 525 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 526 removeActiveAdmin(admin); 527 } 528 } 529 530 @Implementation getApplicationRestrictions(ComponentName admin, String packageName)531 protected Bundle getApplicationRestrictions(ComponentName admin, String packageName) { 532 if (admin != null) { 533 enforceDeviceOwnerOrProfileOwner(admin); 534 } else { 535 enforceCallerDelegated(DevicePolicyManager.DELEGATION_APP_RESTRICTIONS); 536 } 537 return getApplicationRestrictions(packageName); 538 } 539 540 /** Returns all application restrictions of the {@code packageName} in a {@link Bundle}. */ getApplicationRestrictions(String packageName)541 public Bundle getApplicationRestrictions(String packageName) { 542 Bundle bundle = applicationRestrictionsMap.get(packageName); 543 // If no restrictions were saved, DPM method should return an empty Bundle as per JavaDoc. 544 return bundle != null ? new Bundle(bundle) : new Bundle(); 545 } 546 547 @Implementation setApplicationRestrictions( ComponentName admin, String packageName, Bundle applicationRestrictions)548 protected void setApplicationRestrictions( 549 ComponentName admin, String packageName, Bundle applicationRestrictions) { 550 if (admin != null) { 551 enforceDeviceOwnerOrProfileOwner(admin); 552 } else { 553 enforceCallerDelegated(DevicePolicyManager.DELEGATION_APP_RESTRICTIONS); 554 } 555 setApplicationRestrictions(packageName, applicationRestrictions); 556 } 557 558 /** 559 * Sets the application restrictions of the {@code packageName}. 560 * 561 * <p>The new {@code applicationRestrictions} always completely overwrites any existing ones. 562 */ setApplicationRestrictions(String packageName, Bundle applicationRestrictions)563 public void setApplicationRestrictions(String packageName, Bundle applicationRestrictions) { 564 applicationRestrictionsMap.put(packageName, new Bundle(applicationRestrictions)); 565 } 566 enforceProfileOwner(ComponentName admin)567 private void enforceProfileOwner(ComponentName admin) { 568 if (!admin.equals(profileOwner)) { 569 throw new SecurityException("[" + admin + "] is not a profile owner"); 570 } 571 } 572 enforceDeviceOwnerOrProfileOwner(ComponentName admin)573 private void enforceDeviceOwnerOrProfileOwner(ComponentName admin) { 574 if (!admin.equals(deviceOwner) && !admin.equals(profileOwner)) { 575 throw new SecurityException("[" + admin + "] is neither a device owner nor a profile owner."); 576 } 577 } 578 enforceActiveAdmin(ComponentName admin)579 private void enforceActiveAdmin(ComponentName admin) { 580 if (!deviceAdmins.contains(admin)) { 581 throw new SecurityException("[" + admin + "] is not an active device admin"); 582 } 583 } 584 enforceCallerDelegated(String targetScope)585 private void enforceCallerDelegated(String targetScope) { 586 String caller = context.getPackageName(); 587 if (!delegatedScopePackagesMap.containsKey(caller) 588 || !delegatedScopePackagesMap.get(caller).contains(targetScope)) { 589 throw new SecurityException("[" + caller + "] is not delegated with" + targetScope); 590 } 591 } 592 593 @Implementation(minSdk = O) setDelegatedScopes( ComponentName admin, String delegatePackage, List<String> scopes)594 protected void setDelegatedScopes( 595 ComponentName admin, String delegatePackage, List<String> scopes) { 596 enforceDeviceOwnerOrProfileOwner(admin); 597 delegatedScopePackagesMap.put(delegatePackage, ImmutableSet.copyOf(scopes)); 598 } 599 600 @Implementation(minSdk = O) getDelegatedScopes(ComponentName admin, String delegatePackage)601 protected List<String> getDelegatedScopes(ComponentName admin, String delegatePackage) { 602 Objects.requireNonNull(delegatePackage, "Delegate package is null"); 603 if (admin == null) { 604 String caller = context.getPackageName(); 605 if (!Objects.equals(caller, delegatePackage)) { 606 throw new SecurityException(String.format("Caller is not %s.", delegatePackage)); 607 } 608 // this app is retrieving its own delegated scopes 609 } else { 610 enforceDeviceOwnerOrProfileOwner(admin); 611 } 612 if (delegatedScopePackagesMap.containsKey(delegatePackage)) { 613 return ImmutableList.copyOf(delegatedScopePackagesMap.get(delegatePackage)); 614 } 615 return ImmutableList.of(); 616 } 617 618 @Implementation setAccountManagementDisabled( ComponentName admin, String accountType, boolean disabled)619 protected void setAccountManagementDisabled( 620 ComponentName admin, String accountType, boolean disabled) { 621 enforceDeviceOwnerOrProfileOwner(admin); 622 if (disabled) { 623 accountTypesWithManagementDisabled.add(accountType); 624 } else { 625 accountTypesWithManagementDisabled.remove(accountType); 626 } 627 } 628 629 @Implementation getAccountTypesWithManagementDisabled()630 protected String[] getAccountTypesWithManagementDisabled() { 631 return accountTypesWithManagementDisabled.toArray(new String[0]); 632 } 633 634 /** 635 * Sets organization name. 636 * 637 * <p>The API can only be called by profile owner since Android N and can be called by both of 638 * profile owner and device owner since Android O. 639 */ 640 @Implementation(minSdk = N) setOrganizationName(ComponentName admin, @Nullable CharSequence name)641 protected void setOrganizationName(ComponentName admin, @Nullable CharSequence name) { 642 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 643 enforceDeviceOwnerOrProfileOwner(admin); 644 } else { 645 enforceProfileOwner(admin); 646 } 647 648 if (TextUtils.isEmpty(name)) { 649 organizationName = null; 650 } else { 651 organizationName = name; 652 } 653 } 654 655 @Implementation(minSdk = N) setPackagesSuspended( ComponentName admin, String[] packageNames, boolean suspended)656 protected String[] setPackagesSuspended( 657 ComponentName admin, String[] packageNames, boolean suspended) { 658 if (admin != null) { 659 enforceDeviceOwnerOrProfileOwner(admin); 660 } else { 661 enforceCallerDelegated(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS); 662 } 663 if (packageNames == null) { 664 throw new NullPointerException("package names cannot be null"); 665 } 666 PackageManager pm = context.getPackageManager(); 667 ArrayList<String> packagesFailedToSuspend = new ArrayList<>(); 668 for (String packageName : packageNames) { 669 try { 670 // check if it is installed 671 pm.getPackageInfo(packageName, 0); 672 if (suspended) { 673 suspendedPackages.add(packageName); 674 } else { 675 suspendedPackages.remove(packageName); 676 } 677 } catch (NameNotFoundException e) { 678 packagesFailedToSuspend.add(packageName); 679 } 680 } 681 return packagesFailedToSuspend.toArray(new String[0]); 682 } 683 684 @Implementation(minSdk = N) isPackageSuspended(ComponentName admin, String packageName)685 protected boolean isPackageSuspended(ComponentName admin, String packageName) 686 throws NameNotFoundException { 687 if (admin != null) { 688 enforceDeviceOwnerOrProfileOwner(admin); 689 } else { 690 enforceCallerDelegated(DevicePolicyManager.DELEGATION_PACKAGE_ACCESS); 691 } 692 // Throws NameNotFoundException 693 context.getPackageManager().getPackageInfo(packageName, 0); 694 return suspendedPackages.contains(packageName); 695 } 696 697 @Implementation(minSdk = N) setOrganizationColor(ComponentName admin, int color)698 protected void setOrganizationColor(ComponentName admin, int color) { 699 enforceProfileOwner(admin); 700 organizationColor = color; 701 } 702 703 /** 704 * Returns organization name. 705 * 706 * <p>The API can only be called by profile owner since Android N. 707 * 708 * <p>Android framework has a hidden API for getting the organization name for device owner since 709 * Android O. This method, however, is extended to return the organization name for device owners 710 * too to make testing of {@link #setOrganizationName(ComponentName, CharSequence)} easier for 711 * device owner cases. 712 */ 713 @Implementation(minSdk = N) 714 @Nullable getOrganizationName(ComponentName admin)715 protected CharSequence getOrganizationName(ComponentName admin) { 716 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 717 enforceDeviceOwnerOrProfileOwner(admin); 718 } else { 719 enforceProfileOwner(admin); 720 } 721 722 return organizationName; 723 } 724 725 @Implementation(minSdk = N) getOrganizationColor(ComponentName admin)726 protected int getOrganizationColor(ComponentName admin) { 727 enforceProfileOwner(admin); 728 return organizationColor; 729 } 730 731 @Implementation(minSdk = R) setAutoTimeEnabled(ComponentName admin, boolean enabled)732 protected void setAutoTimeEnabled(ComponentName admin, boolean enabled) { 733 enforceDeviceOwnerOrProfileOwner(admin); 734 isAutoTimeEnabled = enabled; 735 } 736 737 @Implementation(minSdk = R) getAutoTimeEnabled(ComponentName admin)738 protected boolean getAutoTimeEnabled(ComponentName admin) { 739 enforceDeviceOwnerOrProfileOwner(admin); 740 return isAutoTimeEnabled; 741 } 742 743 @Implementation setAutoTimeRequired(ComponentName admin, boolean required)744 protected void setAutoTimeRequired(ComponentName admin, boolean required) { 745 enforceDeviceOwnerOrProfileOwner(admin); 746 isAutoTimeRequired = required; 747 } 748 749 @Implementation getAutoTimeRequired()750 protected boolean getAutoTimeRequired() { 751 return isAutoTimeRequired; 752 } 753 754 @Implementation(minSdk = R) setAutoTimeZoneEnabled(ComponentName admin, boolean enabled)755 protected void setAutoTimeZoneEnabled(ComponentName admin, boolean enabled) { 756 enforceDeviceOwnerOrProfileOwner(admin); 757 isAutoTimeZoneEnabled = enabled; 758 } 759 760 @Implementation(minSdk = R) getAutoTimeZoneEnabled(ComponentName admin)761 protected boolean getAutoTimeZoneEnabled(ComponentName admin) { 762 enforceDeviceOwnerOrProfileOwner(admin); 763 return isAutoTimeZoneEnabled; 764 } 765 766 @Implementation(minSdk = P) setTimeZone(ComponentName admin, String timeZone)767 protected boolean setTimeZone(ComponentName admin, String timeZone) { 768 enforceDeviceOwnerOrProfileOwner(admin); 769 if (isAutoTimeZoneEnabled) { 770 return false; 771 } 772 this.timeZone = timeZone; 773 return true; 774 } 775 776 /** Returns the time zone set by setTimeZone. */ getTimeZone()777 public String getTimeZone() { 778 return timeZone; 779 } 780 781 /** 782 * Sets permitted accessibility services. 783 * 784 * <p>The API can be called by either a profile or device owner. 785 * 786 * <p>This method does not check already enabled non-system accessibility services, so will always 787 * set the restriction and return true. 788 */ 789 @Implementation setPermittedAccessibilityServices( ComponentName admin, List<String> packageNames)790 protected boolean setPermittedAccessibilityServices( 791 ComponentName admin, List<String> packageNames) { 792 enforceDeviceOwnerOrProfileOwner(admin); 793 permittedAccessibilityServices = packageNames; 794 return true; 795 } 796 797 @Implementation 798 @Nullable getPermittedAccessibilityServices(ComponentName admin)799 protected List<String> getPermittedAccessibilityServices(ComponentName admin) { 800 enforceDeviceOwnerOrProfileOwner(admin); 801 return permittedAccessibilityServices; 802 } 803 804 /** 805 * Sets permitted input methods. 806 * 807 * <p>The API can be called by either a profile or device owner. 808 * 809 * <p>This method does not check already enabled non-system input methods, so will always set the 810 * restriction and return true. 811 */ 812 @Implementation setPermittedInputMethods(ComponentName admin, List<String> packageNames)813 protected boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) { 814 enforceDeviceOwnerOrProfileOwner(admin); 815 permittedInputMethods = packageNames; 816 return true; 817 } 818 819 @Implementation 820 @Nullable getPermittedInputMethods(ComponentName admin)821 protected List<String> getPermittedInputMethods(ComponentName admin) { 822 enforceDeviceOwnerOrProfileOwner(admin); 823 return permittedInputMethods; 824 } 825 826 /** 827 * @return the previously set status; default is {@link 828 * DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} 829 * @see #setStorageEncryptionStatus(int) 830 */ 831 @Implementation getStorageEncryptionStatus()832 protected int getStorageEncryptionStatus() { 833 return storageEncryptionStatus; 834 } 835 836 /** Setter for {@link DevicePolicyManager#getStorageEncryptionStatus()}. */ setStorageEncryptionStatus(int status)837 public void setStorageEncryptionStatus(int status) { 838 switch (status) { 839 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: 840 case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: 841 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING: 842 case DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED: 843 break; 844 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY: 845 if (RuntimeEnvironment.getApiLevel() < M) { 846 throw new IllegalArgumentException("status " + status + " requires API " + M); 847 } 848 break; 849 case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER: 850 if (RuntimeEnvironment.getApiLevel() < N) { 851 throw new IllegalArgumentException("status " + status + " requires API " + N); 852 } 853 break; 854 default: 855 throw new IllegalArgumentException("Unknown status: " + status); 856 } 857 858 storageEncryptionStatus = status; 859 } 860 861 @Implementation setStorageEncryption(ComponentName admin, boolean encrypt)862 protected int setStorageEncryption(ComponentName admin, boolean encrypt) { 863 enforceActiveAdmin(admin); 864 this.storageEncryptionRequested = encrypt; 865 return storageEncryptionStatus; 866 } 867 868 @Implementation getStorageEncryption(ComponentName admin)869 protected boolean getStorageEncryption(ComponentName admin) { 870 return storageEncryptionRequested; 871 } 872 873 @Implementation(minSdk = VERSION_CODES.M) getPermissionGrantState( ComponentName admin, String packageName, String permission)874 protected int getPermissionGrantState( 875 ComponentName admin, String packageName, String permission) { 876 enforceDeviceOwnerOrProfileOwner(admin); 877 Integer state = 878 appPermissionGrantStateMap.get(new PackageAndPermission(packageName, permission)); 879 return state == null ? DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT : state; 880 } 881 isPermissionGranted(String packageName, String permission)882 public boolean isPermissionGranted(String packageName, String permission) { 883 Boolean isGranted = 884 appPermissionGrantedMap.get(new PackageAndPermission(packageName, permission)); 885 return isGranted == null ? false : isGranted; 886 } 887 888 @Implementation(minSdk = VERSION_CODES.M) setPermissionGrantState( ComponentName admin, String packageName, String permission, int grantState)889 protected boolean setPermissionGrantState( 890 ComponentName admin, String packageName, String permission, int grantState) { 891 enforceDeviceOwnerOrProfileOwner(admin); 892 893 String selfPackageName = context.getPackageName(); 894 895 if (packageName.equals(selfPackageName)) { 896 PackageInfo packageInfo; 897 try { 898 packageInfo = 899 context 900 .getPackageManager() 901 .getPackageInfo(selfPackageName, PackageManager.GET_PERMISSIONS); 902 } catch (NameNotFoundException e) { 903 throw new RuntimeException(e); 904 } 905 if (Arrays.asList(packageInfo.requestedPermissions).contains(permission)) { 906 if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED) { 907 ShadowApplication.getInstance().grantPermissions(permission); 908 } 909 if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED) { 910 ShadowApplication.getInstance().denyPermissions(permission); 911 } 912 } else { 913 // the app does not require this permission 914 return false; 915 } 916 } 917 PackageAndPermission key = new PackageAndPermission(packageName, permission); 918 switch (grantState) { 919 case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: 920 appPermissionGrantedMap.put(key, true); 921 break; 922 case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: 923 appPermissionGrantedMap.put(key, false); 924 break; 925 default: 926 // no-op 927 } 928 appPermissionGrantStateMap.put(key, grantState); 929 return true; 930 } 931 932 @Implementation lockNow()933 protected void lockNow() { 934 KeyguardManager keyguardManager = 935 (KeyguardManager) this.context.getSystemService(Context.KEYGUARD_SERVICE); 936 ShadowKeyguardManager shadowKeyguardManager = Shadow.extract(keyguardManager); 937 shadowKeyguardManager.setKeyguardLocked(true); 938 shadowKeyguardManager.setIsDeviceLocked(true); 939 } 940 941 @Implementation wipeData(int flags)942 protected void wipeData(int flags) { 943 wipeCalled++; 944 } 945 getWipeCalledTimes()946 public long getWipeCalledTimes() { 947 return wipeCalled; 948 } 949 950 @Implementation setPasswordQuality(ComponentName admin, int quality)951 protected void setPasswordQuality(ComponentName admin, int quality) { 952 enforceActiveAdmin(admin); 953 requiredPasswordQuality = quality; 954 } 955 956 @Implementation getPasswordQuality(ComponentName admin)957 protected int getPasswordQuality(ComponentName admin) { 958 if (admin != null) { 959 enforceActiveAdmin(admin); 960 } 961 return requiredPasswordQuality; 962 } 963 964 @Implementation resetPassword(String password, int flags)965 protected boolean resetPassword(String password, int flags) { 966 if (!passwordMeetsRequirements(password)) { 967 return false; 968 } 969 lastSetPassword = password; 970 boolean secure = !password.isEmpty(); 971 KeyguardManager keyguardManager = 972 (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); 973 shadowOf(keyguardManager).setIsDeviceSecure(secure); 974 shadowOf(keyguardManager).setIsKeyguardSecure(secure); 975 return true; 976 } 977 978 @Implementation(minSdk = O) resetPasswordWithToken( ComponentName admin, String password, byte[] token, int flags)979 protected boolean resetPasswordWithToken( 980 ComponentName admin, String password, byte[] token, int flags) { 981 enforceDeviceOwnerOrProfileOwner(admin); 982 if (!Arrays.equals(passwordResetTokens.get(admin), token) 983 || !componentsWithActivatedTokens.contains(admin)) { 984 throw new IllegalStateException("wrong or not activated token"); 985 } 986 resetPassword(password, flags); 987 return true; 988 } 989 990 @Implementation(minSdk = O) isResetPasswordTokenActive(ComponentName admin)991 protected boolean isResetPasswordTokenActive(ComponentName admin) { 992 enforceDeviceOwnerOrProfileOwner(admin); 993 return componentsWithActivatedTokens.contains(admin); 994 } 995 996 @Implementation(minSdk = O) setResetPasswordToken(ComponentName admin, byte[] token)997 protected boolean setResetPasswordToken(ComponentName admin, byte[] token) { 998 if (token.length < 32) { 999 throw new IllegalArgumentException("token too short: " + token.length); 1000 } 1001 enforceDeviceOwnerOrProfileOwner(admin); 1002 passwordResetTokens.put(admin, token); 1003 componentsWithActivatedTokens.remove(admin); 1004 KeyguardManager keyguardManager = 1005 (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); 1006 if (!keyguardManager.isDeviceSecure()) { 1007 activateResetToken(admin); 1008 } 1009 return true; 1010 } 1011 1012 @Implementation setPasswordMinimumLength(ComponentName admin, int length)1013 protected void setPasswordMinimumLength(ComponentName admin, int length) { 1014 enforceActiveAdmin(admin); 1015 passwordMinimumLength = length; 1016 } 1017 1018 @Implementation getPasswordMinimumLength(ComponentName admin)1019 protected int getPasswordMinimumLength(ComponentName admin) { 1020 if (admin != null) { 1021 enforceActiveAdmin(admin); 1022 } 1023 return passwordMinimumLength; 1024 } 1025 1026 @Implementation setPasswordMinimumLetters(ComponentName admin, int length)1027 protected void setPasswordMinimumLetters(ComponentName admin, int length) { 1028 enforceActiveAdmin(admin); 1029 passwordMinimumLetters = length; 1030 } 1031 1032 @Implementation getPasswordMinimumLetters(ComponentName admin)1033 protected int getPasswordMinimumLetters(ComponentName admin) { 1034 if (admin != null) { 1035 enforceActiveAdmin(admin); 1036 } 1037 return passwordMinimumLetters; 1038 } 1039 1040 @Implementation setPasswordMinimumLowerCase(ComponentName admin, int length)1041 protected void setPasswordMinimumLowerCase(ComponentName admin, int length) { 1042 enforceActiveAdmin(admin); 1043 passwordMinimumLowerCase = length; 1044 } 1045 1046 @Implementation getPasswordMinimumLowerCase(ComponentName admin)1047 protected int getPasswordMinimumLowerCase(ComponentName admin) { 1048 if (admin != null) { 1049 enforceActiveAdmin(admin); 1050 } 1051 return passwordMinimumLowerCase; 1052 } 1053 1054 @Implementation setPasswordMinimumUpperCase(ComponentName admin, int length)1055 protected void setPasswordMinimumUpperCase(ComponentName admin, int length) { 1056 enforceActiveAdmin(admin); 1057 passwordMinimumUpperCase = length; 1058 } 1059 1060 @Implementation getPasswordMinimumUpperCase(ComponentName admin)1061 protected int getPasswordMinimumUpperCase(ComponentName admin) { 1062 if (admin != null) { 1063 enforceActiveAdmin(admin); 1064 } 1065 return passwordMinimumUpperCase; 1066 } 1067 1068 @Implementation setPasswordMinimumNonLetter(ComponentName admin, int length)1069 protected void setPasswordMinimumNonLetter(ComponentName admin, int length) { 1070 enforceActiveAdmin(admin); 1071 passwordMinimumNonLetter = length; 1072 } 1073 1074 @Implementation getPasswordMinimumNonLetter(ComponentName admin)1075 protected int getPasswordMinimumNonLetter(ComponentName admin) { 1076 if (admin != null) { 1077 enforceActiveAdmin(admin); 1078 } 1079 return passwordMinimumNonLetter; 1080 } 1081 1082 @Implementation setPasswordMinimumNumeric(ComponentName admin, int length)1083 protected void setPasswordMinimumNumeric(ComponentName admin, int length) { 1084 enforceActiveAdmin(admin); 1085 passwordMinimumNumeric = length; 1086 } 1087 1088 @Implementation getPasswordMinimumNumeric(ComponentName admin)1089 protected int getPasswordMinimumNumeric(ComponentName admin) { 1090 if (admin != null) { 1091 enforceActiveAdmin(admin); 1092 } 1093 return passwordMinimumNumeric; 1094 } 1095 1096 @Implementation setPasswordMinimumSymbols(ComponentName admin, int length)1097 protected void setPasswordMinimumSymbols(ComponentName admin, int length) { 1098 enforceActiveAdmin(admin); 1099 passwordMinimumSymbols = length; 1100 } 1101 1102 @Implementation getPasswordMinimumSymbols(ComponentName admin)1103 protected int getPasswordMinimumSymbols(ComponentName admin) { 1104 if (admin != null) { 1105 enforceActiveAdmin(admin); 1106 } 1107 return passwordMinimumSymbols; 1108 } 1109 1110 @Implementation setMaximumFailedPasswordsForWipe(ComponentName admin, int num)1111 protected void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) { 1112 enforceActiveAdmin(admin); 1113 maximumFailedPasswordsForWipe = num; 1114 } 1115 1116 @Implementation getMaximumFailedPasswordsForWipe(ComponentName admin)1117 protected int getMaximumFailedPasswordsForWipe(ComponentName admin) { 1118 if (admin != null) { 1119 enforceActiveAdmin(admin); 1120 } 1121 return maximumFailedPasswordsForWipe; 1122 } 1123 1124 @Implementation setCameraDisabled(ComponentName admin, boolean disabled)1125 protected void setCameraDisabled(ComponentName admin, boolean disabled) { 1126 enforceActiveAdmin(admin); 1127 cameraDisabled = disabled; 1128 } 1129 1130 @Implementation getCameraDisabled(ComponentName admin)1131 protected boolean getCameraDisabled(ComponentName admin) { 1132 if (admin != null) { 1133 enforceActiveAdmin(admin); 1134 } 1135 return cameraDisabled; 1136 } 1137 1138 @Implementation setPasswordExpirationTimeout(ComponentName admin, long timeout)1139 protected void setPasswordExpirationTimeout(ComponentName admin, long timeout) { 1140 enforceActiveAdmin(admin); 1141 passwordExpirationTimeout = timeout; 1142 } 1143 1144 @Implementation getPasswordExpirationTimeout(ComponentName admin)1145 protected long getPasswordExpirationTimeout(ComponentName admin) { 1146 if (admin != null) { 1147 enforceActiveAdmin(admin); 1148 } 1149 return passwordExpirationTimeout; 1150 } 1151 1152 /** 1153 * Sets the password expiration time for a particular admin. 1154 * 1155 * @param admin which DeviceAdminReceiver this request is associated with. 1156 * @param timeout the password expiration time, in milliseconds since epoch. 1157 */ setPasswordExpiration(ComponentName admin, long timeout)1158 public void setPasswordExpiration(ComponentName admin, long timeout) { 1159 enforceActiveAdmin(admin); 1160 passwordExpiration = timeout; 1161 } 1162 1163 @Implementation getPasswordExpiration(ComponentName admin)1164 protected long getPasswordExpiration(ComponentName admin) { 1165 if (admin != null) { 1166 enforceActiveAdmin(admin); 1167 } 1168 return passwordExpiration; 1169 } 1170 1171 @Implementation setMaximumTimeToLock(ComponentName admin, long timeMs)1172 protected void setMaximumTimeToLock(ComponentName admin, long timeMs) { 1173 enforceActiveAdmin(admin); 1174 maximumTimeToLock = timeMs; 1175 } 1176 1177 @Implementation getMaximumTimeToLock(ComponentName admin)1178 protected long getMaximumTimeToLock(ComponentName admin) { 1179 if (admin != null) { 1180 enforceActiveAdmin(admin); 1181 } 1182 return maximumTimeToLock; 1183 } 1184 1185 @Implementation setPasswordHistoryLength(ComponentName admin, int length)1186 protected void setPasswordHistoryLength(ComponentName admin, int length) { 1187 enforceActiveAdmin(admin); 1188 passwordHistoryLength = length; 1189 } 1190 1191 @Implementation getPasswordHistoryLength(ComponentName admin)1192 protected int getPasswordHistoryLength(ComponentName admin) { 1193 if (admin != null) { 1194 enforceActiveAdmin(admin); 1195 } 1196 return passwordHistoryLength; 1197 } 1198 1199 /** 1200 * Sets if the password meets the current requirements. 1201 * 1202 * @param sufficient indicates the password meets the current requirements 1203 */ setActivePasswordSufficient(boolean sufficient)1204 public void setActivePasswordSufficient(boolean sufficient) { 1205 isActivePasswordSufficient = sufficient; 1206 } 1207 1208 @Implementation isActivePasswordSufficient()1209 protected boolean isActivePasswordSufficient() { 1210 return isActivePasswordSufficient; 1211 } 1212 1213 /** Sets whether the device is provisioned. */ setDeviceProvisioned(boolean isProvisioned)1214 public void setDeviceProvisioned(boolean isProvisioned) { 1215 isDeviceProvisioned = isProvisioned; 1216 } 1217 1218 @Implementation(minSdk = O) 1219 @SystemApi 1220 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) isDeviceProvisioned()1221 protected boolean isDeviceProvisioned() { 1222 return isDeviceProvisioned; 1223 } 1224 1225 @Implementation(minSdk = O) 1226 @SystemApi 1227 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) setDeviceProvisioningConfigApplied()1228 protected void setDeviceProvisioningConfigApplied() { 1229 isDeviceProvisioningConfigApplied = true; 1230 } 1231 1232 @Implementation(minSdk = O) 1233 @SystemApi 1234 @RequiresPermission(android.Manifest.permission.MANAGE_USERS) isDeviceProvisioningConfigApplied()1235 protected boolean isDeviceProvisioningConfigApplied() { 1236 return isDeviceProvisioningConfigApplied; 1237 } 1238 1239 /** Sets the password complexity. */ setPasswordComplexity(@asswordComplexity int passwordComplexity)1240 public void setPasswordComplexity(@PasswordComplexity int passwordComplexity) { 1241 this.passwordComplexity = passwordComplexity; 1242 } 1243 1244 @PasswordComplexity 1245 @Implementation(minSdk = Q) getPasswordComplexity()1246 protected int getPasswordComplexity() { 1247 return passwordComplexity; 1248 } 1249 passwordMeetsRequirements(String password)1250 private boolean passwordMeetsRequirements(String password) { 1251 int digit = 0; 1252 int alpha = 0; 1253 int upper = 0; 1254 int lower = 0; 1255 int symbol = 0; 1256 for (int i = 0; i < password.length(); i++) { 1257 char c = password.charAt(i); 1258 if (Character.isDigit(c)) { 1259 digit++; 1260 } 1261 if (Character.isLetter(c)) { 1262 alpha++; 1263 } 1264 if (Character.isUpperCase(c)) { 1265 upper++; 1266 } 1267 if (Character.isLowerCase(c)) { 1268 lower++; 1269 } 1270 if (!Character.isLetterOrDigit(c)) { 1271 symbol++; 1272 } 1273 } 1274 switch (requiredPasswordQuality) { 1275 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED: 1276 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED: 1277 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK: 1278 return true; 1279 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: 1280 return password.length() > 0; 1281 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: 1282 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX: // complexity not enforced 1283 return digit > 0 && password.length() >= passwordMinimumLength; 1284 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: 1285 return digit > 0 && alpha > 0 && password.length() >= passwordMinimumLength; 1286 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: 1287 return password.length() >= passwordMinimumLength 1288 && alpha >= passwordMinimumLetters 1289 && lower >= passwordMinimumLowerCase 1290 && upper >= passwordMinimumUpperCase 1291 && digit + symbol >= passwordMinimumNonLetter 1292 && digit >= passwordMinimumNumeric 1293 && symbol >= passwordMinimumSymbols; 1294 default: 1295 return true; 1296 } 1297 } 1298 1299 /** 1300 * Retrieves last password set through {@link DevicePolicyManager#resetPassword} or {@link 1301 * DevicePolicyManager#resetPasswordWithToken}. 1302 */ getLastSetPassword()1303 public String getLastSetPassword() { 1304 return lastSetPassword; 1305 } 1306 1307 /** 1308 * Activates reset token for given admin. 1309 * 1310 * @param admin Which {@link DeviceAdminReceiver} this request is associated with. 1311 * @return if the activation state changed. 1312 * @throws IllegalArgumentException if there is no token set for this admin. 1313 */ activateResetToken(ComponentName admin)1314 public boolean activateResetToken(ComponentName admin) { 1315 if (!passwordResetTokens.containsKey(admin)) { 1316 throw new IllegalArgumentException("No token set for comopnent: " + admin); 1317 } 1318 return componentsWithActivatedTokens.add(admin); 1319 } 1320 1321 @Implementation addPersistentPreferredActivity( ComponentName admin, IntentFilter filter, ComponentName activity)1322 protected void addPersistentPreferredActivity( 1323 ComponentName admin, IntentFilter filter, ComponentName activity) { 1324 enforceDeviceOwnerOrProfileOwner(admin); 1325 1326 PackageManager packageManager = context.getPackageManager(); 1327 Shadow.<ShadowPackageManager>extract(packageManager) 1328 .addPersistentPreferredActivity(filter, activity); 1329 } 1330 1331 @Implementation clearPackagePersistentPreferredActivities( ComponentName admin, String packageName)1332 protected void clearPackagePersistentPreferredActivities( 1333 ComponentName admin, String packageName) { 1334 enforceDeviceOwnerOrProfileOwner(admin); 1335 PackageManager packageManager = context.getPackageManager(); 1336 Shadow.<ShadowPackageManager>extract(packageManager) 1337 .clearPackagePersistentPreferredActivities(packageName); 1338 } 1339 1340 @Implementation setKeyguardDisabledFeatures(ComponentName admin, int which)1341 protected void setKeyguardDisabledFeatures(ComponentName admin, int which) { 1342 enforceActiveAdmin(admin); 1343 keyguardDisabledFeatures = which; 1344 } 1345 1346 @Implementation getKeyguardDisabledFeatures(ComponentName admin)1347 protected int getKeyguardDisabledFeatures(ComponentName admin) { 1348 return keyguardDisabledFeatures; 1349 } 1350 1351 /** 1352 * Sets the user provisioning state. 1353 * 1354 * @param state to store provisioning state 1355 */ setUserProvisioningState(int state)1356 public void setUserProvisioningState(int state) { 1357 setUserProvisioningState(state, Process.myUserHandle()); 1358 } 1359 1360 @Implementation(minSdk = TIRAMISU) setUserProvisioningState(@serProvisioningState int state, UserHandle userHandle)1361 protected void setUserProvisioningState(@UserProvisioningState int state, UserHandle userHandle) { 1362 userProvisioningStatesMap.put(userHandle.getIdentifier(), state); 1363 } 1364 1365 /** 1366 * Returns the provisioning state set in {@link #setUserProvisioningState(int)}, or {@link 1367 * DevicePolicyManager#STATE_USER_UNMANAGED} if none is set. 1368 */ 1369 @Implementation(minSdk = N) getUserProvisioningState()1370 protected int getUserProvisioningState() { 1371 return getUserProvisioningStateForUser(Process.myUserHandle().getIdentifier()); 1372 } 1373 1374 @Implementation hasGrantedPolicy(@onnull ComponentName admin, int usesPolicy)1375 protected boolean hasGrantedPolicy(@Nonnull ComponentName admin, int usesPolicy) { 1376 enforceActiveAdmin(admin); 1377 Set<Integer> policyGrantedSet = adminPolicyGrantedMap.get(admin); 1378 return policyGrantedSet != null && policyGrantedSet.contains(usesPolicy); 1379 } 1380 1381 @Implementation(minSdk = P) getLockTaskFeatures(ComponentName admin)1382 protected int getLockTaskFeatures(ComponentName admin) { 1383 Objects.requireNonNull(admin, "ComponentName is null"); 1384 enforceDeviceOwnerOrProfileOwner(admin); 1385 return lockTaskFeatures; 1386 } 1387 1388 @Implementation(minSdk = P) setLockTaskFeatures(ComponentName admin, int flags)1389 protected void setLockTaskFeatures(ComponentName admin, int flags) { 1390 Objects.requireNonNull(admin, "ComponentName is null"); 1391 enforceDeviceOwnerOrProfileOwner(admin); 1392 // Throw if Overview is used without Home. 1393 boolean hasHome = (flags & LOCK_TASK_FEATURE_HOME) != 0; 1394 boolean hasOverview = (flags & LOCK_TASK_FEATURE_OVERVIEW) != 0; 1395 Preconditions.checkArgument( 1396 hasHome || !hasOverview, 1397 "Cannot use LOCK_TASK_FEATURE_OVERVIEW without LOCK_TASK_FEATURE_HOME"); 1398 boolean hasNotification = (flags & LOCK_TASK_FEATURE_NOTIFICATIONS) != 0; 1399 Preconditions.checkArgument( 1400 hasHome || !hasNotification, 1401 "Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME"); 1402 1403 lockTaskFeatures = flags; 1404 } 1405 1406 @Implementation setLockTaskPackages(@onnull ComponentName admin, String[] packages)1407 protected void setLockTaskPackages(@Nonnull ComponentName admin, String[] packages) { 1408 enforceDeviceOwnerOrProfileOwner(admin); 1409 lockTaskPackages.clear(); 1410 Collections.addAll(lockTaskPackages, packages); 1411 } 1412 1413 @Implementation getLockTaskPackages(@onnull ComponentName admin)1414 protected String[] getLockTaskPackages(@Nonnull ComponentName admin) { 1415 enforceDeviceOwnerOrProfileOwner(admin); 1416 return lockTaskPackages.toArray(new String[0]); 1417 } 1418 1419 @Implementation isLockTaskPermitted(@onnull String pkg)1420 protected boolean isLockTaskPermitted(@Nonnull String pkg) { 1421 return lockTaskPackages.contains(pkg); 1422 } 1423 1424 @Implementation(minSdk = O) setAffiliationIds(@onnull ComponentName admin, @Nonnull Set<String> ids)1425 protected void setAffiliationIds(@Nonnull ComponentName admin, @Nonnull Set<String> ids) { 1426 enforceDeviceOwnerOrProfileOwner(admin); 1427 affiliationIds.clear(); 1428 affiliationIds.addAll(ids); 1429 } 1430 1431 @Implementation(minSdk = O) getAffiliationIds(@onnull ComponentName admin)1432 protected Set<String> getAffiliationIds(@Nonnull ComponentName admin) { 1433 enforceDeviceOwnerOrProfileOwner(admin); 1434 return affiliationIds; 1435 } 1436 1437 @Implementation(minSdk = M) setPermissionPolicy(@onnull ComponentName admin, int policy)1438 protected void setPermissionPolicy(@Nonnull ComponentName admin, int policy) { 1439 enforceDeviceOwnerOrProfileOwner(admin); 1440 permissionPolicy = policy; 1441 } 1442 1443 @Implementation(minSdk = M) getPermissionPolicy(ComponentName admin)1444 protected int getPermissionPolicy(ComponentName admin) { 1445 enforceDeviceOwnerOrProfileOwner(admin); 1446 return permissionPolicy; 1447 } 1448 1449 /** 1450 * Grants a particular device policy for an active ComponentName. 1451 * 1452 * @param admin the ComponentName which DeviceAdminReceiver this request is associated with. Must 1453 * be an active administrator, or an exception will be thrown. This value must never be null. 1454 * @param usesPolicy the uses-policy to check 1455 */ grantPolicy(@onnull ComponentName admin, int usesPolicy)1456 public void grantPolicy(@Nonnull ComponentName admin, int usesPolicy) { 1457 enforceActiveAdmin(admin); 1458 Set<Integer> policyGrantedSet = adminPolicyGrantedMap.get(admin); 1459 if (policyGrantedSet == null) { 1460 policyGrantedSet = new HashSet<>(); 1461 policyGrantedSet.add(usesPolicy); 1462 adminPolicyGrantedMap.put(admin, policyGrantedSet); 1463 } else { 1464 policyGrantedSet.add(usesPolicy); 1465 } 1466 } 1467 1468 @Implementation(minSdk = M) getSystemUpdatePolicy()1469 protected SystemUpdatePolicy getSystemUpdatePolicy() { 1470 return policy; 1471 } 1472 1473 @Implementation(minSdk = M) setSystemUpdatePolicy(ComponentName admin, SystemUpdatePolicy policy)1474 protected void setSystemUpdatePolicy(ComponentName admin, SystemUpdatePolicy policy) { 1475 this.policy = policy; 1476 } 1477 1478 /** 1479 * Sets the system update policy. 1480 * 1481 * @see #setSystemUpdatePolicy(ComponentName, SystemUpdatePolicy) 1482 */ setSystemUpdatePolicy(SystemUpdatePolicy policy)1483 public void setSystemUpdatePolicy(SystemUpdatePolicy policy) { 1484 setSystemUpdatePolicy(null, policy); 1485 } 1486 1487 /** 1488 * Set the list of target users that the calling device or profile owner can use when calling 1489 * {@link #bindDeviceAdminServiceAsUser}. 1490 * 1491 * @see #getBindDeviceAdminTargetUsers(ComponentName) 1492 */ setBindDeviceAdminTargetUsers(List<UserHandle> bindDeviceAdminTargetUsers)1493 public void setBindDeviceAdminTargetUsers(List<UserHandle> bindDeviceAdminTargetUsers) { 1494 this.bindDeviceAdminTargetUsers = bindDeviceAdminTargetUsers; 1495 } 1496 1497 /** 1498 * Returns the list of target users that the calling device or profile owner can use when calling 1499 * {@link #bindDeviceAdminServiceAsUser}. 1500 * 1501 * @see #setBindDeviceAdminTargetUsers(List) 1502 */ 1503 @Implementation(minSdk = O) getBindDeviceAdminTargetUsers(ComponentName admin)1504 protected List<UserHandle> getBindDeviceAdminTargetUsers(ComponentName admin) { 1505 return bindDeviceAdminTargetUsers; 1506 } 1507 1508 /** 1509 * Bind to the same package in another user. 1510 * 1511 * <p>This validates that the targetUser is one from {@link 1512 * #getBindDeviceAdminTargetUsers(ComponentName)} but does not actually bind to a different user, 1513 * instead binding to the same user. 1514 * 1515 * <p>It also does not validate the service being bound to. 1516 */ 1517 @Implementation(minSdk = O) bindDeviceAdminServiceAsUser( ComponentName admin, Intent serviceIntent, ServiceConnection conn, int flags, UserHandle targetUser)1518 protected boolean bindDeviceAdminServiceAsUser( 1519 ComponentName admin, 1520 Intent serviceIntent, 1521 ServiceConnection conn, 1522 int flags, 1523 UserHandle targetUser) { 1524 if (!getBindDeviceAdminTargetUsers(admin).contains(targetUser)) { 1525 throw new SecurityException("Not allowed to bind to target user id"); 1526 } 1527 1528 return context.bindServiceAsUser(serviceIntent, conn, flags, targetUser); 1529 } 1530 1531 @Implementation(minSdk = N) setShortSupportMessage(ComponentName admin, @Nullable CharSequence message)1532 protected void setShortSupportMessage(ComponentName admin, @Nullable CharSequence message) { 1533 enforceActiveAdmin(admin); 1534 shortSupportMessageMap.put(admin, message); 1535 } 1536 1537 @Implementation(minSdk = N) 1538 @Nullable getShortSupportMessage(ComponentName admin)1539 protected CharSequence getShortSupportMessage(ComponentName admin) { 1540 enforceActiveAdmin(admin); 1541 return shortSupportMessageMap.get(admin); 1542 } 1543 1544 @Implementation(minSdk = N) setLongSupportMessage(ComponentName admin, @Nullable CharSequence message)1545 protected void setLongSupportMessage(ComponentName admin, @Nullable CharSequence message) { 1546 enforceActiveAdmin(admin); 1547 longSupportMessageMap.put(admin, message); 1548 } 1549 1550 @Implementation(minSdk = N) 1551 @Nullable getLongSupportMessage(ComponentName admin)1552 protected CharSequence getLongSupportMessage(ComponentName admin) { 1553 enforceActiveAdmin(admin); 1554 return longSupportMessageMap.get(admin); 1555 } 1556 1557 /** 1558 * Sets the return value of the {@link 1559 * DevicePolicyManager#isOrganizationOwnedDeviceWithManagedProfile} method (only for Android R+). 1560 */ setOrganizationOwnedDeviceWithManagedProfile(boolean value)1561 public void setOrganizationOwnedDeviceWithManagedProfile(boolean value) { 1562 organizationOwnedDeviceWithManagedProfile = value; 1563 } 1564 1565 /** 1566 * Returns the value stored using in the shadow, while the real method returns the value store on 1567 * the device. 1568 * 1569 * <p>The value can be set by {@link #setOrganizationOwnedDeviceWithManagedProfile} and is {@code 1570 * false} by default. 1571 */ 1572 @Implementation(minSdk = R) isOrganizationOwnedDeviceWithManagedProfile()1573 protected boolean isOrganizationOwnedDeviceWithManagedProfile() { 1574 return organizationOwnedDeviceWithManagedProfile; 1575 } 1576 1577 @Implementation(minSdk = S) 1578 @NearbyStreamingPolicy getNearbyNotificationStreamingPolicy()1579 protected int getNearbyNotificationStreamingPolicy() { 1580 return nearbyNotificationStreamingPolicy; 1581 } 1582 1583 @Implementation(minSdk = S) setNearbyNotificationStreamingPolicy(@earbyStreamingPolicy int policy)1584 protected void setNearbyNotificationStreamingPolicy(@NearbyStreamingPolicy int policy) { 1585 nearbyNotificationStreamingPolicy = policy; 1586 } 1587 1588 @Implementation(minSdk = S) 1589 @NearbyStreamingPolicy getNearbyAppStreamingPolicy()1590 protected int getNearbyAppStreamingPolicy() { 1591 return nearbyAppStreamingPolicy; 1592 } 1593 1594 @Implementation(minSdk = S) setNearbyAppStreamingPolicy(@earbyStreamingPolicy int policy)1595 protected void setNearbyAppStreamingPolicy(@NearbyStreamingPolicy int policy) { 1596 nearbyAppStreamingPolicy = policy; 1597 } 1598 1599 @Nullable 1600 @Implementation(minSdk = TIRAMISU) getDevicePolicyManagementRoleHolderPackage()1601 protected String getDevicePolicyManagementRoleHolderPackage() { 1602 return devicePolicyManagementRoleHolderPackage; 1603 } 1604 1605 /** 1606 * Sets the package name of the device policy management role holder. 1607 * 1608 * @see #getDevicePolicyManagementRoleHolderPackage() 1609 */ setDevicePolicyManagementRoleHolderPackage(@ullable String packageName)1610 public void setDevicePolicyManagementRoleHolderPackage(@Nullable String packageName) { 1611 devicePolicyManagementRoleHolderPackage = packageName; 1612 } 1613 1614 @Implementation(minSdk = TIRAMISU) finalizeWorkProfileProvisioning( UserHandle managedProfileUser, @Nullable Account migratedAccount)1615 protected void finalizeWorkProfileProvisioning( 1616 UserHandle managedProfileUser, @Nullable Account migratedAccount) { 1617 finalizedWorkProfileProvisioningMap.put(managedProfileUser, migratedAccount); 1618 } 1619 1620 /** 1621 * Returns if {@link #finalizeWorkProfileProvisioning(UserHandle, Account)} was called with the 1622 * provided parameters. 1623 */ isWorkProfileProvisioningFinalized( UserHandle userHandle, @Nullable Account migratedAccount)1624 public boolean isWorkProfileProvisioningFinalized( 1625 UserHandle userHandle, @Nullable Account migratedAccount) { 1626 return finalizedWorkProfileProvisioningMap.containsKey(userHandle) 1627 && Objects.equals(finalizedWorkProfileProvisioningMap.get(userHandle), migratedAccount); 1628 } 1629 1630 /** 1631 * Returns the managed profiles set in {@link #setPolicyManagedProfiles(List)}. This value does 1632 * not take the user handle parameter into account. 1633 */ 1634 @Implementation(minSdk = TIRAMISU) getPolicyManagedProfiles(UserHandle userHandle)1635 protected List<UserHandle> getPolicyManagedProfiles(UserHandle userHandle) { 1636 return policyManagedProfiles; 1637 } 1638 1639 /** Sets the value returned by {@link #getPolicyManagedProfiles(UserHandle)}. */ setPolicyManagedProfiles(List<UserHandle> policyManagedProfiles)1640 public void setPolicyManagedProfiles(List<UserHandle> policyManagedProfiles) { 1641 this.policyManagedProfiles = policyManagedProfiles; 1642 } 1643 1644 /** 1645 * Returns the user provisioning state set by {@link #setUserProvisioningState(int, UserHandle)}, 1646 * or {@link DevicePolicyManager#STATE_USER_UNMANAGED} if none is set. 1647 */ 1648 @UserProvisioningState getUserProvisioningStateForUser(int userId)1649 public int getUserProvisioningStateForUser(int userId) { 1650 return userProvisioningStatesMap.getOrDefault(userId, DevicePolicyManager.STATE_USER_UNMANAGED); 1651 } 1652 1653 /** Return a stub value set by {@link #setDevicePolicyState(DevicePolicyState policyState)} */ 1654 @Implementation(minSdk = U.SDK_INT) getDevicePolicyState()1655 protected @ClassName("android.app.admin.DevicePolicyState") Object getDevicePolicyState() { 1656 return devicePolicyState; 1657 } 1658 1659 /** 1660 * Set the {@link DevicePolicyState} which can be constructed from {@link 1661 * DevicePolicyStateBuilder} 1662 */ setDevicePolicyState(Object policyState)1663 public void setDevicePolicyState(Object policyState) { 1664 devicePolicyState = policyState; 1665 } 1666 1667 /** 1668 * Set the {@link SystemUpdateInfo} to be returned by {@link 1669 * DevicePolicyManager#getPendingSystemUpdate(ComponentName)}. 1670 */ setPendingSystemUpdate(@ullable SystemUpdateInfo info)1671 public void setPendingSystemUpdate(@Nullable SystemUpdateInfo info) { 1672 systemUpdateInfo = info; 1673 } 1674 1675 @Implementation(minSdk = O) notifyPendingSystemUpdate(long updateReceivedTime)1676 protected void notifyPendingSystemUpdate(long updateReceivedTime) { 1677 systemUpdateInfo = reflector(SystemUpdateInfoReflector.class).of(updateReceivedTime); 1678 } 1679 1680 @Implementation(minSdk = O) notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch)1681 protected void notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch) { 1682 systemUpdateInfo = 1683 reflector(SystemUpdateInfoReflector.class).of(updateReceivedTime, isSecurityPatch); 1684 } 1685 1686 @Implementation(minSdk = O) 1687 @Nullable getPendingSystemUpdate(@ullable ComponentName admin)1688 protected SystemUpdateInfo getPendingSystemUpdate(@Nullable ComponentName admin) { 1689 return systemUpdateInfo; 1690 } 1691 1692 @ForType(SystemUpdateInfo.class) 1693 interface SystemUpdateInfoReflector { 1694 @Static of(long updateReceivedTime)1695 SystemUpdateInfo of(long updateReceivedTime); 1696 1697 @Static of(long updateReceivedTime, boolean isSecurityPatch)1698 SystemUpdateInfo of(long updateReceivedTime, boolean isSecurityPatch); 1699 } 1700 } 1701