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