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.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.pm.PackageManager
28 import android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED
29 import android.content.pm.PackageManager.FLAG_PERMISSION_ONE_TIME
30 import android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
31 import android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
32 import android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
33 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED
34 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
35 import android.content.pm.PackageManager.PERMISSION_DENIED
36 import android.content.pm.PackageManager.PERMISSION_GRANTED
37 import android.content.pm.PermissionInfo
38 import android.content.pm.PermissionInfo.PROTECTION_FLAG_INSTANT
39 import android.content.pm.PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY
40 import android.os.Build
41 import android.os.UserHandle
42 import com.android.permissioncontroller.permission.model.livedatatypes.LightAppPermGroup
43 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo
44 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermGroupInfo
45 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
46 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermission
47 import com.google.common.truth.Truth.assertThat
48 import com.google.common.truth.Truth.assertWithMessage
49 import org.junit.Assume.assumeNotNull
50 import org.junit.Assume.assumeTrue
51 import org.junit.BeforeClass
52 import org.junit.Test
53 import org.junit.runner.RunWith
54 import org.mockito.ArgumentMatchers.anyInt
55 import org.mockito.ArgumentMatchers.anyString
56 import org.mockito.ArgumentMatchers.eq
57 import org.mockito.ArgumentMatchers.nullable
58 import org.mockito.Mock
59 import org.mockito.Mockito.`when`
60 import org.mockito.Mockito.mock
61 import org.mockito.Mockito.never
62 import org.mockito.Mockito.verify
63 
64 import androidx.test.ext.junit.runners.AndroidJUnit4
65 
66 private const val PERMISSION_CONTROLLER_CHANGED_FLAG_MASK = FLAG_PERMISSION_USER_SET or
67         FLAG_PERMISSION_USER_FIXED or
68         FLAG_PERMISSION_ONE_TIME or
69         FLAG_PERMISSION_REVOKED_COMPAT or
70         FLAG_PERMISSION_ONE_TIME or
71         FLAG_PERMISSION_REVIEW_REQUIRED or
72         FLAG_PERMISSION_AUTO_REVOKED
73 
74 /**
75  * A suite of unit tests to test the granting and revoking of permissions. Note- does not currently
76  * test the Location Access Check.
77  */
78 @RunWith(AndroidJUnit4::class)
79 class GrantRevokeTests {
80 
81     companion object {
82         private const val PERM_GROUP_NAME = Manifest.permission_group.LOCATION
83         private const val FG_PERM_NAME = Manifest.permission.ACCESS_COARSE_LOCATION
84         private const val FG_PERM_2_NAME = Manifest.permission.ACCESS_FINE_LOCATION
85         private const val FG_PERM_NAME_NO_APP_OP = "android.permission.permWithNoAppOp"
86         private const val BG_PERM_NAME = Manifest.permission.ACCESS_BACKGROUND_LOCATION
87         private const val TEST_PACKAGE_NAME = "android.permission.cts.testapp"
88         private const val TEST_UID = 1
89         private val TEST_USER = UserHandle.getUserHandleForUid(TEST_UID)
90         private const val NO_FLAGS = 0
91         private val FG_PERM_NAMES = listOf(FG_PERM_NAME, FG_PERM_2_NAME, FG_PERM_NAME_NO_APP_OP)
92         private val OP_NAME = permissionToOp(FG_PERM_NAME)
93         private val OP_2_NAME = permissionToOp(FG_PERM_2_NAME)
94 
95         @BeforeClass
96         @JvmStatic
checkAppOpsNotNullAndDistinctnull97         fun checkAppOpsNotNullAndDistinct() {
98             assumeNotNull(OP_NAME, OP_2_NAME)
99             assumeTrue(OP_NAME != OP_2_NAME)
100         }
101     }
102 
103     @Mock
104     val app: Application = mock(Application::class.java)
105 
106     /**
107      * Create a mock Application object, with a mock packageManager, AppOpsManager, and
108      * ActivityManager.
109      *
110      * @return The mocked Application object
111      */
resetMockAppStatenull112     private fun resetMockAppState() {
113         `when`(app.packageManager).thenReturn(mock(PackageManager::class.java))
114 
115         val aom: AppOpsManager = mock(AppOpsManager::class.java)
116         // Return an invalid app op state, so setOpMode will always attempt to change the op state
117         `when`(aom.unsafeCheckOpRaw(anyString(), anyInt(), nullable(String::class.java)))
118             .thenReturn(-1)
119         `when`(app.getSystemService(AppOpsManager::class.java)).thenReturn(aom)
120 
121         `when`(app.getSystemService(ActivityManager::class.java)).thenReturn(
122             mock(ActivityManager::class.java))
123     }
124 
125     /**
126      * Create a LightPackageInfo object with a particular set of properties
127      *
128      * @param perms The (name -> permissionInfo) of the permissions requested by the app
129      * @param isPreMApp Whether this app targets pre-M
130      * @param isInstantApp {@code true} iff this is an instant app
131      */
createMockPackagenull132     private fun createMockPackage(
133         perms: Map<String, Boolean>,
134         isPreMApp: Boolean = false,
135         isInstantApp: Boolean = false
136     ): LightPackageInfo {
137         val permNames = mutableListOf<String>()
138         val permFlags = mutableListOf<Int>()
139         for ((permName, isGranted) in perms) {
140             permNames.add(permName)
141             permFlags.add(if (isGranted) {
142                 PERMISSION_GRANTED
143             } else {
144                 PERMISSION_DENIED
145             })
146         }
147 
148         return LightPackageInfo(TEST_PACKAGE_NAME, listOf(), permNames, permFlags, TEST_UID,
149                 if (isPreMApp) {
150                     Build.VERSION_CODES.LOLLIPOP
151                 } else {
152                     Build.VERSION_CODES.R
153                 }, isInstantApp, isInstantApp, 0, 0L)
154     }
155 
156     /**
157      * Create a LightPermission object with a particular set of properties
158      *
159      * @param pkg Package requesting the permission
160      * @param permName The name of the permission
161      * @param granted Whether the permission is granted (should be false if the permission is compat
162      * revoked)
163      * @param backgroundPerm The name of this permission's background permission, if there is one
164      * @param foregroundPerms The names of this permission's foreground permissions, if there are
165      * any
166      * @param flags The system permission flags of this permission
167      * @param permInfoProtectionFlags The flags that the PermissionInfo object has (accessed by
168      * PermissionInfo.getProtectionFlags)
169      */
createMockPermnull170     private fun createMockPerm(
171         pkgInfo: LightPackageInfo,
172         permName: String,
173         backgroundPerm: String? = null,
174         foregroundPerms: List<String>? = null,
175         flags: Int = NO_FLAGS,
176         permInfoProtectionFlags: Int = 0
177     ): LightPermission {
178         val permInfo = LightPermInfo(permName, TEST_PACKAGE_NAME, PERM_GROUP_NAME, backgroundPerm,
179             PermissionInfo.PROTECTION_DANGEROUS, permInfoProtectionFlags, 0)
180         return LightPermission(pkgInfo, permInfo,
181                 pkgInfo.requestedPermissionsFlags[pkgInfo.requestedPermissions.indexOf(permName)]
182                         == PERMISSION_GRANTED, flags, foregroundPerms)
183     }
184 
185     /**
186      * Create a LightAppPermGroup with a particular set of properties.
187      *
188      * @param pkg Package requesting the permission
189      * @param perms The map of perm name to LightPermission (should be created with @createMockPerm)
190      */
createMockGroupnull191     private fun createMockGroup(
192         pkgInfo: LightPackageInfo,
193         perms: Map<String, LightPermission> = emptyMap()
194     ): LightAppPermGroup {
195         val pGi = LightPermGroupInfo(PERM_GROUP_NAME, TEST_PACKAGE_NAME, 0, 0, 0, false)
196         return LightAppPermGroup(pkgInfo, pGi, perms, false, false)
197     }
198 
199     /**
200      * Create a list of strings which usefully states which flags are set in a group of flags.
201      * Only checks for flags relevant to granting and revoking (so, for instance, policy fixed is
202      * not checked).
203      *
204      * @param flags The flags to check
205      *
206      * @return a list of strings, representing which flags have been set
207      */
flagsToStringnull208     private fun flagsToString(flags: Int): List<String> {
209         val flagStrings = mutableListOf<String>()
210         if (flags and FLAG_PERMISSION_USER_SET != 0) {
211             flagStrings.add("USER_SET")
212         }
213         if (flags and FLAG_PERMISSION_USER_FIXED != 0) {
214             flagStrings.add("USER_FIXED")
215         }
216         if (flags and FLAG_PERMISSION_SYSTEM_FIXED != 0) {
217             flagStrings.add("SYSTEM_FIXED")
218         }
219         if (flags and FLAG_PERMISSION_REVOKED_COMPAT != 0) {
220             flagStrings.add("REVOKED_COMPAT")
221         }
222         if (flags and FLAG_PERMISSION_REVIEW_REQUIRED != 0) {
223             flagStrings.add("REVIEW_REQUIRED")
224         }
225         if (flags and FLAG_PERMISSION_ONE_TIME != 0) {
226             flagStrings.add("ONE_TIME")
227         }
228         return flagStrings
229     }
230 
231     /**
232      * Assert that the permissions of the given group match the expected state
233      *
234      * @param groupToCheck The LightAppPermGroup whose permissions we are checking
235      * @param expectedState A map <permission name, grant state and permission flags pair>
236      */
assertGroupPermStatenull237     private fun assertGroupPermState(
238         groupToCheck: LightAppPermGroup,
239         expectedState: Map<String, Pair<Boolean, Int>>
240     ) {
241         val perms = groupToCheck.permissions
242 
243         assertThat(perms.keys).isEqualTo(expectedState.keys)
244 
245         for ((permName, state) in expectedState) {
246             val granted = state.first
247             val flags = state.second
248 
249             assertWithMessage("permission $permName grant state incorrect")
250                 .that(perms[permName]?.isGrantedIncludingAppOp).isEqualTo(granted)
251 
252             val actualFlags = perms[permName]!!.flags
253             assertWithMessage("permission $permName flags incorrect, expected" +
254                 "${flagsToString(flags)}; got ${flagsToString(actualFlags)}")
255                 .that(perms[permName]?.flags).isEqualTo(flags)
256         }
257     }
258 
259     /**
260      * Verify that permission state was propagated to the system. Verify that grant or revoke
261      * were called, if applicable, or verify they weren't. Verify that we have set flags
262      * correctly, if applicable, or verify flags were not set.
263      *
264      * @param permName The name of the permission to verify
265      * @param expectPermChange Whether or not a permission grant or revoke was expected. If false,
266      * verify neither grant nor revoke were called
267      * @param expectPermGranted If a permission change was expected, verify that the permission
268      * was set to granted (if true) or revoked (if false)
269      * @param expectedFlags The flags that the system should have set the permission to have
270      * @param originalFlags The flags the permission originally had. Used to ensure the correct
271      * flag mask was used
272      */
verifyPermissionStatenull273     private fun verifyPermissionState(
274         permName: String,
275         expectPermChange: Boolean,
276         expectPermGranted: Boolean = true,
277         expectedFlags: Int = NO_FLAGS,
278         originalFlags: Int = NO_FLAGS
279     ) {
280         val pm = app.packageManager
281         if (expectPermChange) {
282             if (expectPermGranted) {
283                 verify(pm).grantRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
284             } else {
285                 verify(pm).revokeRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
286             }
287         } else {
288             verify(pm, never()).grantRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
289             verify(pm, never()).revokeRuntimePermission(TEST_PACKAGE_NAME, permName, TEST_USER)
290         }
291 
292         if (expectedFlags != originalFlags) {
293             verify(pm).updatePermissionFlags(permName, TEST_PACKAGE_NAME,
294                     PERMISSION_CONTROLLER_CHANGED_FLAG_MASK, expectedFlags, TEST_USER)
295         } else {
296             verify(pm, never()).updatePermissionFlags(eq(permName), eq(TEST_PACKAGE_NAME), anyInt(),
297                 anyInt(), eq(TEST_USER))
298         }
299     }
300 
301     /**
302      * Verify that app op state was propagated to the system. Verify that setUidMode was called, if
303      * applicable, or verify it wasn't.
304      *
305      * @param appOpName The name of the app op to check
306      * @param expectAppOpSet Whether an app op change was expected. If false, verify setUidMode was
307      * not called
308      * @param expectedMode If a change was expected, the mode the app op should be set to
309      */
verifyAppOpStatenull310     private fun verifyAppOpState(
311         appOpName: String,
312         expectAppOpSet: Boolean,
313         expectedMode: Int = MODE_IGNORED
314     ) {
315         val aom = app.getSystemService(AppOpsManager::class.java)
316         if (expectAppOpSet) {
317             verify(aom).setUidMode(appOpName, TEST_UID, expectedMode)
318         } else {
319             verify(aom, never()).setUidMode(eq(appOpName), eq(TEST_UID), anyInt())
320         }
321     }
322 
323     /**
324      * Verify that the test app either was or was not killed.
325      *
326      * @param shouldBeKilled Whether or not the app should have been killed
327      */
verifyAppKillStatenull328     private fun verifyAppKillState(shouldBeKilled: Boolean) {
329         val am = app.getSystemService(ActivityManager::class.java)
330         if (shouldBeKilled) {
331             verify(am).killUid(eq(TEST_UID), anyString())
332         } else {
333             verify(am, never()).killUid(eq(TEST_UID), anyString())
334         }
335     }
336 
337     /**
338      * Test the granting of a single foreground permission. The permission and its app op should be
339      * granted.
340      */
341     @Test
grantOnePermTestnull342     fun grantOnePermTest() {
343         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
344         val perms = mutableMapOf<String, LightPermission>()
345         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
346         val group = createMockGroup(pkg, perms)
347         resetMockAppState()
348 
349         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
350 
351         val newFlags = FLAG_PERMISSION_USER_SET
352         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
353             expectPermGranted = true, expectedFlags = newFlags)
354         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
355         verifyAppKillState(shouldBeKilled = false)
356 
357         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
358         assertGroupPermState(newGroup, expectedState)
359     }
360 
361     /**
362      * Test the granting of two foreground permissions, one with a background permission. The
363      * permissions and app ops should be granted, and the permissions marked user set. The second
364      * app op should be set to foreground mode.
365      */
366     @Test
grantTwoPermTestnull367     fun grantTwoPermTest() {
368         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, FG_PERM_2_NAME to false))
369         val perms = mutableMapOf<String, LightPermission>()
370         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
371         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, BG_PERM_NAME)
372         val group = createMockGroup(pkg, perms)
373         resetMockAppState()
374 
375         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
376 
377         val newFlags = FLAG_PERMISSION_USER_SET
378         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
379             expectPermGranted = true, expectedFlags = newFlags)
380         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
381         verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = true,
382             expectPermGranted = true, expectedFlags = newFlags)
383         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = true,
384             expectedMode = MODE_FOREGROUND)
385         verifyAppKillState(shouldBeKilled = false)
386 
387         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
388             FG_PERM_2_NAME to (true to newFlags))
389         assertGroupPermState(newGroup, expectedState)
390     }
391 
392     /**
393      * Test the granting of a permission with no app op. No app ops should change, but the
394      * permission should be granted
395      */
396     @Test
grantNoAppOpPermnull397     fun grantNoAppOpPerm() {
398         val pkg = createMockPackage(mapOf(FG_PERM_NAME_NO_APP_OP to false))
399         val perms = mutableMapOf<String, LightPermission>()
400         perms[FG_PERM_NAME_NO_APP_OP] = createMockPerm(pkg, FG_PERM_NAME_NO_APP_OP)
401         val group = createMockGroup(pkg, perms)
402         resetMockAppState()
403 
404         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
405 
406         val newFlags = FLAG_PERMISSION_USER_SET
407         verifyPermissionState(permName = FG_PERM_NAME_NO_APP_OP, expectPermChange = true,
408             expectPermGranted = true, expectedFlags = newFlags)
409         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
410         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
411         verifyAppKillState(shouldBeKilled = false)
412 
413         val expectedState = mutableMapOf(FG_PERM_NAME_NO_APP_OP to (true to newFlags))
414         assertGroupPermState(newGroup, expectedState)
415     }
416 
417     /**
418      * Test that granting a background permission grants the background permission, and allows the
419      * app ops of its foreground permissions, but does not grant the foreground permission itself.
420      */
421     @Test
grantBgPermTestnull422     fun grantBgPermTest() {
423         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to false))
424         val perms = mutableMapOf<String, LightPermission>()
425         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
426         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
427         val group = createMockGroup(pkg, perms)
428         resetMockAppState()
429 
430         val newGroup = KotlinUtils.grantBackgroundRuntimePermissions(app, group)
431 
432         val newFlags = FLAG_PERMISSION_USER_SET
433         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
434             expectPermGranted = true, expectedFlags = newFlags)
435         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
436         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
437         verifyAppKillState(shouldBeKilled = false)
438 
439         val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
440             BG_PERM_NAME to (true to newFlags))
441         assertGroupPermState(newGroup, expectedState)
442     }
443 
444     /**
445      * Test granting a foreground permission, then a background. After the foreground permission is
446      * granted, the app op should be in foreground mode. After the background permission, it should
447      * be fully allowed.
448      */
449     @Test
grantBgAndFgPermTestnull450     fun grantBgAndFgPermTest() {
451         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
452         val perms = mutableMapOf<String, LightPermission>()
453         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
454         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
455         val group = createMockGroup(pkg, perms)
456         resetMockAppState()
457 
458         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
459 
460         val newFlags = FLAG_PERMISSION_USER_SET
461         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
462             expectPermGranted = true, expectedFlags = newFlags)
463         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false)
464         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
465         verifyAppKillState(shouldBeKilled = false)
466 
467         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
468             BG_PERM_NAME to (false to NO_FLAGS))
469         assertGroupPermState(newGroup, expectedState)
470 
471         resetMockAppState()
472         val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
473 
474         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
475             expectPermGranted = true, expectedFlags = newFlags)
476         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
477         verifyAppKillState(shouldBeKilled = false)
478 
479         val expectedState2 = mutableMapOf(FG_PERM_NAME to (true to newFlags),
480             BG_PERM_NAME to (true to newFlags))
481         assertGroupPermState(newGroup2, expectedState2)
482     }
483 
484     /**
485      * Test granting a group with a foreground permission that is system fixed, and another that
486      * isn't. The system fixed permission should not change.
487      */
488     @Test
grantSystemFixedTestnull489     fun grantSystemFixedTest() {
490         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, FG_PERM_2_NAME to false))
491         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
492         val perms = mutableMapOf<String, LightPermission>()
493         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
494         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, flags = permFlags)
495         val group = createMockGroup(pkg, perms)
496         resetMockAppState()
497 
498         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
499 
500         val newFlags = FLAG_PERMISSION_USER_SET
501         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
502             expectPermGranted = true, expectedFlags = newFlags)
503         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
504         verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = false,
505             expectedFlags = permFlags, originalFlags = permFlags)
506         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
507         verifyAppKillState(shouldBeKilled = false)
508 
509         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
510             FG_PERM_2_NAME to (false to permFlags))
511         assertGroupPermState(newGroup, expectedState)
512     }
513 
514     /**
515      * Test granting a group with a background permission that is system fixed, and a background
516      * permission that isn't. The system fixed permission should not change.
517      */
518     @Test
grantBgSystemFixedTestnull519     fun grantBgSystemFixedTest() {
520         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false, BG_PERM_NAME to false))
521         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
522         val perms = mutableMapOf<String, LightPermission>()
523         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
524         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, FG_PERM_NAMES, permFlags)
525         val group = createMockGroup(pkg, perms)
526         resetMockAppState()
527 
528         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
529 
530         val newFlags = FLAG_PERMISSION_USER_SET
531         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
532             expectPermGranted = true, expectedFlags = newFlags)
533         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
534         verifyAppKillState(shouldBeKilled = false)
535 
536         var expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
537             BG_PERM_NAME to (false to permFlags))
538         assertGroupPermState(newGroup, expectedState)
539 
540         resetMockAppState()
541         val newGroup2 = KotlinUtils.grantBackgroundRuntimePermissions(app, newGroup)
542 
543         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false,
544             expectedFlags = permFlags, originalFlags = permFlags)
545         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
546         verifyAppKillState(shouldBeKilled = false)
547 
548         expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags),
549             BG_PERM_NAME to (false to permFlags))
550         assertGroupPermState(newGroup2, expectedState)
551     }
552 
553     /**
554      * Test granting a one time granted permission. The permission should still be granted, but no
555      * longer be one time.
556      */
557     @Test
grantOneTimeTestnull558     fun grantOneTimeTest() {
559         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
560         val oldFlags = FLAG_PERMISSION_ONE_TIME
561         val perms = mutableMapOf<String, LightPermission>()
562         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
563         val group = createMockGroup(pkg, perms)
564         resetMockAppState()
565 
566         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
567 
568         val newFlags = FLAG_PERMISSION_USER_SET
569         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
570             expectedFlags = newFlags, originalFlags = oldFlags)
571         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
572         verifyAppKillState(shouldBeKilled = false)
573 
574         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
575         assertGroupPermState(newGroup, expectedState)
576     }
577 
578     /**
579      * Test granting a compat revoked (permission granted, app op denied) permission. The app op
580      * should be allowed, as should the permission. The app should also be killed.
581      */
582     @Test
grantPreMAppTestnull583     fun grantPreMAppTest() {
584         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isPreMApp = true)
585         val oldFlags = FLAG_PERMISSION_REVOKED_COMPAT
586         val perms = mutableMapOf<String, LightPermission>()
587         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
588         val group = createMockGroup(pkg, perms)
589         resetMockAppState()
590 
591         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
592         val newFlags = FLAG_PERMISSION_USER_SET
593         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
594             expectedFlags = newFlags, originalFlags = oldFlags)
595         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
596         verifyAppKillState(shouldBeKilled = true)
597 
598         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
599         assertGroupPermState(newGroup, expectedState)
600     }
601 
602     /**
603      * Test the granting of a single foreground permission for a Pre M app. Nothing should change,
604      * and the app should not be killed
605      */
606     @Test
grantAlreadyGrantedPreMTestnull607     fun grantAlreadyGrantedPreMTest() {
608         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
609         val perms = mutableMapOf<String, LightPermission>()
610         val flags = FLAG_PERMISSION_USER_SET
611         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = flags)
612         val group = createMockGroup(pkg, perms)
613         resetMockAppState()
614         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
615 
616         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
617             expectedFlags = flags, originalFlags = flags)
618         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
619         verifyAppKillState(shouldBeKilled = false)
620 
621         val expectedState = mutableMapOf(FG_PERM_NAME to (true to flags))
622         assertGroupPermState(newGroup, expectedState)
623     }
624 
625     /**
626      * Test that an instant app cannot have regular (non-instant) permission granted.
627      */
628     @Test
cantGrantInstantAppStandardPermTestnull629     fun cantGrantInstantAppStandardPermTest() {
630         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
631         val perms = mutableMapOf<String, LightPermission>()
632         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
633         val group = createMockGroup(pkg, perms)
634         resetMockAppState()
635 
636         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
637 
638         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
639         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
640         verifyAppKillState(shouldBeKilled = false)
641 
642         val expectedState = mutableMapOf(FG_PERM_NAME to (false to NO_FLAGS))
643         assertGroupPermState(newGroup, expectedState)
644     }
645 
646     /**
647      * Test that a pre-M app (pre runtime permissions) can't have a runtime only permission granted.
648      */
649     @Test
cantGrantPreRuntimeAppWithRuntimeOnlyPermTestnull650     fun cantGrantPreRuntimeAppWithRuntimeOnlyPermTest() {
651         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isPreMApp = true)
652         val perms = mutableMapOf<String, LightPermission>()
653         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME,
654             permInfoProtectionFlags = PROTECTION_FLAG_RUNTIME_ONLY)
655         val group = createMockGroup(pkg, perms)
656         resetMockAppState()
657 
658         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
659 
660         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
661         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
662         verifyAppKillState(shouldBeKilled = false)
663 
664         val expectedState = mutableMapOf(FG_PERM_NAME to (false to NO_FLAGS))
665         assertGroupPermState(newGroup, expectedState)
666     }
667 
668     /**
669      * Test that an instant package can have an instant permission granted.
670      */
671     @Test
grantInstantAppInstantPermTestnull672     fun grantInstantAppInstantPermTest() {
673         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false), isInstantApp = true)
674         val perms = mutableMapOf<String, LightPermission>()
675         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME,
676             permInfoProtectionFlags = PROTECTION_FLAG_INSTANT)
677         val group = createMockGroup(pkg, perms)
678         resetMockAppState()
679 
680         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
681 
682         val newFlags = FLAG_PERMISSION_USER_SET
683         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
684             expectPermGranted = true, expectedFlags = newFlags)
685         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_ALLOWED)
686         verifyAppKillState(shouldBeKilled = false)
687 
688         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
689         assertGroupPermState(newGroup, expectedState)
690     }
691 
692     /**
693      * Test that granting a permission clears the user fixed and review required flags.
694      */
695     @Test
grantClearsUserFixedAndReviewRequirednull696     fun grantClearsUserFixedAndReviewRequired() {
697         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
698         val oldFlags = FLAG_PERMISSION_USER_FIXED or FLAG_PERMISSION_REVIEW_REQUIRED
699         val perms = mutableMapOf<String, LightPermission>()
700         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
701         val group = createMockGroup(pkg, perms)
702         resetMockAppState()
703         val newGroup = KotlinUtils.grantForegroundRuntimePermissions(app, group)
704 
705         val newFlags = FLAG_PERMISSION_USER_SET
706         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
707             expectedFlags = newFlags, originalFlags = oldFlags)
708         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
709         verifyAppKillState(shouldBeKilled = false)
710 
711         val expectedState = mutableMapOf(FG_PERM_NAME to (true to newFlags))
712         assertGroupPermState(newGroup, expectedState)
713     }
714 
715     /**
716      * Test revoking one foreground permission. The permission and app op should be revoked.
717      */
718     @Test
revokeOnePermTestnull719     fun revokeOnePermTest() {
720         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
721         val perms = mutableMapOf<String, LightPermission>()
722         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
723         val group = createMockGroup(pkg, perms)
724         resetMockAppState()
725 
726         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
727 
728         val newFlags = FLAG_PERMISSION_USER_SET
729         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
730             expectPermGranted = false, expectedFlags = newFlags)
731         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
732         verifyAppKillState(shouldBeKilled = false)
733 
734         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
735         assertGroupPermState(newGroup, expectedState)
736     }
737 
738     /**
739      * Test revoking two foreground permissions. Both permissions and app ops should be revoked.
740      */
741     @Test
revokeTwoPermTestnull742     fun revokeTwoPermTest() {
743         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, FG_PERM_2_NAME to true))
744         val perms = mutableMapOf<String, LightPermission>()
745         perms[FG_PERM_NAME] = createMockPerm(pkg,FG_PERM_NAME)
746         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME)
747         val group = createMockGroup(pkg, perms)
748         resetMockAppState()
749 
750         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
751 
752         val newFlags = FLAG_PERMISSION_USER_SET
753         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
754             expectPermGranted = false, expectedFlags = newFlags)
755         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
756         verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = true,
757             expectPermGranted = false, expectedFlags = newFlags)
758         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
759         verifyAppKillState(shouldBeKilled = false)
760 
761         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
762             FG_PERM_2_NAME to (false to newFlags))
763         assertGroupPermState(newGroup, expectedState)
764     }
765 
766     /**
767      * Test the revoking of a permission with no app op. No app ops should change, but the
768      * permission should be revoked.
769      */
770     @Test
revokeNoAppOpPermnull771     fun revokeNoAppOpPerm() {
772         val pkg = createMockPackage(mapOf(FG_PERM_NAME_NO_APP_OP to true))
773         val perms = mutableMapOf<String, LightPermission>()
774         perms[FG_PERM_NAME_NO_APP_OP] = createMockPerm(pkg, FG_PERM_NAME_NO_APP_OP)
775         val group = createMockGroup(pkg, perms)
776         resetMockAppState()
777         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
778 
779         val newFlags = FLAG_PERMISSION_USER_SET
780         verifyPermissionState(permName = FG_PERM_NAME_NO_APP_OP, expectPermChange = true,
781             expectPermGranted = false, expectedFlags = newFlags)
782         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
783         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
784         verifyAppKillState(shouldBeKilled = false)
785 
786         val expectedState = mutableMapOf(FG_PERM_NAME_NO_APP_OP to (false to newFlags))
787         assertGroupPermState(newGroup, expectedState)
788     }
789 
790     /**
791      * Test that revoking a background permission revokes the permission, and sets the app ops of
792      * its foreground permissions to foreground only, and does not revoke the foreground permission.
793      */
794     @Test
revokeBgPermTestnull795     fun revokeBgPermTest() {
796         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
797         val perms = mutableMapOf<String, LightPermission>()
798         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
799         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
800         val group = createMockGroup(pkg, perms)
801         resetMockAppState()
802 
803         val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group)
804 
805         val newFlags = FLAG_PERMISSION_USER_SET
806         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
807         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
808             expectPermGranted = false, expectedFlags = newFlags)
809         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
810         verifyAppKillState(shouldBeKilled = false)
811 
812         val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
813             BG_PERM_NAME to (false to newFlags))
814         assertGroupPermState(newGroup, expectedState)
815     }
816 
817     /**
818      * Test granting a foreground permission, then a background. After the foreground permission is
819      * granted, the app op should be in foreground mode. After the background permission, it should
820      * be fully allowed.
821      */
822     @Test
revokeBgAndFgPermTestnull823     fun revokeBgAndFgPermTest() {
824         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
825         val perms = mutableMapOf<String, LightPermission>()
826         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
827         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, listOf(FG_PERM_NAME))
828         val group = createMockGroup(pkg, perms)
829         resetMockAppState()
830 
831         val newGroup = KotlinUtils.revokeBackgroundRuntimePermissions(app, group, true)
832 
833         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
834         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = true,
835             expectPermGranted = false, expectedFlags = newFlags)
836         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_FOREGROUND)
837         verifyAppKillState(shouldBeKilled = false)
838         val expectedState = mutableMapOf(FG_PERM_NAME to (true to NO_FLAGS),
839             BG_PERM_NAME to (false to newFlags))
840         assertGroupPermState(newGroup, expectedState)
841 
842         resetMockAppState()
843         val newGroup2 = KotlinUtils.revokeForegroundRuntimePermissions(app, newGroup, true)
844 
845         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
846             expectPermGranted = false, expectedFlags = newFlags)
847         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
848         verifyAppKillState(shouldBeKilled = false)
849 
850         val expectedState2 = mutableMapOf(FG_PERM_NAME to (false to newFlags),
851             BG_PERM_NAME to (false to newFlags))
852         assertGroupPermState(newGroup2, expectedState2)
853     }
854 
855     /**
856      * Test revoking a group with a foreground permission that is system fixed, and another that
857      * isn't. The system fixed permission should not change.
858      */
859     @Test
revokeSystemFixedTestnull860     fun revokeSystemFixedTest() {
861         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, FG_PERM_2_NAME to true))
862         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
863         val perms = mutableMapOf<String, LightPermission>()
864         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
865         perms[FG_PERM_2_NAME] = createMockPerm(pkg, FG_PERM_2_NAME, flags = permFlags)
866         val group = createMockGroup(pkg, perms)
867         resetMockAppState()
868 
869         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
870 
871         val newFlags = FLAG_PERMISSION_USER_SET
872         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
873             expectPermGranted = false, expectedFlags = newFlags)
874         verifyPermissionState(permName = FG_PERM_2_NAME, expectPermChange = false)
875         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
876         verifyAppOpState(appOpName = OP_2_NAME, expectAppOpSet = false)
877         verifyAppKillState(shouldBeKilled = false)
878 
879         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
880             FG_PERM_2_NAME to (true to permFlags))
881         assertGroupPermState(newGroup, expectedState)
882     }
883 
884     /**
885      * Test revoking a group with a background permission that is system fixed, and a background
886      * permission that isn't. The system fixed permission should not change.
887      */
888     @Test
revokeBgSystemFixedTestnull889     fun revokeBgSystemFixedTest() {
890         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true, BG_PERM_NAME to true))
891         val permFlags = FLAG_PERMISSION_SYSTEM_FIXED
892         val perms = mutableMapOf<String, LightPermission>()
893         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, BG_PERM_NAME)
894         perms[BG_PERM_NAME] = createMockPerm(pkg, BG_PERM_NAME, null, FG_PERM_NAMES, permFlags)
895         val group = createMockGroup(pkg, perms)
896         resetMockAppState()
897 
898         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
899 
900         val newFlags = FLAG_PERMISSION_USER_SET
901         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
902             expectPermGranted = false, expectedFlags = newFlags)
903         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
904         verifyAppKillState(shouldBeKilled = false)
905 
906         var expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
907             BG_PERM_NAME to (true to permFlags))
908         assertGroupPermState(newGroup, expectedState)
909 
910         resetMockAppState()
911         val newGroup2 = KotlinUtils.revokeBackgroundRuntimePermissions(app, newGroup)
912 
913         verifyPermissionState(permName = BG_PERM_NAME, expectPermChange = false)
914         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
915         verifyAppKillState(shouldBeKilled = false)
916 
917         expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags),
918             BG_PERM_NAME to (true to permFlags))
919         assertGroupPermState(newGroup2, expectedState)
920     }
921 
922     /**
923      * Test revoking a one time granted permission. The permission should be revoked, but no
924      * longer be one time.
925      */
926     @Test
revokeOneTimeTestnull927     fun revokeOneTimeTest() {
928         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
929         val oldFlags = FLAG_PERMISSION_ONE_TIME
930         val perms = mutableMapOf<String, LightPermission>()
931         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = oldFlags)
932         val group = createMockGroup(pkg, perms)
933         resetMockAppState()
934 
935         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
936 
937         val newFlags = FLAG_PERMISSION_USER_SET
938         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
939             expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
940         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
941         verifyAppKillState(shouldBeKilled = false)
942 
943         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
944         assertGroupPermState(newGroup, expectedState)
945     }
946 
947     /**
948      * Test compat revoking (permission granted, app op denied) permission. The app op
949      * should be revoked, while the permission remains granted. The app should also be killed.
950      */
951     @Test
revokePreMAppTestnull952     fun revokePreMAppTest() {
953         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true), isPreMApp = true)
954         val perms = mutableMapOf<String, LightPermission>()
955         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
956         val group = createMockGroup(pkg, perms)
957         resetMockAppState()
958 
959         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
960 
961         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_REVOKED_COMPAT
962         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
963             expectedFlags = newFlags)
964         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
965         verifyAppKillState(shouldBeKilled = true)
966 
967         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
968         assertGroupPermState(newGroup, expectedState)
969     }
970 
971     /**
972      * Test the revoking of a single foreground permission for a Pre M app. Nothing should change,
973      * and the app should not be killed
974      */
975     @Test
revokeAlreadyRevokedPreMTestnull976     fun revokeAlreadyRevokedPreMTest() {
977         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
978         val perms = mutableMapOf<String, LightPermission>()
979         val flags = FLAG_PERMISSION_USER_SET
980         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, flags = flags)
981         val group = createMockGroup(pkg, perms)
982         resetMockAppState()
983 
984         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
985 
986         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false)
987         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
988         verifyAppKillState(shouldBeKilled = false)
989 
990         val expectedState = mutableMapOf(FG_PERM_NAME to (false to flags))
991         assertGroupPermState(newGroup, expectedState)
992     }
993 
994     /**
995      * Test revoking a standard permission for an instant app, to show that instant app status does
996      * not affect the revoking of a permission.
997      */
998     @Test
revokeInstantAppTestnull999     fun revokeInstantAppTest() {
1000         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true), isInstantApp = true)
1001         val perms = mutableMapOf<String, LightPermission>()
1002         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME)
1003         val group = createMockGroup(pkg, perms)
1004         resetMockAppState()
1005 
1006         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
1007 
1008         val newFlags = FLAG_PERMISSION_USER_SET or FLAG_PERMISSION_USER_FIXED
1009         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
1010             expectPermGranted = false, expectedFlags = newFlags)
1011         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1012         verifyAppKillState(shouldBeKilled = false)
1013 
1014         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1015         assertGroupPermState(newGroup, expectedState)
1016     }
1017 
1018     /**
1019      * Revoke a permission that was user fixed, and set it to no longer be user fixed. The
1020      * permission and its app op should be revoked, and the permission should no longer be user
1021      * fixed.
1022      */
1023     @Test
revokeUserFixedPermTestnull1024     fun revokeUserFixedPermTest() {
1025         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
1026         val perms = mutableMapOf<String, LightPermission>()
1027         val oldFlags = FLAG_PERMISSION_USER_FIXED
1028         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1029         val group = createMockGroup(pkg, perms)
1030         resetMockAppState()
1031 
1032         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1033 
1034         val newFlags = FLAG_PERMISSION_USER_SET
1035         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
1036             expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
1037         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1038         verifyAppKillState(shouldBeKilled = false)
1039 
1040         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1041         assertGroupPermState(newGroup, expectedState)
1042     }
1043 
1044     /**
1045      * Revoke a permission that was not user fixed, and set it to be user fixed. The permission and
1046      * its app op should be revoked, and the permission should be user fixed.
1047      */
1048     @Test
revokeAndSetUserFixedPermTestnull1049     fun revokeAndSetUserFixedPermTest() {
1050         val pkg = createMockPackage(mapOf(FG_PERM_NAME to true))
1051         val perms = mutableMapOf<String, LightPermission>()
1052         val oldFlags = FLAG_PERMISSION_USER_SET
1053         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1054         val group = createMockGroup(pkg, perms)
1055         resetMockAppState()
1056 
1057         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group, true)
1058 
1059         val newFlags = oldFlags or FLAG_PERMISSION_USER_FIXED
1060         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = true,
1061             expectPermGranted = false, expectedFlags = newFlags, originalFlags = oldFlags)
1062         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = true, expectedMode = MODE_IGNORED)
1063         verifyAppKillState(shouldBeKilled = false)
1064 
1065         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1066         assertGroupPermState(newGroup, expectedState)
1067     }
1068 
1069     /**
1070      * Test revoking an already revoked permission, while changing its user fixed state from true
1071      * to false. The user fixed should update, but the state should stay the same otherwise.
1072      */
1073     @Test
changeUserFixedTestnull1074     fun changeUserFixedTest() {
1075         val pkg = createMockPackage(mapOf(FG_PERM_NAME to false))
1076         val perms = mutableMapOf<String, LightPermission>()
1077         val oldFlags = FLAG_PERMISSION_USER_FIXED
1078         perms[FG_PERM_NAME] = createMockPerm(pkg, FG_PERM_NAME, null, null, oldFlags)
1079         val group = createMockGroup(pkg, perms)
1080         resetMockAppState()
1081 
1082         val newGroup = KotlinUtils.revokeForegroundRuntimePermissions(app, group)
1083 
1084         val newFlags = FLAG_PERMISSION_USER_SET
1085         verifyPermissionState(permName = FG_PERM_NAME, expectPermChange = false,
1086             expectedFlags = newFlags, originalFlags = oldFlags)
1087         verifyAppOpState(appOpName = OP_NAME, expectAppOpSet = false)
1088         verifyAppKillState(shouldBeKilled = false)
1089 
1090         val expectedState = mutableMapOf(FG_PERM_NAME to (false to newFlags))
1091         assertGroupPermState(newGroup, expectedState)
1092     }
1093 }
1094