1 /* <lambda>null2 * 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 package com.android.bedstead.nene.devicepolicy 17 18 import android.Manifest 19 import android.annotation.SuppressLint 20 import android.annotation.TargetApi 21 import android.app.admin.DevicePolicyManager 22 import android.app.admin.EnforcingAdmin 23 import android.app.role.RoleManager 24 import android.content.ComponentName 25 import android.content.Intent 26 import android.cts.testapisreflection.* 27 import android.os.Build 28 import android.os.PersistableBundle 29 import android.os.UserHandle 30 import android.util.Log 31 import com.android.bedstead.nene.TestApis 32 import com.android.bedstead.nene.annotations.Experimental 33 import com.android.bedstead.nene.exceptions.AdbException 34 import com.android.bedstead.nene.exceptions.AdbParseException 35 import com.android.bedstead.nene.exceptions.NeneException 36 import com.android.bedstead.nene.packages.ComponentReference 37 import com.android.bedstead.nene.packages.Package 38 import com.android.bedstead.nene.roles.RoleContext 39 import com.android.bedstead.nene.users.UserReference 40 import com.android.bedstead.nene.utils.Poll 41 import com.android.bedstead.nene.utils.Retry 42 import com.android.bedstead.nene.utils.ShellCommand 43 import com.android.bedstead.nene.utils.ShellCommandUtils 44 import com.android.bedstead.nene.utils.Versions 45 import com.android.bedstead.permissions.CommonPermissions 46 import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL 47 import com.android.bedstead.permissions.CommonPermissions.MANAGE_DEVICE_POLICY_STORAGE_LIMIT 48 import com.android.bedstead.permissions.CommonPermissions.NOTIFY_PENDING_SYSTEM_UPDATE 49 import com.android.bedstead.permissions.CommonPermissions.QUERY_ADMIN_POLICY 50 import com.android.bedstead.permissions.CommonPermissions.READ_NEARBY_STREAMING_POLICY 51 import java.lang.reflect.InvocationTargetException 52 import java.time.Duration 53 import java.util.stream.Collectors 54 55 /** 56 * Test APIs related to device policy. 57 */ 58 object DevicePolicy { 59 private val mParser = AdbDevicePolicyParser.get(Build.VERSION.SDK_INT) 60 private var mCachedDeviceOwner: DeviceOwner? = null 61 private var mCachedProfileOwners: Map<UserReference, ProfileOwner>? = null 62 63 /** 64 * Set the profile owner for a given [UserReference]. 65 */ 66 fun setProfileOwner(user: UserReference, profileOwnerComponent: ComponentName): ProfileOwner { 67 val command = ShellCommand.builderForUser(user, "dpm set-profile-owner") 68 .addOperand(profileOwnerComponent.flattenToShortString()) 69 .validate { ShellCommandUtils.startsWithSuccess(it) } 70 71 // TODO(b/187925230): If it fails, we check for terminal failure states - and if not 72 // we retry because if the profile owner was recently removed, it can take some time 73 // to be allowed to set it again 74 try { 75 Retry.logic { command.execute() } 76 .terminalException { ex: Throwable -> 77 if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) { 78 return@terminalException false // Just retry on old versions as we don't have stderr 79 } 80 if (ex is AdbException) { 81 val error = ex.error() 82 if (error != null && error.contains("is already set")) { 83 // This can happen for a while when it is being tidied up 84 return@terminalException false 85 } 86 if (error != null && error.contains("is being removed")) { 87 return@terminalException false 88 } 89 } 90 true 91 } 92 .timeout(Duration.ofMinutes(5)) 93 .run() 94 } catch (e: Throwable) { 95 throw NeneException( 96 "Could not set profile owner for user: $user, component: $profileOwnerComponent", 97 e 98 ) 99 } 100 Poll.forValue("Profile Owner") { TestApis.devicePolicy().getProfileOwner(user) } 101 .toNotBeNull() 102 .errorOnFail() 103 .await() 104 return ProfileOwner( 105 user, 106 TestApis.packages().find( 107 profileOwnerComponent.packageName 108 ), 109 profileOwnerComponent 110 ) 111 } 112 113 val organizationOwnedProfileOwner: ProfileOwner? 114 /** 115 * Get the organization owned profile owner for the device, if any, otherwise null. 116 */ 117 get() { 118 for (user in TestApis.users().all()) { 119 val profileOwner = getProfileOwner(user) 120 if (profileOwner != null && profileOwner.isOrganizationOwned) { 121 return profileOwner 122 } 123 } 124 return null 125 } 126 127 /** 128 * Get the profile owner for a given [UserHandle]. 129 */ 130 fun getProfileOwner(user: UserHandle): ProfileOwner? { 131 return getProfileOwner(UserReference.of(user)) 132 } 133 134 /** 135 * Get the profile owner for a given [UserReference]. 136 */ 137 @JvmOverloads 138 fun getProfileOwner(user: UserReference = TestApis.users().instrumented()): ProfileOwner? { 139 fillCache() 140 // mCachedProfileOwners has been filled by fillCache 141 return mCachedProfileOwners!![user] 142 } 143 144 /** 145 * Set the device owner. 146 */ 147 @JvmOverloads 148 fun setDeviceOwner( 149 deviceOwnerComponent: ComponentName, 150 user: UserReference = TestApis.users().system() 151 ): DeviceOwner { 152 if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) { 153 return setDeviceOwnerPreS(deviceOwnerComponent) 154 } else if (!Versions.meetsMinimumSdkVersionRequirement(Versions.U)) { 155 return setDeviceOwnerPreU(deviceOwnerComponent) 156 } 157 try { 158 TestApis.permissions().withPermission( 159 CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS, 160 CommonPermissions.MANAGE_DEVICE_ADMINS, 161 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 162 Manifest.permission.INTERACT_ACROSS_USERS, 163 Manifest.permission.CREATE_USERS 164 ).use { 165 val command = ShellCommand.builderForUser( 166 user, 167 "dpm set-device-owner --device-owner-only" 168 ) 169 .addOperand(deviceOwnerComponent.flattenToShortString()) 170 .validate { ShellCommandUtils.startsWithSuccess(it) } 171 // TODO(b/187925230): If it fails, we check for terminal failure states - and if not 172 // we retry because if the DO/PO was recently removed, it can take some time 173 // to be allowed to set it again 174 Retry.logic { command.execute() } 175 .terminalException { e: Throwable -> 176 checkForTerminalDeviceOwnerFailures( 177 user, 178 deviceOwnerComponent, /* allowAdditionalUsers= */ 179 false, 180 e 181 ) 182 } 183 .timeout(Duration.ofMinutes(5)) 184 .run() 185 } 186 } catch (e: Throwable) { 187 throw NeneException("Error setting device owner.", e) 188 } 189 val deviceOwnerPackage = TestApis.packages().find( 190 deviceOwnerComponent.packageName 191 ) 192 Poll.forValue("Device Owner") { TestApis.devicePolicy().getDeviceOwner() } 193 .toNotBeNull() 194 .errorOnFail() 195 .await() 196 return DeviceOwner(user, deviceOwnerPackage, deviceOwnerComponent) 197 } 198 199 /** 200 * Set Device Owner without changing any other device state. 201 * 202 * 203 * This is used instead of [DevicePolicyManager.setDeviceOwner] directly 204 * because on S_V2 and above, that method can also set profile owners and install packages in 205 * some circumstances. 206 */ 207 private fun setDeviceOwnerOnly( 208 component: ComponentName, 209 deviceOwnerUserId: Int 210 ) { 211 if (Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { 212 devicePolicyManager.setDeviceOwnerOnly(component, deviceOwnerUserId) 213 } else if (Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S_V2)) { 214 try { 215 DevicePolicyManager::class.java.getMethod( 216 "setDeviceOwnerOnly", 217 ComponentName::class.java, 218 String::class.java, 219 Int::class.javaPrimitiveType 220 ).invoke(devicePolicyManager, component, null, deviceOwnerUserId) 221 } catch (e: IllegalAccessException) { 222 throw NeneException("Error executing setDeviceOwnerOnly", e) 223 } catch (e: InvocationTargetException) { 224 throw NeneException("Error executing setDeviceOwnerOnly", e) 225 } catch (e: NoSuchMethodException) { 226 throw NeneException("Error executing setDeviceOwnerOnly", e) 227 } 228 } else { 229 try { 230 DevicePolicyManager::class.java.getMethod( 231 "setDeviceOwner", 232 ComponentName::class.java, 233 String::class.java, 234 Int::class.javaPrimitiveType 235 ).invoke(devicePolicyManager, component, null, deviceOwnerUserId) 236 } catch (e: IllegalAccessException) { 237 throw NeneException("Error executing setDeviceOwner", e) 238 } catch (e: InvocationTargetException) { 239 throw NeneException("Error executing setDeviceOwner", e) 240 } catch (e: NoSuchMethodException) { 241 throw NeneException("Error executing setDeviceOwner", e) 242 } 243 } 244 } 245 246 /** 247 * Resets organization ID via @TestApi. 248 * 249 * @param user whose organization ID to clear 250 */ 251 @JvmOverloads 252 fun clearOrganizationId(user: UserReference = TestApis.users().instrumented()) { 253 TestApis.permissions().withPermission(CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS) 254 .use { devicePolicyManager(user).clearOrganizationId() } 255 } 256 257 /** 258 * See [DevicePolicyManager.setNextOperationSafety]. 259 */ 260 fun setNextOperationSafety( 261 operation: CommonDevicePolicy.DevicePolicyOperation, 262 reason: CommonDevicePolicy.OperationSafetyReason 263 ) { 264 TestApis.permissions().withPermission( 265 CommonPermissions.MANAGE_DEVICE_ADMINS, 266 Manifest.permission.INTERACT_ACROSS_USERS 267 ).use { devicePolicyManager.setNextOperationSafety(operation.value, reason.value) } 268 } 269 270 /** 271 * See [DevicePolicyManager.isSafeOperation]. 272 */ 273 @SuppressLint("NewApi") // isSafeOperation introduced in API 31 274 fun isSafeOperation(reason: CommonDevicePolicy.OperationSafetyReason): Boolean = 275 if (!Versions.meetsMinimumSdkVersionRequirement(Build.VERSION_CODES.S)) { 276 Thread.sleep(ONE_TIME_SAFETY_CHECKER_SELF_DESTRUCT_TIMEOUT_MS) 277 true 278 } 279 else { 280 TestApis.permissions().withPermission( 281 CommonPermissions.MANAGE_DEVICE_ADMINS, 282 Manifest.permission.INTERACT_ACROSS_USERS 283 ).use { devicePolicyManager.isSafeOperation(reason.value) } 284 } 285 286 /** 287 * See [DevicePolicyManager.lockNow]. 288 */ 289 fun lockNow() { 290 devicePolicyManager.lockNow() 291 } 292 293 private fun devicePolicyManager(user: UserReference): DevicePolicyManager = 294 if (user == TestApis.users().instrumented()) { 295 devicePolicyManager 296 } else { 297 TestApis.context().androidContextAsUser(user) 298 .getSystemService(DevicePolicyManager::class.java)!! 299 } 300 301 private fun setDeviceOwnerPreU(deviceOwnerComponent: ComponentName): DeviceOwner { 302 val user = TestApis.users().system() 303 val dpmUserSetupComplete = user.setupComplete 304 try { 305 user.setupComplete = false 306 try { 307 TestApis.permissions().withPermission( 308 CommonPermissions.MANAGE_PROFILE_AND_DEVICE_OWNERS, 309 CommonPermissions.MANAGE_DEVICE_ADMINS, 310 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 311 Manifest.permission.INTERACT_ACROSS_USERS, 312 Manifest.permission.CREATE_USERS 313 ).use { 314 // TODO(b/187925230): If it fails, we check for terminal failure states - and if not 315 // we retry because if the DO/PO was recently removed, it can take some time 316 // to be allowed to set it again 317 Retry.logic { 318 devicePolicyManager.setActiveAdmin( 319 deviceOwnerComponent, /* refreshing= */ 320 true, 321 user.id() 322 ) 323 setDeviceOwnerOnly(deviceOwnerComponent, user.id()) 324 } 325 .terminalException { e: Throwable -> 326 checkForTerminalDeviceOwnerFailures( 327 user, 328 deviceOwnerComponent, /* allowAdditionalUsers= */ 329 true, 330 e 331 ) 332 } 333 .timeout(Duration.ofMinutes(5)) 334 .run() 335 } 336 } catch (e: Throwable) { 337 throw NeneException("Error setting device owner", e) 338 } 339 } finally { 340 user.setupComplete = dpmUserSetupComplete 341 } 342 Poll.forValue("Device Owner") { TestApis.devicePolicy().getDeviceOwner() } 343 .toNotBeNull() 344 .errorOnFail() 345 .await() 346 return DeviceOwner( 347 user, 348 TestApis.packages().find(deviceOwnerComponent.packageName), 349 deviceOwnerComponent 350 ) 351 } 352 353 private fun setDeviceOwnerPreS(deviceOwnerComponent: ComponentName): DeviceOwner { 354 val user = TestApis.users().system() 355 val command = ShellCommand.builderForUser( 356 user, 357 "dpm set-device-owner" 358 ) 359 .addOperand(deviceOwnerComponent.flattenToShortString()) 360 .validate { ShellCommandUtils.startsWithSuccess(it) } 361 // TODO(b/187925230): If it fails, we check for terminal failure states - and if not 362 // we retry because if the device owner was recently removed, it can take some time 363 // to be allowed to set it again 364 try { 365 Retry.logic { command.execute() } 366 .terminalException { e: Throwable -> 367 checkForTerminalDeviceOwnerFailures( 368 user, 369 deviceOwnerComponent, /* allowAdditionalUsers= */ 370 false, 371 e 372 ) 373 } 374 .timeout(Duration.ofMinutes(5)) 375 .run() 376 } catch (e: Throwable) { 377 throw NeneException("Error setting device owner", e) 378 } 379 return DeviceOwner( 380 user, 381 TestApis.packages().find( 382 deviceOwnerComponent.packageName 383 ), 384 deviceOwnerComponent 385 ) 386 } 387 388 private fun checkForTerminalDeviceOwnerFailures( 389 user: UserReference, 390 deviceOwnerComponent: ComponentName, 391 allowAdditionalUsers: Boolean, 392 e: Throwable 393 ): Boolean { 394 val deviceOwner = getDeviceOwner() 395 if (deviceOwner != null) { 396 // TODO(scottjonathan): Should we actually fail here if the component name is the 397 // same? 398 throw NeneException( 399 "Could not set device owner for user $user as a device owner is already set: $deviceOwner", 400 e 401 ) 402 } 403 val pkg = TestApis.packages().find(deviceOwnerComponent.packageName) 404 if (!TestApis.packages().installedForUser(user).contains(pkg)) { 405 throw NeneException( 406 "Could not set device owner for user $user as the package $pkg is not installed", 407 e 408 ) 409 } 410 if (!componentCanBeSetAsDeviceAdmin(deviceOwnerComponent, user)) { 411 throw NeneException( 412 "Could not set device owner for user $user as component $deviceOwnerComponent is not valid", 413 e 414 ) 415 } 416 if (!allowAdditionalUsers && nonTestNonPrecreatedUsersExist()) { 417 throw NeneException( 418 "Could not set device owner for user $user as there are already additional non-test on the device", 419 e 420 ) 421 } 422 // TODO(scottjonathan): Check accounts 423 return false 424 } 425 426 private fun componentCanBeSetAsDeviceAdmin( 427 component: ComponentName, 428 user: UserReference 429 ): Boolean { 430 val packageManager = TestApis.context().instrumentedContext().packageManager 431 val intent = Intent("android.app.action.DEVICE_ADMIN_ENABLED") 432 intent.setComponent(component) 433 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) 434 .use { 435 val r = packageManager.queryBroadcastReceiversAsUser( 436 intent, /* flags= */ 437 0, 438 user.userHandle() 439 ) 440 return r.isNotEmpty() 441 } 442 } 443 444 /** 445 * Get the device owner. 446 */ 447 fun getDeviceOwner(): DeviceOwner? { 448 fillCache() 449 return mCachedDeviceOwner 450 } 451 452 private fun fillCache() { 453 var retries = 5 454 while (true) { 455 try { 456 // TODO: Replace use of adb on supported versions of Android 457 val devicePolicyDumpsysOutput = 458 ShellCommand.builder("dumpsys device_policy").execute() 459 val result = mParser.parse(devicePolicyDumpsysOutput) 460 mCachedDeviceOwner = result.mDeviceOwner 461 mCachedProfileOwners = result.mProfileOwners 462 return 463 } catch (e: AdbParseException) { 464 if (e.adbOutput().contains("DUMP TIMEOUT") && retries-- > 0) { 465 // Sometimes this call times out - just retry 466 Log.e(LOG_TAG, "Dump timeout when filling cache, retrying", e) 467 } else { 468 throw NeneException("Error filling cache", e) 469 } 470 } catch (e: AdbException) { 471 throw NeneException("Error filling cache", e) 472 } 473 } 474 } 475 476 /** See [android.app.admin.DevicePolicyManager.getPolicyExemptApps]. */ 477 @Experimental 478 fun getPolicyExemptApps(): Set<String> { 479 TestApis.permissions().withPermission(CommonPermissions.MANAGE_DEVICE_ADMINS).use { 480 return devicePolicyManager.policyExemptApps 481 } 482 } 483 484 @Experimental 485 fun forceNetworkLogs() { 486 TestApis.permissions().withPermission( 487 CommonPermissions.FORCE_DEVICE_POLICY_MANAGER_LOGS 488 ).use { 489 val throttle = devicePolicyManager.forceNetworkLogs() 490 if (throttle == -1L) { 491 throw NeneException("Error forcing network logs: returned -1") 492 } 493 if (throttle == 0L) { 494 return 495 } 496 try { 497 Thread.sleep(throttle) 498 } catch (e: InterruptedException) { 499 throw NeneException("Error waiting for network log throttle", e) 500 } 501 forceNetworkLogs() 502 } 503 } 504 505 @Experimental 506 fun forceSecurityLogs() { 507 TestApis.permissions().withPermission( 508 CommonPermissions.FORCE_DEVICE_POLICY_MANAGER_LOGS 509 ).use { 510 val throttle = devicePolicyManager.forceSecurityLogs() 511 if (throttle == -1L) { 512 throw NeneException("Error forcing security logs: returned -1") 513 } 514 if (throttle == 0L) { 515 return 516 } 517 try { 518 Thread.sleep(throttle) 519 } catch (e: InterruptedException) { 520 throw NeneException("Error waiting for security log throttle", e) 521 } 522 forceSecurityLogs() 523 } 524 } 525 526 /** 527 * Sets the provided `packageName` as a device policy management role holder. 528 */ 529 @TargetApi(Build.VERSION_CODES.TIRAMISU) 530 @Experimental 531 @JvmOverloads 532 fun setDevicePolicyManagementRoleHolder( 533 pkg: Package, 534 user: UserReference = TestApis.users().instrumented() 535 ): RoleContext { 536 Versions.requireMinimumVersion(Build.VERSION_CODES.TIRAMISU) 537 if (!Versions.meetsMinimumSdkVersionRequirement(Versions.U)) { 538 if (TestApis.users().all().size > 1) { 539 throw NeneException( 540 "Could not set device policy management role holder as" + 541 " more than one user is on the device" 542 ) 543 } 544 } 545 if (nonTestNonPrecreatedUsersExist()) { 546 throw NeneException( 547 "Could not set device policy management role holder as" + 548 " non-test users already exist" 549 ) 550 } 551 TestApis.roles().setBypassingRoleQualification(true) 552 return pkg.setAsRoleHolder(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user) 553 } 554 555 private fun nonTestNonPrecreatedUsersExist(): Boolean { 556 val expectedPrecreatedUsers = if (TestApis.users().isHeadlessSystemUserMode) 2 else 1 557 return TestApis.users().all().stream() 558 .filter { u: UserReference -> !u.isForTesting } 559 .count() > expectedPrecreatedUsers 560 } 561 562 /** 563 * Unsets the provided `packageName` as a device policy management role holder. 564 */ 565 @TargetApi(Build.VERSION_CODES.TIRAMISU) 566 @Experimental 567 @JvmOverloads 568 fun unsetDevicePolicyManagementRoleHolder( 569 pkg: Package, 570 user: UserReference = TestApis.users().instrumented() 571 ) { 572 Versions.requireMinimumVersion(Build.VERSION_CODES.TIRAMISU) 573 pkg.removeAsRoleHolder(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user) 574 } 575 576 /** 577 * Returns true if the AutoTimeRequired policy is set to true for the given user. 578 */ 579 @JvmOverloads 580 @Experimental 581 fun autoTimeRequired(user: UserReference = TestApis.users().instrumented()) = 582 devicePolicyManager(user).autoTimeRequired 583 584 /** 585 * See `DevicePolicyManager#isNewUserDisclaimerAcknowledged`. 586 */ 587 @JvmOverloads 588 @Experimental 589 fun isNewUserDisclaimerAcknowledged( 590 user: UserReference = TestApis.users().instrumented() 591 ): Boolean = 592 TestApis.permissions().withPermission(CommonPermissions.INTERACT_ACROSS_USERS).use { 593 devicePolicyManager(user).isNewUserDisclaimerAcknowledged 594 } 595 596 /** 597 * Access APIs related to Device Policy resource overriding. 598 */ 599 @TargetApi(Build.VERSION_CODES.TIRAMISU) 600 fun resources(): DevicePolicyResources { 601 Versions.requireMinimumVersion(Build.VERSION_CODES.TIRAMISU) 602 return DevicePolicyResources.sInstance 603 } 604 605 /** 606 * Get active admins on the given user. 607 */ 608 @JvmOverloads 609 fun getActiveAdmins( 610 user: UserReference = TestApis.users().instrumented() 611 ): Set<ComponentReference> { 612 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL) 613 .use { 614 val activeAdmins = devicePolicyManager(user).activeAdmins ?: return setOf() 615 return activeAdmins.stream() 616 .map { component: ComponentName? -> ComponentReference(component) } 617 .collect( 618 Collectors.toSet() 619 ) 620 } 621 } 622 623 /** 624 * See 625 * [DevicePolicyManager.resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState]. 626 */ 627 @TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 628 fun resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() { 629 Versions.requireMinimumVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 630 TestApis.permissions().withPermission(CommonPermissions.MANAGE_ROLE_HOLDERS).use { 631 devicePolicyManager(TestApis.users().instrumented()) 632 .resetShouldAllowBypassingDevicePolicyManagementRoleQualificationState() 633 } 634 } 635 636 /** 637 * Set or check user restrictions. 638 */ 639 fun userRestrictions(user: UserHandle): UserRestrictions { 640 return userRestrictions(UserReference.of(user)) 641 } 642 643 /** 644 * Set or check user restrictions. 645 */ 646 @JvmOverloads 647 fun userRestrictions(user: UserReference = TestApis.users().instrumented()): UserRestrictions { 648 return UserRestrictions(user) 649 } 650 651 /** 652 * OEM-Set default cross profile packages. 653 */ 654 @Experimental 655 fun defaultCrossProfilePackages(): Set<Package> { 656 return devicePolicyManager.defaultCrossProfilePackages 657 .stream().map { TestApis.packages().find(it) } 658 .collect(Collectors.toSet()) 659 } 660 661 /** 662 * True if there is a Device Owner who can grant sensor permissions. 663 */ 664 @Experimental 665 fun canAdminGrantSensorsPermissions(): Boolean { 666 return if (!Versions.meetsMinimumSdkVersionRequirement(31)) { 667 true 668 } else { 669 devicePolicyManager.canAdminGrantSensorsPermissions() 670 } 671 } 672 673 /** 674 * @see DevicePolicyManager.getUserProvisioningState 675 */ 676 @Experimental 677 @JvmOverloads 678 fun getUserProvisioningState(user: UserReference = TestApis.users().instrumented()): Int = 679 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS) 680 .use { devicePolicyManager(user).userProvisioningState } 681 682 /** 683 * See [DevicePolicyManager.getPasswordExpirationTimeout]. 684 */ 685 @Experimental 686 @JvmOverloads 687 fun getPasswordExpirationTimeout(user: UserReference = TestApis.users().instrumented()): Long = 688 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS).use { 689 devicePolicyManager(user).getPasswordExpirationTimeout( /* admin= */null) 690 } 691 692 /** 693 * See [DevicePolicyManager.getMaximumTimeToLock]. 694 */ 695 @Experimental 696 @JvmOverloads 697 fun getMaximumTimeToLock(user: UserReference = TestApis.users().instrumented()): Long = 698 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS).use { 699 devicePolicyManager(user).getMaximumTimeToLock( /* admin= */null) 700 } 701 702 /** 703 * See [DevicePolicyManager.getRequiredStrongAuthTimeout]. 704 */ 705 @Experimental 706 @JvmOverloads 707 fun getRequiredStrongAuthTimeout(user: UserReference = TestApis.users().instrumented()): Long = 708 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS).use { 709 devicePolicyManager(user).getRequiredStrongAuthTimeout( /* admin= */null) 710 } 711 712 // TODO: Consider wrapping keyguard disabled features with a bedstead concept instead of flags 713 /** 714 * See [DevicePolicyManager.getKeyguardDisabledFeatures]. 715 */ 716 @Experimental 717 @JvmOverloads 718 fun getKeyguardDisabledFeatures(user: UserReference = TestApis.users().instrumented()): Int = 719 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS).use { 720 devicePolicyManager(user).getKeyguardDisabledFeatures( /* admin= */null) 721 } 722 723 /** 724 * Gets configuration for the `trustAgent` for all admins and `user`. 725 * 726 * 727 * See 728 * [DevicePolicyManager.getTrustAgentConfiguration]. 729 */ 730 @Experimental 731 @JvmOverloads 732 fun getTrustAgentConfiguration( 733 trustAgent: ComponentName, 734 user: UserReference = TestApis.users().instrumented() 735 ): Set<PersistableBundle> { 736 TestApis.permissions().withPermission(Manifest.permission.INTERACT_ACROSS_USERS).use { 737 val configurations = devicePolicyManager(user) 738 .getTrustAgentConfiguration( /* admin= */null, trustAgent) 739 return if (configurations == null) setOf() else java.util.Set.copyOf(configurations) 740 } 741 } 742 743 // TODO(276248451): Make user handle aware so it'll work cross-user 744 /** 745 * True if either this is the system user or the user is affiliated with a device owner on 746 * the device. 747 */ 748 @Experimental 749 @JvmOverloads 750 fun isAffiliated(user: UserReference = TestApis.users().instrumented()): Boolean = 751 devicePolicyManager(user).isAffiliatedUser 752 753 /** See [DevicePolicyManager#permittedInputMethods]. */ 754 // TODO: This doesn't currently work cross-user 755 @Experimental 756 fun getPermittedInputMethods(): List<String>? = 757 TestApis.permissions().withPermission(CommonPermissions.QUERY_ADMIN_POLICY) 758 .use { devicePolicyManager.permittedInputMethodsForCurrentUser } 759 760 /** 761 * Recalculate the "hasIncompatibleAccounts" cache inside DevicePolicyManager. 762 */ 763 @Experimental 764 fun calculateHasIncompatibleAccounts() { 765 if (!Versions.meetsMinimumSdkVersionRequirement(Versions.U)) { 766 // Nothing to calculate pre-U 767 return 768 } 769 TestApis.logcat() 770 .listen { it.contains("Finished calculating hasIncompatibleAccountsTask") } 771 .use { devicePolicyManager.calculateHasIncompatibleAccounts() } 772 } 773 774 /** 775 * Determine whether Bluetooth devices cannot access contacts on `user`. 776 * 777 * See `DevicePolicyManager#getBluetoothContactSharingDisabled(UserHandle)` 778 */ 779 @JvmOverloads 780 @SuppressLint("NewApi") 781 fun getBluetoothContactSharingDisabled( 782 user: UserReference = TestApis.users().instrumented() 783 ): Boolean = 784 devicePolicyManager.getBluetoothContactSharingDisabled(user.userHandle()) 785 786 /** See [DevicePolicyManager.getPermittedAccessibilityServices] */ 787 @Experimental 788 @JvmOverloads 789 fun getPermittedAccessibilityServices( 790 user: UserReference = TestApis.users().instrumented() 791 ): Set<Package>? = 792 TestApis.permissions().withPermission( 793 Manifest.permission.INTERACT_ACROSS_USERS, 794 CommonPermissions.QUERY_ADMIN_POLICY 795 ).use { 796 devicePolicyManager.getPermittedAccessibilityServices( 797 user.id() 798 )?.stream() 799 ?.map { packageName: String? -> TestApis.packages().find(packageName) } 800 ?.collect(Collectors.toSet()) 801 } 802 803 /** See [DevicePolicyManager.getStorageEncryptionStatus] */ 804 fun getStorageEncryptionStatus(): Int = 805 devicePolicyManager.storageEncryptionStatus 806 807 /** See [DevicePolicyManager.createAdminSupportIntent] */ 808 @Experimental 809 fun createAdminSupportIntent(restriction: String): Intent? = 810 devicePolicyManager.createAdminSupportIntent(restriction) 811 812 /** See [DevicePolicyManager.isFactoryResetProtectionPolicySupported] */ 813 fun isFactoryResetProtectionPolicySupported(): Boolean = 814 devicePolicyManager.isFactoryResetProtectionPolicySupported 815 816 @Experimental 817 fun notifyPendingSystemUpdate(updateReceivedTime: Long, isSecurityPatch: Boolean? = null) { 818 TestApis.permissions().withPermission(NOTIFY_PENDING_SYSTEM_UPDATE).use { 819 if (isSecurityPatch == null) { 820 devicePolicyManager.notifyPendingSystemUpdate(updateReceivedTime) 821 } else { 822 devicePolicyManager.notifyPendingSystemUpdate(updateReceivedTime, isSecurityPatch) 823 } 824 } 825 } 826 827 /** See [DevicePolicyManager#getScreenCaptureDisabled]. */ 828 @Experimental 829 @JvmOverloads 830 fun isScreenCaptureDisabled(user: UserReference = TestApis.users().instrumented()) = 831 devicePolicyManager(user).getScreenCaptureDisabled(/* admin = */ null) 832 833 /** See [DevicePolicyManager#isInputMethodSetByOwner]. */ 834 @Experimental 835 @JvmOverloads 836 fun isCurrentInputMethodSetByOwner(user: UserReference = TestApis.users().instrumented()) = 837 TestApis.permissions().withPermission(QUERY_ADMIN_POLICY).use { 838 devicePolicyManager(user).isCurrentInputMethodSetByOwner 839 } 840 841 /** See [DevicePolicyManager#getOwnerInstalledCaCerts]. */ 842 @Experimental 843 fun getOwnerInstalledCaCerts() = getOwnerInstalledCaCerts(TestApis.users().instrumented()) 844 845 /** See [DevicePolicyManager#getOwnerInstalledCaCerts]. */ 846 @Experimental 847 fun getOwnerInstalledCaCerts(user: UserReference) = 848 TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL, QUERY_ADMIN_POLICY).use { 849 devicePolicyManager(user).getOwnerInstalledCaCerts(user.userHandle()) 850 } 851 852 /** See [DevicePolicyManager#getNearbyNotificationStreamingPolicy]. */ 853 @JvmOverloads 854 @Experimental 855 @TargetApi(Build.VERSION_CODES.S) 856 fun getNearbyNotificationStreamingPolicy( 857 user: UserReference = TestApis.users().instrumented() 858 ): NearbyNotificationStreamingPolicy { 859 return TestApis.permissions().withPermission( 860 INTERACT_ACROSS_USERS_FULL, 861 READ_NEARBY_STREAMING_POLICY 862 ).use { 863 val intDef = devicePolicyManager(user).nearbyNotificationStreamingPolicy 864 NearbyNotificationStreamingPolicy.entries.first { it.intDef == intDef } 865 } 866 } 867 868 /** See [DevicePolicyManager#setMaxPolicyStorageLimit]. */ 869 @Experimental 870 fun setMaxPolicySize(limitBytes: Int) = 871 TestApis.permissions().withPermission(MANAGE_DEVICE_POLICY_STORAGE_LIMIT).use { 872 devicePolicyManager.forceSetMaxPolicyStorageLimit(limitBytes) 873 } 874 875 /** See [DevicePolicyManager#getPolicySizeForAdmin]. */ 876 @Experimental 877 fun getPolicySizeForAdmin(admin: EnforcingAdmin): Int = 878 TestApis.permissions().withPermission(MANAGE_DEVICE_POLICY_STORAGE_LIMIT).use { 879 devicePolicyManager.getPolicySizeForAdmin(admin) 880 } 881 882 /** Get string dump of device policy state. */ 883 fun dump(): String = 884 ShellCommand.builder("dumpsys device_policy").validate(String::isNotEmpty).execute() 885 886 /** Returns true if device can control UsbDataSignaling. */ 887 @TargetApi(Build.VERSION_CODES.S) 888 fun canUsbDataSignalingBeDisabled(): Boolean { 889 return devicePolicyManager.canUsbDataSignalingBeDisabled() 890 } 891 892 enum class NearbyNotificationStreamingPolicy(val intDef: Int) { 893 NotManaged(0), 894 Disabled(1), 895 Enabled(2), 896 SameManagedAccountOnly(3) 897 } 898 899 private const val LOG_TAG = "DevicePolicy" 900 private const val ONE_TIME_SAFETY_CHECKER_SELF_DESTRUCT_TIMEOUT_MS: Long = 10_000L 901 902 private val devicePolicyManager: DevicePolicyManager by lazy { TestApis.context().instrumentedContext() 903 .getSystemService(DevicePolicyManager::class.java)!! } 904 } 905