1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.permissioncontroller.tests.mocking.permission.utils
18 
19 import android.Manifest
20 import android.app.ActivityManager
21 import android.app.AppOpsManager
22 import android.app.AppOpsManager.MODE_ALLOWED
23 import android.app.AppOpsManager.MODE_FOREGROUND
24 import android.app.AppOpsManager.MODE_IGNORED
25 import android.app.AppOpsManager.permissionToOp
26 import android.app.Application
27 import android.content.Context
28 import android.content.pm.PackageManager
29 import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED
30 import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME
31 import android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
32 import android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
33 import android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
34 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED
35 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
36 import android.content.pm.PackageManager.PERMISSION_DENIED
37 import android.content.pm.PackageManager.PERMISSION_GRANTED
38 import android.content.pm.PermissionInfo
39 import android.content.pm.PermissionInfo.PROTECTION_FLAG_INSTANT
40 import android.content.pm.PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY
41 import android.os.Build
42 import android.os.UserHandle
43 import android.permission.PermissionManager
44 import androidx.test.ext.junit.runners.AndroidJUnit4
45 import com.android.modules.utils.build.SdkLevel
46 import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
47 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
48 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermGroupInfo
49 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
50 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
51 import com.android.permissioncontroller.permission.utils.ContextCompat
52 import com.android.permissioncontroller.permission.utils.KotlinUtils
53 import com.google.common.truth.Truth.assertThat
54 import com.google.common.truth.Truth.assertWithMessage
55 import org.junit.Assume.assumeNotNull
56 import org.junit.Assume.assumeTrue
57 import org.junit.BeforeClass
58 import org.junit.Test
59 import org.junit.runner.RunWith
60 import org.mockito.ArgumentMatchers.anyInt
61 import org.mockito.ArgumentMatchers.anyString
62 import org.mockito.ArgumentMatchers.eq
63 import org.mockito.ArgumentMatchers.nullable
64 import org.mockito.Mock
65 import org.mockito.Mockito.mock
66 import org.mockito.Mockito.never
67 import org.mockito.Mockito.verify
68 import org.mockito.Mockito.`when`
69 
70 private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK =
71     FLAG_PERMISSION_USER_SET or
72         FLAG_PERMISSION_USER_FIXED or
73         FLAG_PERMISSION_ONE_TIME or
74         FLAG_PERMISSION_REVOKED_COMPAT or
75         FLAG_PERMISSION_ONE_TIME or
76         FLAG_PERMISSION_REVIEW_REQUIRED or
77         FLAG_PERMISSION_AUTO_REVOKED
78 
79 /**
80  * A suite of unit tests to test the granting and revoking of permissions. Note- does not currently
81  * test the Location Access Check.
82  */
83 @RunWith(AndroidJUnit4::class)
84 class GrantRevokeTests {
85 
86     companion object {
87         private const val PERM_GROUP_NAME = Manifest.permission_group.LOCATION
88         private const val FG_PERM_NAME = Manifest.permission.ACCESS_COARSE_LOCATION
89         private const val FG_PERM_2_NAME = Manifest.permission.ACCESS_FINE_LOCATION
90         private const val FG_PERM_NAME_NO_APP_OP = "android.permission.permWithNoAppOp"
91         private const val BG_PERM_NAME = Manifest.permission.ACCESS_BACKGROUND_LOCATION
92         private const val TEST_PACKAGE_NAME = "android.permission.cts.testapp"
93         private const val TEST_UID = 1
94         private val TEST_USER = UserHandle.getUserHandleForUid(TEST_UID)
95         private const val NO_FLAGS = 0
96         private val FG_PERM_NAMES = listOf(FG_PERM_NAME, FG_PERM_2_NAME, FG_PERM_NAME_NO_APP_OP)
97         private val OP_NAME = permissionToOp(FG_PERM_NAME)!!
98         private val OP_2_NAME = permissionToOp(FG_PERM_2_NAME)!!
99 
100         @BeforeClass
101         @JvmStatic
checkAppOpsNotNullAndDistinctnull102         fun checkAppOpsNotNullAndDistinct() {
103             assumeNotNull(OP_NAME, OP_2_NAME)
104             assumeTrue(OP_NAME != OP_2_NAME)
105         }
106     }
107 
108     @Mock val app: Application = mock(Application::class.java)
109 
110     @Mock val context: Context = mock(Context::class.java)
111 
112     /**
113      * Create a mock Application object, with a mock packageManager, AppOpsManager, and
114      * ActivityManager.
115      *
116      * @return The mocked Application object
117      */
resetMockAppStatenull118     private fun resetMockAppState() {
119         `when`(app.packageManager).thenReturn(mock(PackageManager::class.java))
120 
121         val aom: AppOpsManager = mock(AppOpsManager::class.java)
122 
123         if (SdkLevel.isAtLeastU()) {
124             `when`(context.deviceId).thenReturn(ContextCompat.DEVICE_ID_DEFAULT)
125         }
126         `when`(context.packageManager).thenReturn(mock(PackageManager::class.java))
127         `when`(context.getSystemService(PermissionManager::class.java))
128             .thenReturn(mock(PermissionManager::class.java))
129         // Return an invalid app op state, so setOpMode will always attempt to change the op state
130         `when`(aom.unsafeCheckOpRaw(anyString(), anyInt(), nullable(String::class.java)))
131             .thenReturn(-1)
132         `when`(app.getSystemService(AppOpsManager::class.java)).thenReturn(aom)
133 
134         `when`(app.getSystemService(ActivityManager::class.java))
135             .thenReturn(mock(ActivityManager::class.java))
136 
137         `when`(app.getSystemService(PermissionManager::class.java))
138             .thenReturn(mock(PermissionManager::class.java))
139         `when`(app.applicationContext).thenReturn(context)
140     }
141 
142     /**
143      * Create a LightPackageInfo object with a particular set of properties
144      *
145      * @param perms The (name -> permissionInfo) of the permissions requested by the app
146      * @param isPreMApp Whether this app targets pre-M
147      * @param isInstantApp {@code true} iff this is an instant app
148      */
createMockPackagenull149     private fun createMockPackage(
150         perms: Map<String, Boolean>,
151         isPreMApp: Boolean = false,
152         isInstantApp: Boolean = false
153     ): LightPackageInfo {
154         val permNames = mutableListOf<String>()
155         val permFlags = mutableListOf<Int>()
156         for ((permName, isGranted) in perms) {
157             permNames.add(permName)
158             permFlags.add(
159                 if (isGranted) {
160                     PERMISSION_GRANTED
161                 } else {
162                     PERMISSION_DENIED
163                 }
164             )
165         }
166 
167         return LightPackageInfo(
168             TEST_PACKAGE_NAME,
169             listOf(),
170             permNames,
171             permFlags,
172             TEST_UID,
173             if (isPreMApp) {
174                 Build.VERSION_CODES.LOLLIPOP
175             } else {
176                 Build.VERSION_CODES.R
177             },
178             isInstantApp,
179             isInstantApp,
180             0,
181             0L,
182             0L,
183             false,
184             emptyMap(),
185             ContextCompat.DEVICE_ID_DEFAULT
186         )
187     }
188 
189     /**
190      * Create a LightPermission object with a particular set of properties
191      *
192      * @param pkg Package requesting the permission
193      * @param permName The name of the permission
194      * @param granted Whether the permission is granted (should be false if the permission is compat
195      *   revoked)
196      * @param backgroundPerm The name of this permission's background permission, if there is one
197      * @param foregroundPerms The names of this permission's foreground permissions, if there are
198      *   any
199      * @param flags The system permission flags of this permission
200      * @param permInfoProtectionFlags The flags that the PermissionInfo object has (accessed by
201      *   PermissionInfo.getProtectionFlags)
202      */
createMockPermnull203     private fun createMockPerm(
204         pkgInfo: LightPackageInfo,
205         permName: String,
206         backgroundPerm: String? = null,
207         foregroundPerms: List<String>? = null,
208         flags: Int = NO_FLAGS,
209         permInfoProtectionFlags: Int = 0
210     ): LightPermission {
211         val permInfo =
212             LightPermInfo(
213                 permName,
214                 TEST_PACKAGE_NAME,
215                 PERM_GROUP_NAME,
216                 backgroundPerm,
217                 PermissionInfo.PROTECTION_DANGEROUS,
218                 permInfoProtectionFlags,
219                 0
220             )
221         return LightPermission(
222             pkgInfo,
223             permInfo,
224             pkgInfo.requestedPermissionsFlags[pkgInfo.requestedPermissions.indexOf(permName)] ==
225                 PERMISSION_GRANTED,
226             flags,
227             foregroundPerms
228         )
229     }
230 
231     /**
232      * Create a LightAppPermGroup with a particular set of properties.
233      *
234      * @param pkg Package requesting the permission
235      * @param perms The map of perm name to LightPermission (should be created with @createMockPerm)
236      */
createMockGroupnull237     private fun createMockGroup(
238         pkgInfo: LightPackageInfo,
239         perms: Map<String, LightPermission> = emptyMap()
240     ): LightAppPermGroup {
241         val pGi = LightPermGroupInfo(PERM_GROUP_NAME, TEST_PACKAGE_NAME, 0, 0, 0, false)
242         return LightAppPermGroup(pkgInfo, pGi, perms, false, false)
243     }
244 
245     /**
246      * Create a list of strings which usefully states which flags are set in a group of flags. Only
247      * checks for flags relevant to granting and revoking (so, for instance, policy fixed is not
248      * checked).
249      *
250      * @param flags The flags to check
251      * @return a list of strings, representing which flags have been set
252      */
flagsToStringnull253     private fun flagsToString(flags: Int): List<String> {
254         val flagStrings = mutableListOf<String>()
255         if (flags and FLAG_PERMISSION_USER_SET != 0) {
256             flagStrings.add("USER_SET")
257         }
258         if (flags and FLAG_PERMISSION_USER_FIXED != 0) {
259             flagStrings.add("USER_FIXED")
260         }
261         if (flags and FLAG_PERMISSION_SYSTEM_FIXED != 0) {
262             flagStrings.add("SYSTEM_FIXED")
263         }
264         if (flags and FLAG_PERMISSION_REVOKED_COMPAT != 0) {
265             flagStrings.add("REVOKED_COMPAT")
266         }
267         if (flags and FLAG_PERMISSION_REVIEW_REQUIRED != 0) {
268             flagStrings.add("REVIEW_REQUIRED")
269         }
270         if (flags and FLAG_PERMISSION_ONE_TIME != 0) {
271             flagStrings.add("ONE_TIME")
272         }
273         return flagStrings
274     }
275 
276     /**
277      * Assert that the permissions of the given group match the expected state
278      *
279      * @param groupToCheck The LightAppPermGroup whose permissions we are checking
280      * @param expectedState A map <permission name, grant state and permission flags pair>
281      */
assertGroupPermStatenull282     private fun assertGroupPermState(
283         groupToCheck: LightAppPermGroup,
284         expectedState: Map<String, Pair<Boolean, Int>>
285     ) {
286         val perms = groupToCheck.permissions
287 
288         assertThat(perms.keys).isEqualTo(expectedState.keys)
289 
290         for ((permName, state) in expectedState) {
291             val granted = state.first
292             val flags = state.second
293 
294             assertWithMessage("permission $permName grant state incorrect")
295                 .that(perms[permName]?.isGrantedIncludingAppOp)
296                 .isEqualTo(granted)
297 
298             val actualFlags = perms[permName]!!.flags
299             assertWithMessage(
300                     "permission $permName flags incorrect, expected" +
301                         "${flagsToString(flags)}; got ${flagsToString(actualFlags)}"
302                 )
303                 .that(perms[permName]?.flags)
304                 .isEqualTo(flags)
305         }
306     }
307 
308     /**
309      * Verify that permission state was propagated to the system. Verify that grant or revoke were
310      * called, if applicable, or verify they weren't. Verify that we have set flags correctly, if
311      * applicable, or verify flags were not set.
312      *
313      * @param permName The name of the permission to verify
314      * @param expectPermChange Whether or not a permission grant or revoke was expected. If false,
315      *   verify neither grant nor revoke were called
316      * @param expectPermGranted If a permission change was expected, verify that the permission was
317      *   set to granted (if true) or revoked (if false)
318      * @param expectedFlags The flags that the system should have set the permission to have
319      * @param originalFlags The flags the permission originally had. Used to ensure the correct flag
320      *   mask was used
321      */
verifyPermissionStatenull322     private fun verifyPermissionState(
323         permName: String,
324         expectPermChange: Boolean,
325         expectPermGranted: Boolean = true,
326         expectedFlags: Int = NO_FLAGS,
327         originalFlags: Int = NO_FLAGS
328     ) {
329         val pm = context.packageManager
330         if (expectPermChange) {
331             if (expectPermGranted) {
332                 verify(pm).grantRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
333             } else {
334                 verify(pm).revokeRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
335             }
336         } else {
337             verify(pm, never()).grantRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
338             verify(pm, never()).revokeRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
339         }
340 
341         if (expectedFlags != originalFlags) {
342             verify(pm)
343                 .updatePermissionFlags(
344                     permName,
345                     TEST_PACKAGE_NAME,
346                     PERMISSION_CONTROLLER_CHANGED_FLAG_MASK,
347                     expectedFlags,
348                     TEST_USER
349                 )
350         } else {
351             verify(pm, never())
352                 .updatePermissionFlags(
353                     eq(permName),
354                     eq(TEST_PACKAGE_NAME),
355                     anyInt(),
356                     anyInt(),
357                     eq(TEST_USER)
358                 )
359         }
360     }
361 
362     /**
363      * Verify that app op state was propagated to the system. Verify that setUidMode was called, if
364      * applicable, or verify it wasn't.
365      *
366      * @param appOpName The name of the app op to check
367      * @param expectAppOpSet Whether an app op change was expected. If false, verify setUidMode was
368      *   not called
369      * @param expectedMode If a change was expected, the mode the app op should be set to
370      */
verifyAppOpStatenull371     private fun verifyAppOpState(
372         appOpName: String,
373         expectAppOpSet: Boolean,
374         expectedMode: Int = MODE_IGNORED
375     ) {
376         val aom = app.getSystemService(AppOpsManager::class.java)
377         if (expectAppOpSet) {
378             verify(aom).setUidMode(appOpName, TEST_UID, expectedMode)
379         } else {
380             verify(aom, never()).setUidMode(eq(appOpName), eq(TEST_UID), anyInt())
381         }
382     }
383 
384     /**
385      * Verify that the test app either was or was not killed.
386      *
387      * @param shouldBeKilled Whether or not the app should have been killed
388      */
verifyAppKillStatenull389     private fun verifyAppKillState(shouldBeKilled: Boolean) {
390         val am = app.getSystemService(ActivityManager::class.java)
391         if (shouldBeKilled) {
392             verify(am).killUid(eq(TEST_UID), anyString())
393         } else {
394             verify(am, never()).killUid(eq(TEST_UID), anyString())
395         }
396     }
397 
398     /**
399      * Test the granting of a single foreground permission. The permission and its app op should be
400      * granted.
401      */
402     @Test
grantOnePermTestnull403     fun grantOnePermTest() {
404         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
405         val perms = mutableMapOf<String, LightPermission>()
406         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
407         val group = createMockGroup(pkg, perms)
408         resetMockAppState()
409 
410         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
411 
412         val newFlags = FLAG_PERMISSION_USER_SET
413         verifyPermissionState(
414             permName = FG_PERM_NAME,
415             expectPermChange = true,
416             expectPermGranted = true,
417             expectedFlags = newFlags
418         )
419         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
420         verifyAppKillState(shouldBeKilled = false)
421 
422         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
423         assertGroupPermState(newGroup, expectedState)
424     }
425 
426     /**
427      * Test the granting of two foreground permissions, one with a background permission. The
428      * permissions and app ops should be granted, and the permissions marked user set. The second
429      * app op should be set to foreground mode.
430      */
431     @Test
grantTwoPermTestnull432     fun grantTwoPermTest() {
433         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, FG_PERM_2_NAME to false))
434         val perms = mutableMapOf<String, LightPermission>()
435         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
436         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, BG_PERM_NAME)
437         val group = createMockGroup(pkg, perms)
438         resetMockAppState()
439 
440         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
441 
442         val newFlags = FLAG_PERMISSION_USER_SET
443         verifyPermissionState(
444             permName = FG_PERM_NAME,
445             expectPermChange = true,
446             expectPermGranted = true,
447             expectedFlags = newFlags
448         )
449         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
450         verifyPermissionState(
451             permName = FG_PERM_2_NAME,
452             expectPermChange = true,
453             expectPermGranted = true,
454             expectedFlags = newFlags
455         )
456         verifyAppOpState(
457             appOpName = OP_2_NAME,
458             expectAppOpSet = true,
459             expectedMode = MODE_FOREGROUND
460         )
461         verifyAppKillState(shouldBeKilled = false)
462 
463         val expectedState =
464             mutableMapOf(FG_PERM_NAME to (true to newFlags), FG_PERM_2_NAME to (true to newFlags))
465         assertGroupPermState(newGroup, expectedState)
466     }
467 
468     /**
469      * Test the granting of a permission with no app op. No app ops should change, but the
470      * permission should be granted
471      */
472     @Test
grantNoAppOpPermnull473     fun grantNoAppOpPerm() {
474         val pkg = createMockPackage(mapOf(FG_PERM_NAME_NO_APP_OP to false))
475         val perms = mutableMapOf<String, LightPermission>()
476         perms[FG_PERM_NAME_NO_APP_OP] = createMockPerm(pkg, FG_PERM_NAME_NO_APP_OP)
477         val group = createMockGroup(pkg, perms)
478         resetMockAppState()
479 
480         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
481 
482         val newFlags = FLAG_PERMISSION_USER_SET
483         verifyPermissionState(
484             permName = FG_PERM_NAME_NO_APP_OP,
485             expectPermChange = true,
486             expectPermGranted = true,
487             expectedFlags = newFlags
488         )
489         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
490         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
491         verifyAppKillState(shouldBeKilled = false)
492 
493         val expectedState = mutableMapOf(FG_PERM_NAME_NO_APP_OP to (true to newFlags))
494         assertGroupPermState(newGroup, expectedState)
495     }
496 
497     /**
498      * Test that granting a background permission grants the background permission, and allows the
499      * app ops of its foreground permissions, but does not grant the foreground permission itself.
500      */
501     @Test
grantBgPermTestnull502     fun grantBgPermTest() {
503         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to false))
504         val perms = mutableMapOf<String, LightPermission>()
505         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
506         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
507         val group = createMockGroup(pkg, perms)
508         resetMockAppState()
509 
510         val newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, group)
511 
512         val newFlags = FLAG_PERMISSION_USER_SET
513         verifyPermissionState(
514             permName = BG_PERM_NAME,
515             expectPermChange = true,
516             expectPermGranted = true,
517             expectedFlags = newFlags
518         )
519         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
520         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
521         verifyAppKillState(shouldBeKilled = false)
522 
523         val expectedState =
524             mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (true to newFlags))
525         assertGroupPermState(newGroup, expectedState)
526     }
527 
528     /**
529      * Test granting a foreground permission, then a background. After the foreground permission is
530      * granted, the app op should be in foreground mode. After the background permission, it should
531      * be fully allowed.
532      */
533     @Test
grantBgAndFgPermTestnull534     fun grantBgAndFgPermTest() {
535         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
536         val perms = mutableMapOf<String, LightPermission>()
537         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
538         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
539         val group = createMockGroup(pkg, perms)
540         resetMockAppState()
541 
542         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
543 
544         val newFlags = FLAG_PERMISSION_USER_SET
545         verifyPermissionState(
546             permName = FG_PERM_NAME,
547             expectPermChange = true,
548             expectPermGranted = true,
549             expectedFlags = newFlags
550         )
551         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false)
552         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
553         verifyAppKillState(shouldBeKilled = false)
554 
555         val expectedState =
556             mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to NO_FLAGS))
557         assertGroupPermState(newGroup, expectedState)
558 
559         resetMockAppState()
560         val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
561 
562         verifyPermissionState(
563             permName = BG_PERM_NAME,
564             expectPermChange = true,
565             expectPermGranted = true,
566             expectedFlags = newFlags
567         )
568         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
569         verifyAppKillState(shouldBeKilled = false)
570 
571         val expectedState2 =
572             mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (true to newFlags))
573         assertGroupPermState(newGroup2, expectedState2)
574     }
575 
576     /**
577      * Test the granting of a permission which has been auto-revoked along with others in the group.
578      * Granting one permission should also clear the [FLAG_PERMISSION_AUTO_REVOKED] flag on others
579      * in the group.
580      */
581     @Test
grantAutoRevokedPermInGroupTestnull582     fun grantAutoRevokedPermInGroupTest() {
583         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
584         val perms = mutableMapOf<String, LightPermission>()
585         val origBgFlags = FLAG_PERMISSION_AUTO_REVOKED
586         perms[FG_PERM_NAME] =
587             createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME, null, FLAG_PERMISSION_AUTO_REVOKED)
588         perms[BG_PERM_NAME] =
589             createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME), origBgFlags)
590         val group = createMockGroup(pkg, perms)
591         resetMockAppState()
592 
593         KotlinUtils.grantForegroundRuntimePermissions(app, group)
594 
595         val newFlags = FLAG_PERMISSION_USER_SET
596         verifyPermissionState(
597             permName = FG_PERM_NAME,
598             expectPermChange = true,
599             expectPermGranted = true,
600             expectedFlags = newFlags
601         )
602         verifyPermissionState(
603             permName = BG_PERM_NAME,
604             expectPermChange = false,
605             expectedFlags = NO_FLAGS,
606             originalFlags = origBgFlags
607         )
608     }
609 
610     /**
611      * Test granting a group with a foreground permission that is system fixed, and another that
612      * isn't. The system fixed permission should not change.
613      */
614     @Test
grantSystemFixedTestnull615     fun grantSystemFixedTest() {
616         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, FG_PERM_2_NAME to false))
617         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
618         val perms = mutableMapOf<String, LightPermission>()
619         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
620         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, flags = permFlags)
621         val group = createMockGroup(pkg, perms)
622         resetMockAppState()
623 
624         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
625 
626         val newFlags = FLAG_PERMISSION_USER_SET
627         verifyPermissionState(
628             permName = FG_PERM_NAME,
629             expectPermChange = true,
630             expectPermGranted = true,
631             expectedFlags = newFlags
632         )
633         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
634         verifyPermissionState(
635             permName = FG_PERM_2_NAME,
636             expectPermChange = false,
637             expectedFlags = permFlags,
638             originalFlags = permFlags
639         )
640         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
641         verifyAppKillState(shouldBeKilled = false)
642 
643         val expectedState =
644             mutableMapOf(FG_PERM_NAME to (true to newFlags), FG_PERM_2_NAME to (false to permFlags))
645         assertGroupPermState(newGroup, expectedState)
646     }
647 
648     /**
649      * Test granting a group with a background permission that is system fixed, and a background
650      * permission that isn't. The system fixed permission should not change.
651      */
652     @Test
grantBgSystemFixedTestnull653     fun grantBgSystemFixedTest() {
654         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
655         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
656         val perms = mutableMapOf<String, LightPermission>()
657         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
658         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, FG_PERM_NAMES, permFlags)
659         val group = createMockGroup(pkg, perms)
660         resetMockAppState()
661 
662         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
663 
664         val newFlags = FLAG_PERMISSION_USER_SET
665         verifyPermissionState(
666             permName = FG_PERM_NAME,
667             expectPermChange = true,
668             expectPermGranted = true,
669             expectedFlags = newFlags
670         )
671         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
672         verifyAppKillState(shouldBeKilled = false)
673 
674         var expectedState =
675             mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to permFlags))
676         assertGroupPermState(newGroup, expectedState)
677 
678         resetMockAppState()
679         val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
680 
681         verifyPermissionState(
682             permName = BG_PERM_NAME,
683             expectPermChange = false,
684             expectedFlags = permFlags,
685             originalFlags = permFlags
686         )
687         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
688         verifyAppKillState(shouldBeKilled = false)
689 
690         expectedState =
691             mutableMapOf(FG_PERM_NAME to (true to newFlags), BG_PERM_NAME to (false to permFlags))
692         assertGroupPermState(newGroup2, expectedState)
693     }
694 
695     /**
696      * Test granting a one time granted permission. The permission should still be granted, but no
697      * longer be one time.
698      */
699     @Test
grantOneTimeTestnull700     fun grantOneTimeTest() {
701         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
702         val oldFlags = FLAG_PERMISSION_ONE_TIME
703         val perms = mutableMapOf<String, LightPermission>()
704         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
705         val group = createMockGroup(pkg, perms)
706         resetMockAppState()
707 
708         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
709 
710         val newFlags = FLAG_PERMISSION_USER_SET
711         verifyPermissionState(
712             permName = FG_PERM_NAME,
713             expectPermChange = false,
714             expectedFlags = newFlags,
715             originalFlags = oldFlags
716         )
717         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
718         verifyAppKillState(shouldBeKilled = false)
719 
720         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
721         assertGroupPermState(newGroup, expectedState)
722     }
723 
724     /**
725      * Test granting a compat revoked (permission granted, app op denied) permission. The app op
726      * should be allowed, as should the permission. The app should also be killed.
727      */
728     @Test
grantPreMAppTestnull729     fun grantPreMAppTest() {
730         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isPreMApp = true)
731         val oldFlags = FLAG_PERMISSION_REVOKED_COMPAT
732         val perms = mutableMapOf<String, LightPermission>()
733         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
734         val group = createMockGroup(pkg, perms)
735         resetMockAppState()
736 
737         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
738         val newFlags = FLAG_PERMISSION_USER_SET
739         verifyPermissionState(
740             permName = FG_PERM_NAME,
741             expectPermChange = false,
742             expectedFlags = newFlags,
743             originalFlags = oldFlags
744         )
745         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
746         verifyAppKillState(shouldBeKilled = true)
747 
748         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
749         assertGroupPermState(newGroup, expectedState)
750     }
751 
752     /**
753      * Test the granting of a single foreground permission for a Pre M app. Nothing should change,
754      * and the app should not be killed
755      */
756     @Test
grantAlreadyGrantedPreMTestnull757     fun grantAlreadyGrantedPreMTest() {
758         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
759         val perms = mutableMapOf<String, LightPermission>()
760         val flags = FLAG_PERMISSION_USER_SET
761         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = flags)
762         val group = createMockGroup(pkg, perms)
763         resetMockAppState()
764         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
765 
766         verifyPermissionState(
767             permName = FG_PERM_NAME,
768             expectPermChange = false,
769             expectedFlags = flags,
770             originalFlags = flags
771         )
772         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
773         verifyAppKillState(shouldBeKilled = false)
774 
775         val expectedState = mutableMapOf(FG_PERM_NAME to (true to flags))
776         assertGroupPermState(newGroup, expectedState)
777     }
778 
779     /** Test that an instant app cannot have regular (non-instant) permission granted. */
780     @Test
cantGrantInstantAppStandardPermTestnull781     fun cantGrantInstantAppStandardPermTest() {
782         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
783         val perms = mutableMapOf<String, LightPermission>()
784         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
785         val group = createMockGroup(pkg, perms)
786         resetMockAppState()
787 
788         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
789 
790         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
791         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
792         verifyAppKillState(shouldBeKilled = false)
793 
794         val expectedState = mutableMapOf(FG_PERM_NAME to (false to NO_FLAGS))
795         assertGroupPermState(newGroup, expectedState)
796     }
797 
798     /**
799      * Test that a pre-M app (pre runtime permissions) can't have a runtime only permission granted.
800      */
801     @Test
cantGrantPreRuntimeAppWithRuntimeOnlyPermTestnull802     fun cantGrantPreRuntimeAppWithRuntimeOnlyPermTest() {
803         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isPreMApp = true)
804         val perms = mutableMapOf<String, LightPermission>()
805         perms[FG_PERM_NAME] =
806             createMockPerm(
807                 pkg,
808                 FG_PERM_NAME,
809                 permInfoProtectionFlags = PROTECTION_FLAG_RUNTIME_ONLY
810             )
811         val group = createMockGroup(pkg, perms)
812         resetMockAppState()
813 
814         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
815 
816         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
817         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
818         verifyAppKillState(shouldBeKilled = false)
819 
820         val expectedState = mutableMapOf(FG_PERM_NAME to (false to NO_FLAGS))
821         assertGroupPermState(newGroup, expectedState)
822     }
823 
824     /** Test that an instant package can have an instant permission granted. */
825     @Test
grantInstantAppInstantPermTestnull826     fun grantInstantAppInstantPermTest() {
827         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
828         val perms = mutableMapOf<String, LightPermission>()
829         perms[FG_PERM_NAME] =
830             createMockPerm(pkg, FG_PERM_NAME, permInfoProtectionFlags = PROTECTION_FLAG_INSTANT)
831         val group = createMockGroup(pkg, perms)
832         resetMockAppState()
833 
834         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
835 
836         val newFlags = FLAG_PERMISSION_USER_SET
837         verifyPermissionState(
838             permName = FG_PERM_NAME,
839             expectPermChange = true,
840             expectPermGranted = true,
841             expectedFlags = newFlags
842         )
843         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
844         verifyAppKillState(shouldBeKilled = false)
845 
846         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
847         assertGroupPermState(newGroup, expectedState)
848     }
849 
850     /** Test that granting a permission clears the user fixed and review required flags. */
851     @Test
grantClearsUserFixedAndReviewRequirednull852     fun grantClearsUserFixedAndReviewRequired() {
853         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
854         val oldFlags = FLAG_PERMISSION_USER_FIXED or FLAG_PERMISSION_REVIEW_REQUIRED
855         val perms = mutableMapOf<String, LightPermission>()
856         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
857         val group = createMockGroup(pkg, perms)
858         resetMockAppState()
859         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
860 
861         val newFlags = FLAG_PERMISSION_USER_SET
862         verifyPermissionState(
863             permName = FG_PERM_NAME,
864             expectPermChange = false,
865             expectedFlags = newFlags,
866             originalFlags = oldFlags
867         )
868         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
869         verifyAppKillState(shouldBeKilled = false)
870 
871         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
872         assertGroupPermState(newGroup, expectedState)
873     }
874 
875     /** Test revoking one foreground permission. The permission and app op should be revoked. */
876     @Test
revokeOnePermTestnull877     fun revokeOnePermTest() {
878         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
879         val perms = mutableMapOf<String, LightPermission>()
880         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
881         val group = createMockGroup(pkg, perms)
882         resetMockAppState()
883 
884         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
885 
886         val newFlags = FLAG_PERMISSION_USER_SET
887         verifyPermissionState(
888             permName = FG_PERM_NAME,
889             expectPermChange = true,
890             expectPermGranted = false,
891             expectedFlags = newFlags
892         )
893         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
894         verifyAppKillState(shouldBeKilled = false)
895 
896         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
897         assertGroupPermState(newGroup, expectedState)
898     }
899 
900     /** Test revoking two foreground permissions. Both permissions and app ops should be revoked. */
901     @Test
revokeTwoPermTestnull902     fun revokeTwoPermTest() {
903         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, FG_PERM_2_NAME to true))
904         val perms = mutableMapOf<String, LightPermission>()
905         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
906         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME)
907         val group = createMockGroup(pkg, perms)
908         resetMockAppState()
909 
910         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
911 
912         val newFlags = FLAG_PERMISSION_USER_SET
913         verifyPermissionState(
914             permName = FG_PERM_NAME,
915             expectPermChange = true,
916             expectPermGranted = false,
917             expectedFlags = newFlags
918         )
919         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
920         verifyPermissionState(
921             permName = FG_PERM_2_NAME,
922             expectPermChange = true,
923             expectPermGranted = false,
924             expectedFlags = newFlags
925         )
926         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
927         verifyAppKillState(shouldBeKilled = false)
928 
929         val expectedState =
930             mutableMapOf(FG_PERM_NAME to (false to newFlags), FG_PERM_2_NAME to (false to newFlags))
931         assertGroupPermState(newGroup, expectedState)
932     }
933 
934     /**
935      * Test the revoking of a permission with no app op. No app ops should change, but the
936      * permission should be revoked.
937      */
938     @Test
revokeNoAppOpPermnull939     fun revokeNoAppOpPerm() {
940         val pkg = createMockPackage(mapOf(FG_PERM_NAME_NO_APP_OP to true))
941         val perms = mutableMapOf<String, LightPermission>()
942         perms[FG_PERM_NAME_NO_APP_OP] = createMockPerm(pkg, FG_PERM_NAME_NO_APP_OP)
943         val group = createMockGroup(pkg, perms)
944         resetMockAppState()
945         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
946 
947         val newFlags = FLAG_PERMISSION_USER_SET
948         verifyPermissionState(
949             permName = FG_PERM_NAME_NO_APP_OP,
950             expectPermChange = true,
951             expectPermGranted = false,
952             expectedFlags = newFlags
953         )
954         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
955         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
956         verifyAppKillState(shouldBeKilled = false)
957 
958         val expectedState = mutableMapOf(FG_PERM_NAME_NO_APP_OP to (false to newFlags))
959         assertGroupPermState(newGroup, expectedState)
960     }
961 
962     /**
963      * Test that revoking a background permission revokes the permission, and sets the app ops of
964      * its foreground permissions to foreground only, and does not revoke the foreground permission.
965      */
966     @Test
revokeBgPermTestnull967     fun revokeBgPermTest() {
968         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
969         val perms = mutableMapOf<String, LightPermission>()
970         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
971         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
972         val group = createMockGroup(pkg, perms)
973         resetMockAppState()
974 
975         val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group)
976 
977         val newFlags = FLAG_PERMISSION_USER_SET
978         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
979         verifyPermissionState(
980             permName = BG_PERM_NAME,
981             expectPermChange = true,
982             expectPermGranted = false,
983             expectedFlags = newFlags
984         )
985         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
986         verifyAppKillState(shouldBeKilled = false)
987 
988         val expectedState =
989             mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (false to newFlags))
990         assertGroupPermState(newGroup, expectedState)
991     }
992 
993     /**
994      * Test granting a foreground permission, then a background. After the foreground permission is
995      * granted, the app op should be in foreground mode. After the background permission, it should
996      * be fully allowed.
997      */
998     @Test
revokeBgAndFgPermTestnull999     fun revokeBgAndFgPermTest() {
1000         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
1001         val perms = mutableMapOf<String, LightPermission>()
1002         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
1003         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
1004         val group = createMockGroup(pkg, perms)
1005         resetMockAppState()
1006 
1007         val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, true)
1008 
1009         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
1010         verifyPermissionState(
1011             permName = BG_PERM_NAME,
1012             expectPermChange = true,
1013             expectPermGranted = false,
1014             expectedFlags = newFlags
1015         )
1016         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
1017         verifyAppKillState(shouldBeKilled = false)
1018         val expectedState =
1019             mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS), BG_PERM_NAME to (false to newFlags))
1020         assertGroupPermState(newGroup, expectedState)
1021 
1022         resetMockAppState()
1023         val newGroup2 = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, true)
1024 
1025         verifyPermissionState(
1026             permName = FG_PERM_NAME,
1027             expectPermChange = true,
1028             expectPermGranted = false,
1029             expectedFlags = newFlags
1030         )
1031         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1032         verifyAppKillState(shouldBeKilled = false)
1033 
1034         val expectedState2 =
1035             mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (false to newFlags))
1036         assertGroupPermState(newGroup2, expectedState2)
1037     }
1038 
1039     /**
1040      * Test revoking a group with a foreground permission that is system fixed, and another that
1041      * isn't. The system fixed permission should not change.
1042      */
1043     @Test
revokeSystemFixedTestnull1044     fun revokeSystemFixedTest() {
1045         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, FG_PERM_2_NAME to true))
1046         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
1047         val perms = mutableMapOf<String, LightPermission>()
1048         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
1049         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, flags = permFlags)
1050         val group = createMockGroup(pkg, perms)
1051         resetMockAppState()
1052 
1053         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1054 
1055         val newFlags = FLAG_PERMISSION_USER_SET
1056         verifyPermissionState(
1057             permName = FG_PERM_NAME,
1058             expectPermChange = true,
1059             expectPermGranted = false,
1060             expectedFlags = newFlags
1061         )
1062         verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = false)
1063         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1064         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
1065         verifyAppKillState(shouldBeKilled = false)
1066 
1067         val expectedState =
1068             mutableMapOf(FG_PERM_NAME to (false to newFlags), FG_PERM_2_NAME to (true to permFlags))
1069         assertGroupPermState(newGroup, expectedState)
1070     }
1071 
1072     /**
1073      * Test revoking a group with a background permission that is system fixed, and a background
1074      * permission that isn't. The system fixed permission should not change.
1075      */
1076     @Test
revokeBgSystemFixedTestnull1077     fun revokeBgSystemFixedTest() {
1078         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
1079         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
1080         val perms = mutableMapOf<String, LightPermission>()
1081         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
1082         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, FG_PERM_NAMES, permFlags)
1083         val group = createMockGroup(pkg, perms)
1084         resetMockAppState()
1085 
1086         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1087 
1088         val newFlags = FLAG_PERMISSION_USER_SET
1089         verifyPermissionState(
1090             permName = FG_PERM_NAME,
1091             expectPermChange = true,
1092             expectPermGranted = false,
1093             expectedFlags = newFlags
1094         )
1095         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1096         verifyAppKillState(shouldBeKilled = false)
1097 
1098         var expectedState =
1099             mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (true to permFlags))
1100         assertGroupPermState(newGroup, expectedState)
1101 
1102         resetMockAppState()
1103         val newGroup2 = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup)
1104 
1105         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false)
1106         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
1107         verifyAppKillState(shouldBeKilled = false)
1108 
1109         expectedState =
1110             mutableMapOf(FG_PERM_NAME to (false to newFlags), BG_PERM_NAME to (true to permFlags))
1111         assertGroupPermState(newGroup2, expectedState)
1112     }
1113 
1114     /**
1115      * Test revoking a one time granted permission. The permission should be revoked, but no longer
1116      * be one time.
1117      */
1118     @Test
revokeOneTimeTestnull1119     fun revokeOneTimeTest() {
1120         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
1121         val oldFlags = FLAG_PERMISSION_ONE_TIME
1122         val perms = mutableMapOf<String, LightPermission>()
1123         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
1124         val group = createMockGroup(pkg, perms)
1125         resetMockAppState()
1126 
1127         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1128 
1129         val newFlags = FLAG_PERMISSION_USER_SET
1130         verifyPermissionState(
1131             permName = FG_PERM_NAME,
1132             expectPermChange = true,
1133             expectPermGranted = false,
1134             expectedFlags = newFlags,
1135             originalFlags = oldFlags
1136         )
1137         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1138         verifyAppKillState(shouldBeKilled = false)
1139 
1140         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1141         assertGroupPermState(newGroup, expectedState)
1142     }
1143 
1144     /**
1145      * Test compat revoking (permission granted, app op denied) permission. The app op should be
1146      * revoked, while the permission remains granted. The app should also be killed.
1147      */
1148     @Test
revokePreMAppTestnull1149     fun revokePreMAppTest() {
1150         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true), isPreMApp = true)
1151         val perms = mutableMapOf<String, LightPermission>()
1152         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
1153         val group = createMockGroup(pkg, perms)
1154         resetMockAppState()
1155 
1156         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1157 
1158         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_REVOKED_COMPAT
1159         verifyPermissionState(
1160             permName = FG_PERM_NAME,
1161             expectPermChange = false,
1162             expectedFlags = newFlags
1163         )
1164         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1165         verifyAppKillState(shouldBeKilled = true)
1166 
1167         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1168         assertGroupPermState(newGroup, expectedState)
1169     }
1170 
1171     /**
1172      * Test the revoking of a single foreground permission for a Pre M app. Nothing should change,
1173      * and the app should not be killed
1174      */
1175     @Test
revokeAlreadyRevokedPreMTestnull1176     fun revokeAlreadyRevokedPreMTest() {
1177         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
1178         val perms = mutableMapOf<String, LightPermission>()
1179         val flags = FLAG_PERMISSION_USER_SET
1180         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = flags)
1181         val group = createMockGroup(pkg, perms)
1182         resetMockAppState()
1183 
1184         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1185 
1186         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
1187         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
1188         verifyAppKillState(shouldBeKilled = false)
1189 
1190         val expectedState = mutableMapOf(FG_PERM_NAME to (false to flags))
1191         assertGroupPermState(newGroup, expectedState)
1192     }
1193 
1194     /**
1195      * Test revoking a standard permission for an instant app, to show that instant app status does
1196      * not affect the revoking of a permission.
1197      */
1198     @Test
revokeInstantAppTestnull1199     fun revokeInstantAppTest() {
1200         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true), isInstantApp = true)
1201         val perms = mutableMapOf<String, LightPermission>()
1202         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
1203         val group = createMockGroup(pkg, perms)
1204         resetMockAppState()
1205 
1206         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
1207 
1208         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
1209         verifyPermissionState(
1210             permName = FG_PERM_NAME,
1211             expectPermChange = true,
1212             expectPermGranted = false,
1213             expectedFlags = newFlags
1214         )
1215         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1216         verifyAppKillState(shouldBeKilled = false)
1217 
1218         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1219         assertGroupPermState(newGroup, expectedState)
1220     }
1221 
1222     /**
1223      * Revoke a permission that was user fixed, and set it to no longer be user fixed. The
1224      * permission and its app op should be revoked, and the permission should no longer be user
1225      * fixed.
1226      */
1227     @Test
revokeUserFixedPermTestnull1228     fun revokeUserFixedPermTest() {
1229         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
1230         val perms = mutableMapOf<String, LightPermission>()
1231         val oldFlags = FLAG_PERMISSION_USER_FIXED
1232         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1233         val group = createMockGroup(pkg, perms)
1234         resetMockAppState()
1235 
1236         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1237 
1238         val newFlags = FLAG_PERMISSION_USER_SET
1239         verifyPermissionState(
1240             permName = FG_PERM_NAME,
1241             expectPermChange = true,
1242             expectPermGranted = false,
1243             expectedFlags = newFlags,
1244             originalFlags = oldFlags
1245         )
1246         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1247         verifyAppKillState(shouldBeKilled = false)
1248 
1249         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1250         assertGroupPermState(newGroup, expectedState)
1251     }
1252 
1253     /**
1254      * Revoke a permission that was not user fixed, and set it to be user fixed. The permission and
1255      * its app op should be revoked, and the permission should be user fixed.
1256      */
1257     @Test
revokeAndSetUserFixedPermTestnull1258     fun revokeAndSetUserFixedPermTest() {
1259         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
1260         val perms = mutableMapOf<String, LightPermission>()
1261         val oldFlags = FLAG_PERMISSION_USER_SET
1262         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1263         val group = createMockGroup(pkg, perms)
1264         resetMockAppState()
1265 
1266         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
1267 
1268         val newFlags = oldFlags or FLAG_PERMISSION_USER_FIXED
1269         verifyPermissionState(
1270             permName = FG_PERM_NAME,
1271             expectPermChange = true,
1272             expectPermGranted = false,
1273             expectedFlags = newFlags,
1274             originalFlags = oldFlags
1275         )
1276         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1277         verifyAppKillState(shouldBeKilled = false)
1278 
1279         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1280         assertGroupPermState(newGroup, expectedState)
1281     }
1282 
1283     /**
1284      * Test revoking an already revoked permission, while changing its user fixed state from true to
1285      * false. The user fixed should update, but the state should stay the same otherwise.
1286      */
1287     @Test
changeUserFixedTestnull1288     fun changeUserFixedTest() {
1289         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
1290         val perms = mutableMapOf<String, LightPermission>()
1291         val oldFlags = FLAG_PERMISSION_USER_FIXED
1292         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1293         val group = createMockGroup(pkg, perms)
1294         resetMockAppState()
1295 
1296         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1297 
1298         val newFlags = FLAG_PERMISSION_USER_SET
1299         verifyPermissionState(
1300             permName = FG_PERM_NAME,
1301             expectPermChange = false,
1302             expectedFlags = newFlags,
1303             originalFlags = oldFlags
1304         )
1305         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
1306         verifyAppKillState(shouldBeKilled = false)
1307 
1308         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1309         assertGroupPermState(newGroup, expectedState)
1310     }
1311 }
1312