1 /*
2  * Copyright (C) 2022 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.server.permission.access.permission
18 
19 import android.Manifest
20 import android.app.ActivityManager
21 import android.app.AppOpsManager
22 import android.compat.annotation.ChangeId
23 import android.compat.annotation.EnabledAfter
24 import android.content.Context
25 import android.content.pm.PackageInstaller
26 import android.content.pm.PackageManager
27 import android.content.pm.PackageManagerInternal
28 import android.content.pm.PermissionGroupInfo
29 import android.content.pm.PermissionInfo
30 import android.content.pm.permission.SplitPermissionInfoParcelable
31 import android.metrics.LogMaker
32 import android.os.Binder
33 import android.os.Build
34 import android.os.Handler
35 import android.os.HandlerThread
36 import android.os.Looper
37 import android.os.Message
38 import android.os.Process
39 import android.os.RemoteCallbackList
40 import android.os.RemoteException
41 import android.os.ServiceManager
42 import android.os.UserHandle
43 import android.os.UserManager
44 import android.permission.IOnPermissionsChangeListener
45 import android.permission.PermissionControllerManager
46 import android.permission.PermissionManager
47 import android.provider.Settings
48 import android.util.DebugUtils
49 import android.util.IntArray as GrowingIntArray
50 import android.util.Log
51 import com.android.internal.compat.IPlatformCompat
52 import com.android.internal.logging.MetricsLogger
53 import com.android.internal.logging.nano.MetricsProto
54 import com.android.internal.util.DumpUtils
55 import com.android.internal.util.Preconditions
56 import com.android.server.FgThread
57 import com.android.server.LocalManagerRegistry
58 import com.android.server.LocalServices
59 import com.android.server.PermissionThread
60 import com.android.server.ServiceThread
61 import com.android.server.SystemConfig
62 import com.android.server.permission.access.AccessCheckingService
63 import com.android.server.permission.access.AppOpUri
64 import com.android.server.permission.access.GetStateScope
65 import com.android.server.permission.access.MutateStateScope
66 import com.android.server.permission.access.PermissionUri
67 import com.android.server.permission.access.UidUri
68 import com.android.server.permission.access.appop.UidAppOpPolicy
69 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
70 import com.android.server.permission.access.util.andInv
71 import com.android.server.permission.access.util.hasAnyBit
72 import com.android.server.permission.access.util.hasBits
73 import com.android.server.permission.access.util.withClearedCallingIdentity
74 import com.android.server.pm.KnownPackages
75 import com.android.server.pm.PackageInstallerService
76 import com.android.server.pm.PackageManagerLocal
77 import com.android.server.pm.UserManagerInternal
78 import com.android.server.pm.UserManagerService
79 import com.android.server.pm.parsing.pkg.AndroidPackageUtils
80 import com.android.server.pm.permission.LegacyPermission
81 import com.android.server.pm.permission.Permission as LegacyPermission2
82 import com.android.server.pm.permission.LegacyPermissionSettings
83 import com.android.server.pm.permission.LegacyPermissionState
84 import com.android.server.pm.permission.PermissionManagerServiceInterface
85 import com.android.server.pm.permission.PermissionManagerServiceInternal
86 import com.android.server.pm.pkg.AndroidPackage
87 import com.android.server.pm.pkg.PackageState
88 import com.android.server.policy.SoftRestrictedPermissionPolicy
89 import libcore.util.EmptyArray
90 import java.io.FileDescriptor
91 import java.io.PrintWriter
92 import java.util.concurrent.CompletableFuture
93 import java.util.concurrent.ExecutionException
94 import java.util.concurrent.TimeUnit
95 import java.util.concurrent.TimeoutException
96 
97 /**
98  * Modern implementation of [PermissionManagerServiceInterface].
99  */
100 class PermissionService(
101     private val service: AccessCheckingService
102 ) : PermissionManagerServiceInterface {
103     private val policy =
104         service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
105 
106     private val context = service.context
107     private lateinit var metricsLogger: MetricsLogger
108     private lateinit var packageManagerInternal: PackageManagerInternal
109     private lateinit var packageManagerLocal: PackageManagerLocal
110     private lateinit var platformCompat: IPlatformCompat
111     private lateinit var systemConfig: SystemConfig
112     private lateinit var userManagerInternal: UserManagerInternal
113     private lateinit var userManagerService: UserManagerService
114 
115     private lateinit var handlerThread: HandlerThread
116     private lateinit var handler: Handler
117     private lateinit var onPermissionsChangeListeners: OnPermissionsChangeListeners
118     private lateinit var onPermissionFlagsChangedListener: OnPermissionFlagsChangedListener
119 
120     private val mountedStorageVolumes = IndexedSet<String?>()
121 
122     private lateinit var permissionControllerManager: PermissionControllerManager
123 
124     /**
125      * A permission backup might contain apps that are not installed. In this case we delay the
126      * restoration until the app is installed.
127      *
128      * This array (`userId -> noDelayedBackupLeft`) is `true` for all the users where
129      * there is **no more** delayed backup left.
130      */
131     private val isDelayedPermissionBackupFinished = IntBooleanMap()
132 
133     fun initialize() {
134         metricsLogger = MetricsLogger()
135         packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java)
136         packageManagerLocal =
137             LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
138         platformCompat = IPlatformCompat.Stub.asInterface(
139             ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)
140         )
141         systemConfig = SystemConfig.getInstance()
142         userManagerInternal = LocalServices.getService(UserManagerInternal::class.java)
143         userManagerService = UserManagerService.getInstance()
144 
145         handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true)
146             .apply { start() }
147         handler = Handler(handlerThread.looper)
148         onPermissionsChangeListeners = OnPermissionsChangeListeners(FgThread.get().looper)
149         onPermissionFlagsChangedListener = OnPermissionFlagsChangedListener()
150         policy.addOnPermissionFlagsChangedListener(onPermissionFlagsChangedListener)
151     }
152 
153     override fun getAllPermissionGroups(flags: Int): List<PermissionGroupInfo> {
154         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
155             val callingUid = Binder.getCallingUid()
156             if (snapshot.isUidInstantApp(callingUid)) {
157                 return emptyList()
158             }
159 
160             val permissionGroups = service.getState {
161                 with(policy) { getPermissionGroups() }
162             }
163 
164             return permissionGroups.mapNotNullIndexed { _, _, permissionGroup ->
165                 if (snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) {
166                     permissionGroup.generatePermissionGroupInfo(flags)
167                 } else {
168                     null
169                 }
170             }
171         }
172     }
173 
174     override fun getPermissionGroupInfo(
175         permissionGroupName: String,
176         flags: Int
177     ): PermissionGroupInfo? {
178         val permissionGroup: PermissionGroupInfo
179         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
180             val callingUid = Binder.getCallingUid()
181             if (snapshot.isUidInstantApp(callingUid)) {
182                 return null
183             }
184 
185             permissionGroup = service.getState {
186                 with(policy) { getPermissionGroups()[permissionGroupName] }
187             } ?: return null
188 
189             if (!snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) {
190                 return null
191             }
192         }
193 
194         return permissionGroup.generatePermissionGroupInfo(flags)
195     }
196 
197     /**
198      * Generate a new [PermissionGroupInfo] from [PermissionGroupInfo] and adjust it accordingly.
199      */
200     private fun PermissionGroupInfo.generatePermissionGroupInfo(flags: Int): PermissionGroupInfo =
201         @Suppress("DEPRECATION")
202         PermissionGroupInfo(this).apply {
203             if (!flags.hasBits(PackageManager.GET_META_DATA)) {
204                 metaData = null
205             }
206         }
207 
208     override fun getPermissionInfo(
209         permissionName: String,
210         flags: Int,
211         opPackageName: String
212     ): PermissionInfo? {
213         val permission: Permission
214         val targetSdkVersion: Int
215         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
216             val callingUid = Binder.getCallingUid()
217             if (snapshot.isUidInstantApp(callingUid)) {
218                 return null
219             }
220 
221             permission = service.getState {
222                 with(policy) { getPermissions()[permissionName] }
223             } ?: return null
224 
225             if (!snapshot.isPackageVisibleToUid(permission.packageName, callingUid)) {
226                 return null
227             }
228 
229             val opPackage = snapshot.getPackageState(opPackageName)?.androidPackage
230             targetSdkVersion = when {
231                 // System sees all flags.
232                 isRootOrSystemOrShell(callingUid) -> Build.VERSION_CODES.CUR_DEVELOPMENT
233                 opPackage != null -> opPackage.targetSdkVersion
234                 else -> Build.VERSION_CODES.CUR_DEVELOPMENT
235             }
236         }
237 
238         return permission.generatePermissionInfo(flags, targetSdkVersion)
239     }
240 
241     /**
242      * Generate a new [PermissionInfo] from [Permission] and adjust it accordingly.
243      */
244     private fun Permission.generatePermissionInfo(
245         flags: Int,
246         targetSdkVersion: Int = Build.VERSION_CODES.CUR_DEVELOPMENT
247     ): PermissionInfo =
248         @Suppress("DEPRECATION")
249         PermissionInfo(permissionInfo).apply {
250             // All Permission objects are registered so the PermissionInfo generated for it should
251             // also have FLAG_INSTALLED.
252             this.flags = this.flags or PermissionInfo.FLAG_INSTALLED
253             if (!flags.hasBits(PackageManager.GET_META_DATA)) {
254                 metaData = null
255             }
256             if (targetSdkVersion < Build.VERSION_CODES.O) {
257                 val protection = protection
258                 // Signature permission's protection flags are always reported.
259                 if (protection != PermissionInfo.PROTECTION_SIGNATURE) {
260                     protectionLevel = protection
261                 }
262             }
263         }
264 
265     override fun queryPermissionsByGroup(
266         permissionGroupName: String?,
267         flags: Int
268     ): List<PermissionInfo>? {
269         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
270             val callingUid = Binder.getCallingUid()
271             if (snapshot.isUidInstantApp(callingUid)) {
272                 return null
273             }
274 
275             val permissions: IndexedMap<String, Permission>
276             service.getState {
277                 if (permissionGroupName != null) {
278                     val permissionGroup =
279                         with(policy) { getPermissionGroups()[permissionGroupName] } ?: return null
280 
281                     if (!snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) {
282                         return null
283                     }
284                 }
285 
286                 permissions = with(policy) { getPermissions() }
287             }
288 
289             return permissions.mapNotNullIndexed { _, _, permission ->
290                 if (permission.groupName == permissionGroupName &&
291                     snapshot.isPackageVisibleToUid(permission.packageName, callingUid)
292                 ) {
293                     permission.generatePermissionInfo(flags)
294                 } else {
295                     null
296                 }
297             }
298         }
299     }
300 
301     override fun getAllPermissionsWithProtection(protection: Int): List<PermissionInfo> =
302         getPermissionsWithProtectionOrProtectionFlags { permission ->
303             permission.protection == protection
304         }
305 
306     override fun getAllPermissionsWithProtectionFlags(protectionFlags: Int): List<PermissionInfo> =
307         getPermissionsWithProtectionOrProtectionFlags { permission ->
308             permission.protectionFlags.hasBits(protectionFlags)
309         }
310 
311     private inline fun getPermissionsWithProtectionOrProtectionFlags(
312         predicate: (Permission) -> Boolean
313     ): List<PermissionInfo> {
314         service.getState {
315             with(policy) {
316                 return getPermissions().mapNotNullIndexed { _, _, permission ->
317                     if (predicate(permission)) {
318                         permission.generatePermissionInfo(0)
319                     } else {
320                         null
321                     }
322                 }
323             }
324         }
325     }
326 
327     override fun getPermissionGids(permissionName: String, userId: Int): IntArray {
328         val permission = service.getState {
329             with(policy) { getPermissions()[permissionName] }
330         } ?: return EmptyArray.INT
331         return permission.getGidsForUser(userId)
332     }
333 
334     override fun getInstalledPermissions(packageName: String): Set<String> {
335         requireNotNull(packageName) { "packageName cannot be null" }
336 
337         val permissions = service.getState {
338             with(policy) { getPermissions() }
339         }
340         return permissions.mapNotNullIndexedToSet { _, _, permission ->
341             if (permission.packageName == packageName) {
342                 permission.name
343             } else {
344                 null
345             }
346         }
347     }
348 
349     override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean {
350         val permissionName = permissionInfo.name
351         requireNotNull(permissionName) { "permissionName cannot be null" }
352         val callingUid = Binder.getCallingUid()
353         if (packageManagerLocal.withUnfilteredSnapshot().use { it.isUidInstantApp(callingUid) }) {
354             throw SecurityException("Instant apps cannot add permissions")
355         }
356         if (permissionInfo.labelRes == 0 && permissionInfo.nonLocalizedLabel == null) {
357             throw SecurityException("Label must be specified in permission")
358         }
359         val oldPermission: Permission?
360 
361         service.mutateState {
362             val permissionTree = getAndEnforcePermissionTree(permissionName)
363             enforcePermissionTreeSize(permissionInfo, permissionTree)
364 
365             oldPermission = with(policy) { getPermissions()[permissionName] }
366             if (oldPermission != null && !oldPermission.isDynamic) {
367                 throw SecurityException(
368                     "Not allowed to modify non-dynamic permission $permissionName"
369                 )
370             }
371 
372             permissionInfo.packageName = permissionTree.permissionInfo.packageName
373             @Suppress("DEPRECATION")
374             permissionInfo.protectionLevel =
375                 PermissionInfo.fixProtectionLevel(permissionInfo.protectionLevel)
376 
377             val newPermission = Permission(
378                 permissionInfo, true, Permission.TYPE_DYNAMIC, permissionTree.appId
379             )
380 
381             with(policy) { addPermission(newPermission, !async) }
382         }
383 
384         return oldPermission == null
385     }
386 
387     override fun removePermission(permissionName: String) {
388         val callingUid = Binder.getCallingUid()
389         if (packageManagerLocal.withUnfilteredSnapshot().use { it.isUidInstantApp(callingUid) }) {
390             throw SecurityException("Instant applications don't have access to this method")
391         }
392         service.mutateState {
393             getAndEnforcePermissionTree(permissionName)
394             val permission = with(policy) { getPermissions()[permissionName] } ?: return@mutateState
395 
396             if (!permission.isDynamic) {
397                 // TODO(b/67371907): switch to logging if it fails
398                 throw SecurityException(
399                     "Not allowed to modify non-dynamic permission $permissionName"
400                 )
401             }
402 
403             with(policy) { removePermission(permission) }
404         }
405     }
406     private fun GetStateScope.getAndEnforcePermissionTree(permissionName: String): Permission {
407         val callingUid = Binder.getCallingUid()
408         val permissionTree = with(policy) { findPermissionTree(permissionName) }
409         if (permissionTree != null && permissionTree.appId == UserHandle.getAppId(callingUid)) {
410                 return permissionTree
411         }
412 
413         throw SecurityException(
414             "Calling UID $callingUid is not allowed to add to or remove from the permission tree"
415         )
416     }
417 
418     private fun GetStateScope.enforcePermissionTreeSize(
419         permissionInfo: PermissionInfo,
420         permissionTree: Permission
421     ) {
422         // We calculate the max size of permissions defined by this uid and throw
423         // if that plus the size of 'info' would exceed our stated maximum.
424         if (permissionTree.appId != Process.SYSTEM_UID) {
425             val permissionTreeFootprint = calculatePermissionTreeFootprint(permissionTree)
426             if (permissionTreeFootprint + permissionInfo.calculateFootprint() >
427                 MAX_PERMISSION_TREE_FOOTPRINT
428             ) {
429                 throw SecurityException("Permission tree size cap exceeded")
430             }
431         }
432     }
433 
434     private fun GetStateScope.calculatePermissionTreeFootprint(permissionTree: Permission): Int {
435         var size = 0
436         with(policy) {
437             getPermissions().forEachValueIndexed { _, permission ->
438                 if (permissionTree.appId == permission.appId) {
439                     size += permission.footprint
440                 }
441             }
442         }
443         return size
444     }
445 
446     override fun checkUidPermission(uid: Int, permissionName: String): Int {
447         val userId = UserHandle.getUserId(uid)
448         if (!userManagerInternal.exists(userId)) {
449             return PackageManager.PERMISSION_DENIED
450         }
451 
452         // PackageManagerInternal.getPackage(int) already checks package visibility and enforces
453         // that instant apps can't see shared UIDs. Note that on the contrary,
454         // Note that PackageManagerInternal.getPackage(String) doesn't perform any checks.
455         val androidPackage = packageManagerInternal.getPackage(uid)
456         if (androidPackage != null) {
457             // Note that PackageManagerInternal.getPackageStateInternal() is not filtered.
458             val packageState =
459                 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)
460             if (packageState == null) {
461                 Log.e(
462                     LOG_TAG, "checkUidPermission: PackageState not found for AndroidPackage" +
463                         " $androidPackage"
464                 )
465                 return PackageManager.PERMISSION_DENIED
466             }
467             val isPermissionGranted = service.getState {
468                 isPermissionGranted(packageState, userId, permissionName)
469             }
470             return if (isPermissionGranted) {
471                 PackageManager.PERMISSION_GRANTED
472             } else {
473                 PackageManager.PERMISSION_DENIED
474             }
475         }
476 
477         return if (isSystemUidPermissionGranted(uid, permissionName)) {
478             PackageManager.PERMISSION_GRANTED
479         } else {
480             PackageManager.PERMISSION_DENIED
481         }
482     }
483 
484     /**
485      * Internal implementation that should only be called by [checkUidPermission].
486      */
487     private fun isSystemUidPermissionGranted(uid: Int, permissionName: String): Boolean {
488         val uidPermissions = systemConfig.systemPermissions[uid] ?: return false
489         if (permissionName in uidPermissions) {
490             return true
491         }
492 
493         val fullerPermissionName = FULLER_PERMISSIONS[permissionName]
494         if (fullerPermissionName != null && fullerPermissionName in uidPermissions) {
495             return true
496         }
497 
498         return false
499     }
500 
501     override fun checkPermission(packageName: String, permissionName: String, userId: Int): Int {
502         if (!userManagerInternal.exists(userId)) {
503             return PackageManager.PERMISSION_DENIED
504         }
505 
506         val packageState = packageManagerLocal.withFilteredSnapshot(Binder.getCallingUid(), userId)
507             .use { it.getPackageState(packageName) } ?: return PackageManager.PERMISSION_DENIED
508 
509         val isPermissionGranted = service.getState {
510             isPermissionGranted(packageState, userId, permissionName)
511         }
512         return if (isPermissionGranted) {
513             PackageManager.PERMISSION_GRANTED
514         } else {
515             PackageManager.PERMISSION_DENIED
516         }
517     }
518 
519     /**
520      * Check whether a permission is granted, without any validation on caller.
521      *
522      * This method should always be called for checking whether a permission is granted, instead of
523      * reading permission flags directly from the policy.
524      */
525     private fun GetStateScope.isPermissionGranted(
526         packageState: PackageState,
527         userId: Int,
528         permissionName: String
529     ): Boolean {
530         val appId = packageState.appId
531         // Note that instant apps can't have shared UIDs, so we only need to check the current
532         // package state.
533         val isInstantApp = packageState.getUserStateOrDefault(userId).isInstantApp
534         if (isSinglePermissionGranted(appId, userId, isInstantApp, permissionName)) {
535             return true
536         }
537 
538         val fullerPermissionName = FULLER_PERMISSIONS[permissionName]
539         if (fullerPermissionName != null &&
540             isSinglePermissionGranted(appId, userId, isInstantApp, fullerPermissionName)) {
541             return true
542         }
543 
544         return false
545     }
546 
547     /**
548      * Internal implementation that should only be called by [isPermissionGranted].
549      */
550     private fun GetStateScope.isSinglePermissionGranted(
551         appId: Int,
552         userId: Int,
553         isInstantApp: Boolean,
554         permissionName: String
555     ): Boolean {
556         val flags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
557         if (!PermissionFlags.isPermissionGranted(flags)) {
558             return false
559         }
560 
561         if (isInstantApp) {
562             val permission = with(policy) { getPermissions()[permissionName] } ?: return false
563             if (!permission.isInstant) {
564                 return false
565             }
566         }
567 
568         return true
569     }
570 
571     override fun getGrantedPermissions(packageName: String, userId: Int): Set<String> {
572         requireNotNull(packageName) { "packageName cannot be null" }
573         Preconditions.checkArgumentNonnegative(userId, "userId")
574 
575         val packageState = packageManagerLocal.withUnfilteredSnapshot()
576             .use { it.getPackageState(packageName) }
577         if (packageState == null) {
578             Log.w(LOG_TAG, "getGrantedPermissions: Unknown package $packageName")
579             return emptySet()
580         }
581 
582         service.getState {
583             val permissionFlags = with(policy) { getUidPermissionFlags(packageState.appId, userId) }
584                 ?: return emptySet()
585 
586             return permissionFlags.mapNotNullIndexedToSet { _, permissionName, _ ->
587                 if (isPermissionGranted(packageState, userId, permissionName)) {
588                     permissionName
589                 } else {
590                     null
591                 }
592             }
593         }
594     }
595 
596     override fun getGidsForUid(uid: Int): IntArray {
597         val appId = UserHandle.getAppId(uid)
598         val userId = UserHandle.getUserId(uid)
599         val globalGids = systemConfig.globalGids
600         service.getState {
601             // Different from the old implementation, which returns an empty array when the
602             // permission state is not found, now we always return at least global GIDs. This is
603             // more consistent with the pre-S-refactor behavior. This is also because we are now
604             // actively trimming the per-UID objects when empty.
605             val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) }
606                 ?: return globalGids.copyOf()
607 
608             val gids = GrowingIntArray.wrap(globalGids)
609             permissionFlags.forEachIndexed { _, permissionName, flags ->
610                 if (!PermissionFlags.isPermissionGranted(flags)) {
611                     return@forEachIndexed
612                 }
613 
614                 val permission = with(policy) { getPermissions()[permissionName] }
615                     ?: return@forEachIndexed
616                 val permissionGids = permission.getGidsForUser(userId)
617                 if (permissionGids.isEmpty()) {
618                     return@forEachIndexed
619                 }
620                 gids.addAll(permissionGids)
621             }
622             return gids.toArray()
623         }
624     }
625 
626     override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) {
627         setRuntimePermissionGranted(packageName, userId, permissionName, isGranted = true)
628     }
629 
630     override fun revokeRuntimePermission(
631         packageName: String,
632         permissionName: String,
633         userId: Int,
634         reason: String?
635     ) {
636         setRuntimePermissionGranted(
637             packageName, userId, permissionName, isGranted = false, revokeReason = reason
638         )
639     }
640 
641     override fun revokePostNotificationPermissionWithoutKillForTest(
642         packageName: String,
643         userId: Int
644     ) {
645         setRuntimePermissionGranted(
646             packageName, userId, Manifest.permission.POST_NOTIFICATIONS, isGranted = false,
647             skipKillUid = true
648         )
649     }
650 
651     /**
652      * Shared internal implementation that should only be called by [grantRuntimePermission],
653      * [revokeRuntimePermission] and [revokePostNotificationPermissionWithoutKillForTest].
654      */
655     private fun setRuntimePermissionGranted(
656         packageName: String,
657         userId: Int,
658         permissionName: String,
659         isGranted: Boolean,
660         skipKillUid: Boolean = false,
661         revokeReason: String? = null
662     ) {
663         val methodName = if (isGranted) "grantRuntimePermission" else "revokeRuntimePermission"
664         val callingUid = Binder.getCallingUid()
665         val isDebugEnabled = if (isGranted) {
666             PermissionManager.DEBUG_TRACE_GRANTS
667         } else {
668             PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
669         }
670         if (isDebugEnabled &&
671             PermissionManager.shouldTraceGrant(packageName, permissionName, userId)) {
672             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
673             Log.i(
674                 LOG_TAG, "$methodName(packageName = $packageName," +
675                     " permissionName = $permissionName" +
676                     (if (isGranted) "" else "skipKillUid = $skipKillUid, reason = $revokeReason") +
677                     ", userId = $userId," + " callingUid = $callingUidName ($callingUid))",
678                 RuntimeException()
679             )
680         }
681 
682         if (!userManagerInternal.exists(userId)) {
683             Log.w(LOG_TAG, "$methodName: Unknown user $userId")
684             return
685         }
686 
687         enforceCallingOrSelfCrossUserPermission(
688             userId, enforceFullPermission = true, enforceShellRestriction = true, methodName
689         )
690         val enforcedPermissionName = if (isGranted) {
691             Manifest.permission.GRANT_RUNTIME_PERMISSIONS
692         } else {
693             Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
694         }
695         context.enforceCallingOrSelfPermission(enforcedPermissionName, methodName)
696 
697         val packageState: PackageState?
698         val permissionControllerPackageName = packageManagerInternal.getKnownPackageNames(
699             KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
700         ).first()
701         val permissionControllerPackageState: PackageState?
702         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
703             packageState = snapshot.filtered(callingUid, userId)
704                 .use { it.getPackageState(packageName) }
705             permissionControllerPackageState =
706                 snapshot.getPackageState(permissionControllerPackageName)
707         }
708         val androidPackage = packageState?.androidPackage
709         // Different from the old implementation, which returns when package doesn't exist but
710         // throws when package exists but isn't visible, we now return in both cases to avoid
711         // leaking the package existence.
712         if (androidPackage == null) {
713             Log.w(LOG_TAG, "$methodName: Unknown package $packageName")
714             return
715         }
716 
717         val canManageRolePermission = isRootOrSystem(callingUid) ||
718             UserHandle.getAppId(callingUid) == permissionControllerPackageState!!.appId
719         val overridePolicyFixed = context.checkCallingOrSelfPermission(
720             Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
721         ) == PackageManager.PERMISSION_GRANTED
722 
723         service.mutateState {
724             with(onPermissionFlagsChangedListener) {
725                 if (skipKillUid) {
726                     skipKillRuntimePermissionRevokedUids()
727                 }
728                 if (revokeReason != null) {
729                     addKillRuntimePermissionRevokedUidsReason(revokeReason)
730                 }
731             }
732 
733             setRuntimePermissionGranted(
734                 packageState, userId, permissionName, isGranted, canManageRolePermission,
735                 overridePolicyFixed, reportError = true, methodName
736             )
737         }
738     }
739 
740     private fun setRequestedPermissionStates(
741         packageState: PackageState,
742         userId: Int,
743         permissionStates: IndexedMap<String, Int>
744     ) {
745         service.mutateState {
746             permissionStates.forEachIndexed { _, permissionName, permissionState ->
747                 when (permissionState) {
748                     PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED,
749                     PackageInstaller.SessionParams.PERMISSION_STATE_DENIED -> {}
750                     else -> {
751                         Log.w(
752                             LOG_TAG, "setRequestedPermissionStates: Unknown permission state" +
753                             " $permissionState for permission $permissionName"
754                         )
755                         return@forEachIndexed
756                     }
757                 }
758                 if (permissionName !in packageState.androidPackage!!.requestedPermissions) {
759                     return@forEachIndexed
760                 }
761                 val permission = with(policy) { getPermissions()[permissionName] }
762                     ?: return@forEachIndexed
763                 when {
764                     permission.isDevelopment || permission.isRuntime -> {
765                         if (permissionState ==
766                             PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED) {
767                             setRuntimePermissionGranted(
768                                 packageState, userId, permissionName, isGranted = true,
769                                 canManageRolePermission = false, overridePolicyFixed = false,
770                                 reportError = false, "setRequestedPermissionStates"
771                             )
772                         }
773                     }
774                     permission.isAppOp && permissionName in
775                             PackageInstallerService.INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS ->
776                         setAppOpPermissionGranted(
777                             packageState, userId, permissionName, permissionState ==
778                                     PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED
779                         )
780                     else -> {}
781                 }
782             }
783         }
784     }
785 
786     /**
787      * Set whether a runtime permission is granted, without any validation on caller.
788      */
789     private fun MutateStateScope.setRuntimePermissionGranted(
790         packageState: PackageState,
791         userId: Int,
792         permissionName: String,
793         isGranted: Boolean,
794         canManageRolePermission: Boolean,
795         overridePolicyFixed: Boolean,
796         reportError: Boolean,
797         methodName: String
798     ) {
799         val permission = with(policy) { getPermissions()[permissionName] }
800         if (permission == null) {
801             if (reportError) {
802                 throw IllegalArgumentException("Unknown permission $permissionName")
803             }
804             return
805         }
806 
807         val androidPackage = packageState.androidPackage!!
808         val packageName = packageState.packageName
809         when {
810             permission.isDevelopment -> {}
811             permission.isRole -> {
812                 if (!canManageRolePermission) {
813                     if (reportError) {
814                         throw SecurityException("Permission $permissionName is managed by role")
815                     }
816                     return
817                 }
818             }
819             permission.isRuntime -> {
820                 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M) {
821                     // If a permission review is required for legacy apps we represent
822                     // their permissions as always granted
823                     return
824                 }
825                 if (isGranted && packageState.getUserStateOrDefault(userId).isInstantApp &&
826                     !permission.isInstant) {
827                     if (reportError) {
828                         throw SecurityException(
829                             "Cannot grant non-instant permission $permissionName to package" +
830                                 " $packageName"
831                         )
832                     }
833                     return
834                 }
835             }
836             else -> {
837                 if (reportError) {
838                     throw SecurityException(
839                         "Permission $permissionName requested by package $packageName is not a" +
840                             " changeable permission type"
841                     )
842                 }
843                 return
844             }
845         }
846 
847         val appId = packageState.appId
848         val oldFlags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
849 
850         if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) {
851             if (reportError) {
852                 throw SecurityException(
853                     "Permission $permissionName isn't requested by package $packageName"
854                 )
855             }
856             return
857         }
858 
859         if (oldFlags.hasBits(PermissionFlags.SYSTEM_FIXED)) {
860             if (reportError) {
861                 Log.e(
862                     LOG_TAG, "$methodName: Cannot change system fixed permission $permissionName" +
863                         " for package $packageName"
864                 )
865             }
866             return
867         }
868 
869         if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED) && !overridePolicyFixed) {
870             if (reportError) {
871                 Log.e(
872                     LOG_TAG, "$methodName: Cannot change policy fixed permission $permissionName" +
873                         " for package $packageName"
874                 )
875             }
876             return
877         }
878 
879         if (isGranted && oldFlags.hasBits(PermissionFlags.RESTRICTION_REVOKED)) {
880             if (reportError) {
881                 Log.e(
882                     LOG_TAG, "$methodName: Cannot grant hard-restricted non-exempt permission" +
883                         " $permissionName to package $packageName"
884                 )
885             }
886             return
887         }
888 
889         if (isGranted && oldFlags.hasBits(PermissionFlags.SOFT_RESTRICTED)) {
890             // TODO: Refactor SoftRestrictedPermissionPolicy.
891             val softRestrictedPermissionPolicy = SoftRestrictedPermissionPolicy.forPermission(
892                 context, AndroidPackageUtils.generateAppInfoWithoutState(androidPackage),
893                 androidPackage, UserHandle.of(userId), permissionName
894             )
895             if (!softRestrictedPermissionPolicy.mayGrantPermission()) {
896                 if (reportError) {
897                     Log.e(
898                         LOG_TAG, "$methodName: Cannot grant soft-restricted non-exempt permission" +
899                             " $permissionName to package $packageName"
900                     )
901                 }
902                 return
903             }
904         }
905 
906         val newFlags = PermissionFlags.updateRuntimePermissionGranted(oldFlags, isGranted)
907         if (oldFlags == newFlags) {
908             return
909         }
910 
911         with(policy) { setPermissionFlags(appId, userId, permissionName, newFlags) }
912 
913         if (permission.isRuntime) {
914             val action = if (isGranted) {
915                 MetricsProto.MetricsEvent.ACTION_PERMISSION_GRANTED
916             } else {
917                 MetricsProto.MetricsEvent.ACTION_PERMISSION_REVOKED
918             }
919             val log = LogMaker(action).apply {
920                 setPackageName(packageName)
921                 addTaggedData(MetricsProto.MetricsEvent.FIELD_PERMISSION, permissionName)
922             }
923             metricsLogger.write(log)
924         }
925     }
926 
927     private fun MutateStateScope.setAppOpPermissionGranted(
928         packageState: PackageState,
929         userId: Int,
930         permissionName: String,
931         isGranted: Boolean
932     ) {
933         val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as UidAppOpPolicy
934         val appOpName = AppOpsManager.permissionToOp(permissionName)
935         val mode = if (isGranted) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
936         with(appOpPolicy) { setAppOpMode(packageState.appId, userId, appOpName, mode) }
937     }
938 
939     override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int {
940         if (!userManagerInternal.exists(userId)) {
941             Log.w(LOG_TAG, "getPermissionFlags: Unknown user $userId")
942             return 0
943         }
944 
945         enforceCallingOrSelfCrossUserPermission(
946             userId, enforceFullPermission = true, enforceShellRestriction = false,
947             "getPermissionFlags"
948         )
949         enforceCallingOrSelfAnyPermission(
950             "getPermissionFlags", Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
951             Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
952             Manifest.permission.GET_RUNTIME_PERMISSIONS
953         )
954 
955         val packageState = packageManagerLocal.withFilteredSnapshot()
956             .use { it.getPackageState(packageName) }
957         if (packageState == null) {
958             Log.w(LOG_TAG, "getPermissionFlags: Unknown package $packageName")
959             return 0
960         }
961 
962         service.getState {
963             val permission = with(policy) { getPermissions()[permissionName] }
964             if (permission == null) {
965                 Log.w(LOG_TAG, "getPermissionFlags: Unknown permission $permissionName")
966                 return 0
967             }
968 
969             val flags =
970                 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) }
971             return PermissionFlags.toApiFlags(flags)
972         }
973     }
974 
975     override fun isPermissionRevokedByPolicy(
976         packageName: String,
977         permissionName: String,
978         userId: Int
979     ): Boolean {
980         if (!userManagerInternal.exists(userId)) {
981             Log.w(LOG_TAG, "isPermissionRevokedByPolicy: Unknown user $userId")
982             return false
983         }
984 
985         enforceCallingOrSelfCrossUserPermission(
986             userId, enforceFullPermission = true, enforceShellRestriction = false,
987             "isPermissionRevokedByPolicy"
988         )
989 
990         val packageState = packageManagerLocal.withFilteredSnapshot(Binder.getCallingUid(), userId)
991             .use { it.getPackageState(packageName) } ?: return false
992 
993         service.getState {
994             if (isPermissionGranted(packageState, userId, permissionName)) {
995                 return false
996             }
997 
998             val flags = with(policy) {
999                 getPermissionFlags(packageState.appId, userId, permissionName)
1000             }
1001             return flags.hasBits(PermissionFlags.POLICY_FIXED)
1002         }
1003     }
1004 
1005     override fun isPermissionsReviewRequired(packageName: String, userId: Int): Boolean {
1006         requireNotNull(packageName) { "packageName cannot be null" }
1007         // TODO(b/173235285): Some caller may pass USER_ALL as userId.
1008         // Preconditions.checkArgumentNonnegative(userId, "userId")
1009 
1010         val packageState = packageManagerLocal.withUnfilteredSnapshot()
1011             .use { it.getPackageState(packageName) } ?: return false
1012 
1013         val permissionFlags = service.getState {
1014             with(policy) { getUidPermissionFlags(packageState.appId, userId) }
1015         } ?: return false
1016         return permissionFlags.anyIndexed { _, _, it -> it.hasBits(REVIEW_REQUIRED_FLAGS) }
1017     }
1018 
1019     override fun shouldShowRequestPermissionRationale(
1020         packageName: String,
1021         permissionName: String,
1022         userId: Int
1023     ): Boolean {
1024         if (!userManagerInternal.exists(userId)) {
1025             Log.w(LOG_TAG, "shouldShowRequestPermissionRationale: Unknown user $userId")
1026             return false
1027         }
1028 
1029         enforceCallingOrSelfCrossUserPermission(
1030             userId, enforceFullPermission = true, enforceShellRestriction = false,
1031             "shouldShowRequestPermissionRationale"
1032         )
1033 
1034         val callingUid = Binder.getCallingUid()
1035         val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId)
1036             .use { it.getPackageState(packageName) } ?: return false
1037         val appId = packageState.appId
1038         if (UserHandle.getAppId(callingUid) != appId) {
1039             return false
1040         }
1041 
1042         val flags: Int
1043         service.getState {
1044             if (isPermissionGranted(packageState, userId, permissionName)) {
1045                 return false
1046             }
1047 
1048             flags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
1049         }
1050         if (flags.hasAnyBit(UNREQUESTABLE_MASK)) {
1051             return false
1052         }
1053 
1054         if (permissionName == Manifest.permission.ACCESS_BACKGROUND_LOCATION) {
1055             val isBackgroundRationaleChangeEnabled = Binder::class.withClearedCallingIdentity {
1056                 try {
1057                     platformCompat.isChangeEnabledByPackageName(
1058                         BACKGROUND_RATIONALE_CHANGE_ID, packageName, userId
1059                     )
1060                 } catch (e: RemoteException) {
1061                     Log.e(LOG_TAG, "shouldShowRequestPermissionRationale: Unable to check if" +
1062                         " compatibility change is enabled", e)
1063                     false
1064                 }
1065             }
1066             if (isBackgroundRationaleChangeEnabled) {
1067                 return true
1068             }
1069         }
1070 
1071         return flags.hasBits(PermissionFlags.USER_SET)
1072     }
1073 
1074     override fun updatePermissionFlags(
1075         packageName: String,
1076         permissionName: String,
1077         flagMask: Int,
1078         flagValues: Int,
1079         enforceAdjustPolicyPermission: Boolean,
1080         userId: Int
1081     ) {
1082         val callingUid = Binder.getCallingUid()
1083         if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES &&
1084             PermissionManager.shouldTraceGrant(packageName, permissionName, userId)) {
1085             val flagMaskString = DebugUtils.flagsToString(
1086                 PackageManager::class.java, "FLAG_PERMISSION_", flagMask.toLong()
1087             )
1088             val flagValuesString = DebugUtils.flagsToString(
1089                 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong()
1090             )
1091             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
1092             Log.i(
1093                 LOG_TAG, "updatePermissionFlags(packageName = $packageName," +
1094                     " permissionName = $permissionName, flagMask = $flagMaskString," +
1095                     " flagValues = $flagValuesString, userId = $userId," +
1096                     " callingUid = $callingUidName ($callingUid))", RuntimeException()
1097             )
1098         }
1099 
1100         if (!userManagerInternal.exists(userId)) {
1101             Log.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId")
1102             return
1103         }
1104 
1105         enforceCallingOrSelfCrossUserPermission(
1106             userId, enforceFullPermission = true, enforceShellRestriction = true,
1107             "updatePermissionFlags"
1108         )
1109         enforceCallingOrSelfAnyPermission(
1110             "updatePermissionFlags", Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1111             Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
1112         )
1113 
1114         // Different from the old implementation, which implicitly didn't allow modifying the
1115         // POLICY_FIXED flag if the caller is system or root UID, now we do allow that since system
1116         // and root UIDs are supposed to have all permissions including
1117         // ADJUST_RUNTIME_PERMISSIONS_POLICY.
1118         if (!isRootOrSystem(callingUid)) {
1119             if (flagMask.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) {
1120                 if (enforceAdjustPolicyPermission) {
1121                     context.enforceCallingOrSelfPermission(
1122                         Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
1123                         "Need ${Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY} to change" +
1124                             " policy flags"
1125                     )
1126                 } else {
1127                     val targetSdkVersion = packageManagerInternal.getUidTargetSdkVersion(callingUid)
1128                     require(targetSdkVersion < Build.VERSION_CODES.Q) {
1129                         "${Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY} needs to be" +
1130                             " checked for packages targeting ${Build.VERSION_CODES.Q} or later" +
1131                             " when changing policy flags"
1132                     }
1133                 }
1134             }
1135         }
1136 
1137         // Using PackageManagerInternal instead of PackageManagerLocal for now due to need to access
1138         // shared user packages.
1139         // TODO: We probably shouldn't check the share user packages, since the package name is
1140         //  explicitly provided and grantRuntimePermission() isn't checking shared user packages
1141         //  anyway.
1142         val packageState = packageManagerInternal.getPackageStateInternal(packageName)
1143         val androidPackage = packageState?.androidPackage
1144         // Different from the old implementation, which returns when package doesn't exist but
1145         // throws when package exists but isn't visible, we now return in both cases to avoid
1146         // leaking the package existence.
1147         if (androidPackage == null ||
1148             packageManagerInternal.filterAppAccess(packageName, callingUid, userId, false)) {
1149             Log.w(LOG_TAG, "updatePermissionFlags: Unknown package $packageName")
1150             return
1151         }
1152 
1153         val isPermissionRequested = if (permissionName in androidPackage.requestedPermissions) {
1154             // Fast path, the current package has requested the permission.
1155             true
1156         } else {
1157             // Slow path, go through all shared user packages.
1158             val sharedUserPackageNames =
1159                 packageManagerInternal.getSharedUserPackagesForPackage(packageName, userId)
1160             sharedUserPackageNames.any { sharedUserPackageName ->
1161                 val sharedUserPackage = packageManagerInternal.getPackage(sharedUserPackageName)
1162                 sharedUserPackage != null &&
1163                     permissionName in sharedUserPackage.requestedPermissions
1164             }
1165         }
1166 
1167         val appId = packageState.appId
1168         service.mutateState {
1169             updatePermissionFlags(
1170                 appId, userId, permissionName, flagMask, flagValues,
1171                 reportErrorForUnknownPermission = true, isPermissionRequested,
1172                 "updatePermissionFlags", packageName
1173             )
1174         }
1175     }
1176 
1177     override fun updatePermissionFlagsForAllApps(flagMask: Int, flagValues: Int, userId: Int) {
1178         val callingUid = Binder.getCallingUid()
1179         if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES) {
1180             val flagMaskString = DebugUtils.flagsToString(
1181                 PackageManager::class.java, "FLAG_PERMISSION_", flagMask.toLong()
1182             )
1183             val flagValuesString = DebugUtils.flagsToString(
1184                 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong()
1185             )
1186             val callingUidName = packageManagerInternal.getNameForUid(callingUid)
1187             Log.i(
1188                 LOG_TAG, "updatePermissionFlagsForAllApps(flagMask = $flagMaskString," +
1189                     " flagValues = $flagValuesString, userId = $userId," +
1190                     " callingUid = $callingUidName ($callingUid))", RuntimeException()
1191             )
1192         }
1193 
1194         if (!userManagerInternal.exists(userId)) {
1195             Log.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId")
1196             return
1197         }
1198 
1199         enforceCallingOrSelfCrossUserPermission(
1200             userId, enforceFullPermission = true, enforceShellRestriction = true,
1201             "updatePermissionFlagsForAllApps"
1202         )
1203         enforceCallingOrSelfAnyPermission(
1204             "updatePermissionFlagsForAllApps", Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
1205             Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
1206         )
1207 
1208         val packageStates = packageManagerLocal.withUnfilteredSnapshot()
1209             .use { it.packageStates }
1210         service.mutateState {
1211             packageStates.forEach { (packageName, packageState) ->
1212                 val androidPackage = packageState.androidPackage ?: return@forEach
1213                 androidPackage.requestedPermissions.forEach { permissionName ->
1214                     // Different from the old implementation, which only sanitized the SYSTEM_FIXED
1215                     // flag, we now properly sanitize all flags as in updatePermissionFlags().
1216                     updatePermissionFlags(
1217                         packageState.appId, userId, permissionName, flagMask, flagValues,
1218                         reportErrorForUnknownPermission = false, isPermissionRequested = true,
1219                         "updatePermissionFlagsForAllApps", packageName
1220                     )
1221                 }
1222             }
1223         }
1224     }
1225 
1226     /**
1227      * Shared internal implementation that should only be called by [updatePermissionFlags] and
1228      * [updatePermissionFlagsForAllApps].
1229      */
1230     private fun MutateStateScope.updatePermissionFlags(
1231         appId: Int,
1232         userId: Int,
1233         permissionName: String,
1234         flagMask: Int,
1235         flagValues: Int,
1236         reportErrorForUnknownPermission: Boolean,
1237         isPermissionRequested: Boolean,
1238         methodName: String,
1239         packageName: String
1240     ) {
1241         // Different from the old implementation, which only allowed the system UID to modify the
1242         // following flags, we now allow the root UID as well since both should have all
1243         // permissions.
1244         // Only the system can change these flags and nothing else.
1245         val callingUid = Binder.getCallingUid()
1246         @Suppress("NAME_SHADOWING")
1247         var flagMask = flagMask
1248         @Suppress("NAME_SHADOWING")
1249         var flagValues = flagValues
1250         if (!isRootOrSystem(callingUid)) {
1251             // Different from the old implementation, which allowed non-system UIDs to remove (but
1252             // not add) permission restriction flags, we now consistently ignore them altogether.
1253             val ignoredMask = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED or
1254                 PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT or
1255                 // REVIEW_REQUIRED can be set on any permission by the shell, or by any app for the
1256                 // NOTIFICATIONS permissions specifically.
1257                 if (isShell(callingUid) || permissionName in NOTIFICATIONS_PERMISSIONS) {
1258                     0
1259                 } else {
1260                     PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
1261                 } or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or
1262                 PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or
1263                 PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or
1264                 PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
1265             flagMask = flagMask andInv ignoredMask
1266             flagValues = flagValues andInv ignoredMask
1267         }
1268 
1269         val permission = with(policy) { getPermissions()[permissionName] }
1270         if (permission == null) {
1271             if (reportErrorForUnknownPermission) {
1272                 throw IllegalArgumentException("Unknown permission $permissionName")
1273             }
1274             return
1275         }
1276 
1277         val oldFlags = with(policy) { getPermissionFlags(appId, userId, permissionName) }
1278         if (!isPermissionRequested && oldFlags == 0) {
1279             Log.w(
1280                 LOG_TAG, "$methodName: Permission $permissionName isn't requested by package" +
1281                     " $packageName"
1282             )
1283             return
1284         }
1285 
1286         val newFlags = PermissionFlags.updateFlags(permission, oldFlags, flagMask, flagValues)
1287         with(policy) { setPermissionFlags(appId, userId, permissionName, newFlags) }
1288     }
1289 
1290     override fun getAllowlistedRestrictedPermissions(
1291         packageName: String,
1292         allowlistedFlags: Int,
1293         userId: Int
1294     ): IndexedList<String>? {
1295         requireNotNull(packageName) { "packageName cannot be null" }
1296         Preconditions.checkFlagsArgument(allowlistedFlags, PERMISSION_ALLOWLIST_MASK)
1297         Preconditions.checkArgumentNonnegative(userId, "userId cannot be null")
1298 
1299         if (!userManagerInternal.exists(userId)) {
1300             Log.w(LOG_TAG, "AllowlistedRestrictedPermission api: Unknown user $userId")
1301             return null
1302         }
1303 
1304         enforceCallingOrSelfCrossUserPermission(
1305             userId, enforceFullPermission = false, enforceShellRestriction = false,
1306             "getAllowlistedRestrictedPermissions"
1307         )
1308 
1309         val callingUid = Binder.getCallingUid()
1310         val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId)
1311             .use { it.getPackageState(packageName) } ?: return null
1312         val androidPackage = packageState.androidPackage ?: return null
1313 
1314         val isCallerPrivileged = context.checkCallingOrSelfPermission(
1315             Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1316         ) == PackageManager.PERMISSION_GRANTED
1317 
1318         if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) &&
1319             !isCallerPrivileged) {
1320             throw SecurityException(
1321                 "Querying system allowlist requires " +
1322                     Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1323             )
1324         }
1325 
1326         val isCallerInstallerOnRecord =
1327             packageManagerInternal.isCallerInstallerOfRecord(androidPackage, callingUid)
1328 
1329         if (allowlistedFlags.hasAnyBit(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE or
1330                 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) {
1331             if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1332                 throw SecurityException(
1333                     "Querying upgrade or installer allowlist requires being installer on record" +
1334                         " or ${Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS}"
1335                 )
1336             }
1337         }
1338 
1339         return getAllowlistedRestrictedPermissionsUnchecked(
1340             packageState.appId, allowlistedFlags, userId
1341         )
1342     }
1343 
1344     /**
1345      * This method does not enforce checks on the caller, should only be called after
1346      * required checks.
1347      */
1348     private fun getAllowlistedRestrictedPermissionsUnchecked(
1349         appId: Int,
1350         allowlistedFlags: Int,
1351         userId: Int
1352     ): IndexedList<String>? {
1353         val permissionFlags = service.getState {
1354             with(policy) { getUidPermissionFlags(appId, userId) }
1355         } ?: return null
1356 
1357         var queryFlags = 0
1358         if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM)) {
1359             queryFlags = queryFlags or PermissionFlags.SYSTEM_EXEMPT
1360         }
1361         if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE)) {
1362             queryFlags = queryFlags or PermissionFlags.UPGRADE_EXEMPT
1363         }
1364         if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) {
1365             queryFlags = queryFlags or PermissionFlags.INSTALLER_EXEMPT
1366         }
1367 
1368         return permissionFlags.mapNotNullIndexed { _, permissionName, flags ->
1369             if (flags.hasAnyBit(queryFlags)) permissionName else null
1370         }
1371     }
1372 
1373     override fun addAllowlistedRestrictedPermission(
1374         packageName: String,
1375         permissionName: String,
1376         allowlistedFlags: Int,
1377         userId: Int
1378     ): Boolean {
1379         requireNotNull(permissionName) { "permissionName cannot be null" }
1380         if (!enforceRestrictedPermission(permissionName)) {
1381             return false
1382         }
1383 
1384         val permissionNames = getAllowlistedRestrictedPermissions(
1385             packageName, allowlistedFlags, userId
1386         ) ?: IndexedList(1)
1387 
1388         if (permissionName !in permissionNames) {
1389             permissionNames += permissionName
1390             return setAllowlistedRestrictedPermissions(
1391                 packageName, permissionNames, allowlistedFlags, userId, isAddingPermission = true
1392             )
1393         }
1394         return false
1395     }
1396 
1397     private fun addAllowlistedRestrictedPermissionsUnchecked(
1398         androidPackage: AndroidPackage,
1399         appId: Int,
1400         permissionNames: List<String>,
1401         userId: Int
1402     ) {
1403         val newPermissionNames = getAllowlistedRestrictedPermissionsUnchecked(appId,
1404             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId
1405         )?.let {
1406             IndexedSet(permissionNames).apply { this += it }.toList()
1407         } ?: permissionNames
1408 
1409         setAllowlistedRestrictedPermissionsUnchecked(androidPackage, appId, newPermissionNames,
1410             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId)
1411     }
1412 
1413     override fun removeAllowlistedRestrictedPermission(
1414         packageName: String,
1415         permissionName: String,
1416         allowlistedFlags: Int,
1417         userId: Int
1418     ): Boolean {
1419         requireNotNull(permissionName) { "permissionName cannot be null" }
1420         if (!enforceRestrictedPermission(permissionName)) {
1421             return false
1422         }
1423 
1424         val permissions = getAllowlistedRestrictedPermissions(
1425             packageName, allowlistedFlags, userId
1426         ) ?: return false
1427 
1428         if (permissions.remove(permissionName)) {
1429             return setAllowlistedRestrictedPermissions(
1430                 packageName, permissions, allowlistedFlags, userId, isAddingPermission = false
1431             )
1432         }
1433 
1434         return false
1435     }
1436 
1437     private fun enforceRestrictedPermission(permissionName: String): Boolean {
1438         val permission = service.getState { with(policy) { getPermissions()[permissionName] } }
1439         if (permission == null) {
1440             Log.w(LOG_TAG, "permission definition for $permissionName does not exist")
1441             return false
1442         }
1443 
1444         if (packageManagerLocal.withFilteredSnapshot()
1445                 .use { it.getPackageState(permission.packageName) } == null) {
1446             return false
1447         }
1448 
1449         val isImmutablyRestrictedPermission =
1450             permission.isHardOrSoftRestricted && permission.isImmutablyRestricted
1451         if (isImmutablyRestrictedPermission && context.checkCallingOrSelfPermission(
1452                 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1453             ) != PackageManager.PERMISSION_GRANTED) {
1454             throw SecurityException(
1455                 "Cannot modify allowlist of an immutably restricted permission: ${permission.name}"
1456             )
1457         }
1458 
1459         return true
1460     }
1461 
1462     private fun setAllowlistedRestrictedPermissions(
1463         packageName: String,
1464         permissionNames: List<String>,
1465         allowlistedFlags: Int,
1466         userId: Int,
1467         isAddingPermission: Boolean
1468     ): Boolean {
1469         Preconditions.checkArgument(allowlistedFlags.countOneBits() == 1)
1470 
1471         val isCallerPrivileged = context.checkCallingOrSelfPermission(
1472             Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1473         ) == PackageManager.PERMISSION_GRANTED
1474 
1475         val callingUid = Binder.getCallingUid()
1476         val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId)
1477             .use { snapshot -> snapshot.packageStates[packageName] ?: return false }
1478         val androidPackage = packageState.androidPackage ?: return false
1479 
1480         val isCallerInstallerOnRecord =
1481             packageManagerInternal.isCallerInstallerOfRecord(androidPackage, callingUid)
1482 
1483         if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE)) {
1484             if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
1485                 throw SecurityException(
1486                     "Modifying upgrade allowlist requires being installer on record or " +
1487                         Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1488                 )
1489             }
1490             if (isAddingPermission && !isCallerPrivileged) {
1491                 throw SecurityException(
1492                     "Adding to upgrade allowlist requires" +
1493                         Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS
1494                 )
1495             }
1496         }
1497 
1498         setAllowlistedRestrictedPermissionsUnchecked(
1499             androidPackage, packageState.appId, permissionNames, allowlistedFlags, userId
1500         )
1501 
1502         return true
1503     }
1504 
1505     /**
1506      * This method does not enforce checks on the caller, should only be called after
1507      * required checks.
1508      */
1509     private fun setAllowlistedRestrictedPermissionsUnchecked(
1510         androidPackage: AndroidPackage,
1511         appId: Int,
1512         permissionNames: List<String>,
1513         allowlistedFlags: Int,
1514         userId: Int
1515     ) {
1516         service.mutateState {
1517             with(policy) {
1518                 val permissionsFlags =
1519                     getUidPermissionFlags(appId, userId) ?: return@mutateState
1520 
1521                 val permissions = getPermissions()
1522                 androidPackage.requestedPermissions.forEachIndexed { _, requestedPermission ->
1523                     val permission = permissions[requestedPermission]
1524                     if (permission == null || !permission.isHardOrSoftRestricted) {
1525                         return@forEachIndexed
1526                     }
1527 
1528                     val oldFlags = permissionsFlags[requestedPermission] ?: 0
1529                     val wasGranted = PermissionFlags.isPermissionGranted(oldFlags)
1530 
1531                     var newFlags = oldFlags
1532                     var mask = 0
1533                     var allowlistFlagsCopy = allowlistedFlags
1534                     while (allowlistFlagsCopy != 0) {
1535                         val flag = 1 shl allowlistFlagsCopy.countTrailingZeroBits()
1536                         allowlistFlagsCopy = allowlistFlagsCopy and flag.inv()
1537                         when (flag) {
1538                             PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM -> {
1539                                 mask = mask or PermissionFlags.SYSTEM_EXEMPT
1540                                 newFlags =
1541                                     if (permissionNames.contains(requestedPermission)) {
1542                                         newFlags or PermissionFlags.SYSTEM_EXEMPT
1543                                     } else {
1544                                         newFlags andInv PermissionFlags.SYSTEM_EXEMPT
1545                                     }
1546                             }
1547                             PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE -> {
1548                                 mask = mask or PermissionFlags.UPGRADE_EXEMPT
1549                                 newFlags =
1550                                     if (permissionNames.contains(requestedPermission)) {
1551                                         newFlags or PermissionFlags.UPGRADE_EXEMPT
1552                                     } else {
1553                                         newFlags andInv PermissionFlags.UPGRADE_EXEMPT
1554                                     }
1555                             }
1556                             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER -> {
1557                                 mask = mask or PermissionFlags.INSTALLER_EXEMPT
1558                                 newFlags =
1559                                     if (permissionNames.contains(requestedPermission)) {
1560                                         newFlags or PermissionFlags.INSTALLER_EXEMPT
1561                                     } else {
1562                                         newFlags andInv PermissionFlags.INSTALLER_EXEMPT
1563                                     }
1564                             }
1565                         }
1566                     }
1567 
1568                     if (oldFlags == newFlags) {
1569                         return@forEachIndexed
1570                     }
1571 
1572                     val wasAllowlisted = oldFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
1573                     val isAllowlisted = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)
1574 
1575                     // If the permission is policy fixed as granted but it is no longer
1576                     // on any of the allowlists we need to clear the policy fixed flag
1577                     // as allowlisting trumps policy i.e. policy cannot grant a non
1578                     // grantable permission.
1579                     if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED)) {
1580                         if (!isAllowlisted && wasGranted) {
1581                             mask = mask or PermissionFlags.POLICY_FIXED
1582                             newFlags = newFlags andInv PermissionFlags.POLICY_FIXED
1583                         }
1584                     }
1585 
1586                     // If we are allowlisting an app that does not support runtime permissions
1587                     // we need to make sure it goes through the permission review UI at launch.
1588                     if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M &&
1589                         !wasAllowlisted && isAllowlisted) {
1590                         mask = mask or PermissionFlags.IMPLICIT
1591                         newFlags = newFlags or PermissionFlags.IMPLICIT
1592                     }
1593 
1594                     updatePermissionFlags(
1595                         appId, userId, requestedPermission, mask, newFlags
1596                     )
1597                 }
1598             }
1599         }
1600     }
1601 
1602     override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) {
1603         // TODO("Not yet implemented")
1604     }
1605 
1606     override fun resetRuntimePermissionsForUser(userId: Int) {
1607         // TODO("Not yet implemented")
1608     }
1609 
1610     override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
1611         onPermissionsChangeListeners.addListener(listener)
1612     }
1613 
1614     override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
1615         onPermissionsChangeListeners.removeListener(listener)
1616     }
1617 
1618     override fun addOnRuntimePermissionStateChangedListener(
1619         listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
1620     ) {
1621         // TODO: Should be removed once we remove PermissionPolicyService.
1622     }
1623 
1624     override fun removeOnRuntimePermissionStateChangedListener(
1625         listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
1626     ) {
1627         // TODO: Should be removed once we remove PermissionPolicyService.
1628     }
1629 
1630     override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> {
1631         return PermissionManager.splitPermissionInfoListToParcelableList(
1632             systemConfig.splitPermissions
1633         )
1634     }
1635 
1636 
1637 
1638     override fun getAppOpPermissionPackages(permissionName: String): Array<String> {
1639         requireNotNull(permissionName) { "permissionName cannot be null" }
1640         val packageNames = IndexedSet<String>()
1641 
1642         val permission = service.getState {
1643             with(policy) { getPermissions()[permissionName] }
1644         }
1645         if (permission == null || !permission.isAppOp) {
1646             packageNames.toTypedArray()
1647         }
1648 
1649         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
1650             snapshot.packageStates.forEach packageStates@{ (_, packageState) ->
1651                 val androidPackage = packageState.androidPackage ?: return@packageStates
1652                 if (permissionName in androidPackage.requestedPermissions) {
1653                     packageNames += androidPackage.packageName
1654                 }
1655             }
1656         }
1657 
1658         return packageNames.toTypedArray()
1659     }
1660 
1661     override fun getAllAppOpPermissionPackages(): Map<String, Set<String>> {
1662         val appOpPermissionPackageNames = IndexedMap<String, IndexedSet<String>>()
1663         val permissions = service.getState { with(policy) { getPermissions() } }
1664         packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
1665             snapshot.packageStates.forEach packageStates@{ (_, packageState) ->
1666                 val androidPackage = packageState.androidPackage ?: return@packageStates
1667                 androidPackage.requestedPermissions.forEach requestedPermissions@{ permissionName ->
1668                     val permission = permissions[permissionName] ?: return@requestedPermissions
1669                     if (permission.isAppOp) {
1670                         val packageNames = appOpPermissionPackageNames
1671                             .getOrPut(permissionName) { IndexedSet() }
1672                         packageNames += androidPackage.packageName
1673                     }
1674                 }
1675             }
1676         }
1677         return appOpPermissionPackageNames
1678     }
1679 
1680     override fun backupRuntimePermissions(userId: Int): ByteArray? {
1681         Preconditions.checkArgumentNonnegative(userId, "userId cannot be null")
1682         val backup = CompletableFuture<ByteArray>()
1683         permissionControllerManager.getRuntimePermissionBackup(
1684             UserHandle.of(userId), PermissionThread.getExecutor(), backup::complete
1685         )
1686 
1687         return try {
1688             backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
1689         } catch (e: Exception) {
1690             when (e) {
1691                 is TimeoutException, is InterruptedException, is ExecutionException -> {
1692                     Log.e(LOG_TAG, "Cannot create permission backup for user $userId", e)
1693                     null
1694                 }
1695                 else -> throw e
1696             }
1697         }
1698     }
1699 
1700     override fun restoreRuntimePermissions(backup: ByteArray, userId: Int) {
1701         requireNotNull(backup) { "backup" }
1702         Preconditions.checkArgumentNonnegative(userId, "userId")
1703 
1704         synchronized(isDelayedPermissionBackupFinished) {
1705             isDelayedPermissionBackupFinished -= userId
1706         }
1707         permissionControllerManager.stageAndApplyRuntimePermissionsBackup(
1708             backup, UserHandle.of(userId)
1709         )
1710     }
1711 
1712     override fun restoreDelayedRuntimePermissions(packageName: String, userId: Int) {
1713         requireNotNull(packageName) { "packageName" }
1714         Preconditions.checkArgumentNonnegative(userId, "userId")
1715 
1716         synchronized(isDelayedPermissionBackupFinished) {
1717             if (isDelayedPermissionBackupFinished.get(userId, false)) {
1718                 return
1719             }
1720         }
1721         permissionControllerManager.applyStagedRuntimePermissionBackup(
1722             packageName, UserHandle.of(userId), PermissionThread.getExecutor()
1723         ) { hasMoreBackup ->
1724             if (hasMoreBackup) {
1725                 return@applyStagedRuntimePermissionBackup
1726             }
1727             synchronized(isDelayedPermissionBackupFinished) {
1728                 isDelayedPermissionBackupFinished.put(userId, true)
1729             }
1730         }
1731     }
1732 
1733     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>?) {
1734         if (!DumpUtils.checkDumpPermission(context, LOG_TAG, pw)) {
1735             return
1736         }
1737         context.getSystemService(PermissionControllerManager::class.java)!!.dump(fd, args)
1738     }
1739 
1740     override fun getPermissionTEMP(permissionName: String): LegacyPermission2? {
1741         val permission = service.getState {
1742             with(policy) { getPermissions()[permissionName] }
1743         } ?: return null
1744 
1745         return LegacyPermission2(
1746             permission.permissionInfo, permission.type, permission.isReconciled, permission.appId,
1747             permission.gids, permission.areGidsPerUser
1748         )
1749     }
1750 
1751     override fun getLegacyPermissions(): List<LegacyPermission> =
1752         service.getState {
1753             with(policy) { getPermissions() }
1754         }.mapIndexed { _, _, permission ->
1755             LegacyPermission(
1756                 permission.permissionInfo, permission.type, permission.appId, permission.gids
1757             )
1758         }
1759 
1760     override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
1761         // Package settings has been read when this method is called.
1762         service.initialize()
1763     }
1764 
1765     override fun writeLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
1766         service.getState {
1767             val permissions = with(policy) { getPermissions() }
1768             legacyPermissionSettings.replacePermissions(toLegacyPermissions(permissions))
1769             val permissionTrees = with(policy) { getPermissionTrees() }
1770             legacyPermissionSettings.replacePermissionTrees(toLegacyPermissions(permissionTrees))
1771         }
1772     }
1773 
1774     private fun toLegacyPermissions(
1775         permissions: IndexedMap<String, Permission>
1776     ): List<LegacyPermission> =
1777         permissions.mapIndexed { _, _, permission ->
1778             // We don't need to provide UID and GIDs, which are only retrieved when dumping.
1779             LegacyPermission(
1780                 permission.permissionInfo, permission.type, 0, EmptyArray.INT
1781             )
1782         }
1783 
1784     override fun getLegacyPermissionState(appId: Int): LegacyPermissionState {
1785         val legacyState = LegacyPermissionState()
1786         val userIds = userManagerService.userIdsIncludingPreCreated
1787         service.getState {
1788             val permissions = with(policy) { getPermissions() }
1789             userIds.forEachIndexed { _, userId ->
1790                 val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) }
1791                     ?: return@forEachIndexed
1792 
1793                 permissionFlags.forEachIndexed permissionFlags@{ _, permissionName, flags ->
1794                     val permission = permissions[permissionName] ?: return@permissionFlags
1795                     val legacyPermissionState = LegacyPermissionState.PermissionState(
1796                         permissionName,
1797                         permission.isRuntime,
1798                         PermissionFlags.isPermissionGranted(flags),
1799                         PermissionFlags.toApiFlags(flags)
1800                     )
1801                     legacyState.putPermissionState(legacyPermissionState, userId)
1802                 }
1803             }
1804         }
1805         return legacyState
1806     }
1807 
1808     override fun readLegacyPermissionStateTEMP() {}
1809 
1810     override fun writeLegacyPermissionStateTEMP() {}
1811 
1812     override fun onSystemReady() {
1813         service.onSystemReady()
1814         permissionControllerManager = PermissionControllerManager(
1815             context, PermissionThread.getHandler()
1816         )
1817     }
1818 
1819     override fun onUserCreated(userId: Int) {
1820         service.onUserAdded(userId)
1821     }
1822 
1823     override fun onUserRemoved(userId: Int) {
1824         service.onUserRemoved(userId)
1825     }
1826 
1827     override fun onStorageVolumeMounted(volumeUuid: String, fingerprintChanged: Boolean) {
1828         service.onStorageVolumeMounted(volumeUuid, fingerprintChanged)
1829         synchronized(mountedStorageVolumes) {
1830             mountedStorageVolumes += volumeUuid
1831         }
1832     }
1833 
1834     override fun onPackageAdded(
1835         packageState: PackageState,
1836         isInstantApp: Boolean,
1837         oldPackage: AndroidPackage?
1838     ) {
1839         synchronized(mountedStorageVolumes) {
1840             if (packageState.volumeUuid !in mountedStorageVolumes) {
1841                 // Wait for the storage volume to be mounted and batch the state mutation there.
1842                 return
1843             }
1844         }
1845         service.onPackageAdded(packageState.packageName)
1846     }
1847 
1848     override fun onPackageRemoved(androidPackage: AndroidPackage) {
1849         // This may not be a full removal so ignored - we'll figure out full removal in
1850         // onPackageUninstalled().
1851     }
1852 
1853     override fun onPackageInstalled(
1854         androidPackage: AndroidPackage,
1855         previousAppId: Int,
1856         params: PermissionManagerServiceInternal.PackageInstalledParams,
1857         userId: Int
1858     ) {
1859         synchronized(mountedStorageVolumes) {
1860             if (androidPackage.volumeUuid !in mountedStorageVolumes) {
1861                 // Wait for the storage volume to be mounted and batch the state mutation there.
1862                 // PackageInstalledParams won't exist when packages are being scanned instead of
1863                 // being installed by an installer.
1864                 return
1865             }
1866         }
1867         val userIds = if (userId == UserHandle.USER_ALL) {
1868             userManagerService.userIdsIncludingPreCreated
1869         } else {
1870             intArrayOf(userId)
1871         }
1872         @Suppress("NAME_SHADOWING")
1873         userIds.forEach { userId ->
1874             service.onPackageInstalled(androidPackage.packageName, userId)
1875         }
1876 
1877         @Suppress("NAME_SHADOWING")
1878         userIds.forEach { userId ->
1879             // TODO: Remove when this callback receives packageState directly.
1880             val packageState =
1881                 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)!!
1882             addAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId,
1883                 params.allowlistedRestrictedPermissions, userId)
1884             setRequestedPermissionStates(packageState, userId, params.permissionStates)
1885         }
1886     }
1887 
1888     override fun onPackageUninstalled(
1889         packageName: String,
1890         appId: Int,
1891         packageState: PackageState,
1892         androidPackage: AndroidPackage?,
1893         sharedUserPkgs: List<AndroidPackage>,
1894         userId: Int
1895     ) {
1896         val userIds = if (userId == UserHandle.USER_ALL) {
1897             userManagerService.userIdsIncludingPreCreated
1898         } else {
1899             intArrayOf(userId)
1900         }
1901         userIds.forEach { service.onPackageUninstalled(packageName, appId, it) }
1902         val packageState = packageManagerInternal.packageStates[packageName]
1903         if (packageState == null) {
1904             service.onPackageRemoved(packageName, appId)
1905         }
1906     }
1907 
1908     /**
1909      * Check whether a UID is root or system.
1910      */
1911     private fun isRootOrSystem(uid: Int) =
1912         when (UserHandle.getAppId(uid)) {
1913             Process.ROOT_UID, Process.SYSTEM_UID -> true
1914             else -> false
1915         }
1916 
1917     /**
1918      * Check whether a UID is shell.
1919      */
1920     private fun isShell(uid: Int) = UserHandle.getAppId(uid) == Process.SHELL_UID
1921 
1922     /**
1923      * Check whether a UID is root, system or shell.
1924      */
1925     private fun isRootOrSystemOrShell(uid: Int) = isRootOrSystem(uid) || isShell(uid)
1926 
1927     /**
1928      * This method should typically only be used when granting or revoking permissions, since the
1929      * app may immediately restart after this call.
1930      *
1931      * If you're doing surgery on app code/data, use [PackageFreezer] to guard your work against
1932      * the app being relaunched.
1933      */
1934     private fun killUid(uid: Int, reason: String) {
1935         val activityManager = ActivityManager.getService()
1936         if (activityManager != null) {
1937             val appId = UserHandle.getAppId(uid)
1938             val userId = UserHandle.getUserId(uid)
1939             Binder::class.withClearedCallingIdentity {
1940                 try {
1941                     activityManager.killUidForPermissionChange(appId, userId, reason)
1942                 } catch (e: RemoteException) {
1943                     /* ignore - same process */
1944                 }
1945             }
1946         }
1947     }
1948 
1949     /**
1950      * @see PackageManagerLocal.withFilteredSnapshot
1951      */
1952     private fun PackageManagerLocal.withFilteredSnapshot(
1953         callingUid: Int,
1954         userId: Int
1955     ): PackageManagerLocal.FilteredSnapshot =
1956         withFilteredSnapshot(callingUid, UserHandle.of(userId))
1957 
1958     /**
1959      * Get the [PackageState] for a package name.
1960      *
1961      * This is for parity with [PackageManagerLocal.FilteredSnapshot.getPackageState] which is more
1962      * efficient than [PackageManagerLocal.FilteredSnapshot.getPackageStates], so that we can always
1963      * prefer using `getPackageState()` without worrying about whether the snapshot is filtered.
1964      */
1965     private fun PackageManagerLocal.UnfilteredSnapshot.getPackageState(
1966         packageName: String
1967     ): PackageState? = packageStates[packageName]
1968 
1969     /**
1970      * Check whether a UID belongs to an instant app.
1971      */
1972     private fun PackageManagerLocal.UnfilteredSnapshot.isUidInstantApp(uid: Int): Boolean =
1973         // Unfortunately we don't have the API for getting the owner UID of an isolated UID or the
1974         // API for getting the SharedUserApi object for an app ID yet, so for now we just keep
1975         // calling the old API.
1976         packageManagerInternal.getInstantAppPackageName(uid) != null
1977 
1978     /**
1979      * Check whether a package is visible to a UID within the same user as the UID.
1980      */
1981     private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid(
1982         packageName: String,
1983         uid: Int
1984     ): Boolean = isPackageVisibleToUid(packageName, UserHandle.getUserId(uid), uid)
1985 
1986     /**
1987      * Check whether a package in a particular user is visible to a UID.
1988      */
1989     private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid(
1990         packageName: String,
1991         userId: Int,
1992         uid: Int
1993     ): Boolean = filtered(uid, userId).use { it.getPackageState(packageName) != null }
1994 
1995     /**
1996      * @see PackageManagerLocal.UnfilteredSnapshot.filtered
1997      */
1998     private fun PackageManagerLocal.UnfilteredSnapshot.filtered(
1999         callingUid: Int,
2000         userId: Int
2001     ): PackageManagerLocal.FilteredSnapshot = filtered(callingUid, UserHandle.of(userId))
2002 
2003     /**
2004      * If neither you nor the calling process of an IPC you are handling has been granted the
2005      * permission for accessing a particular [userId], throw a [SecurityException].
2006      *
2007      * @see Context.enforceCallingOrSelfPermission
2008      * @see UserManager.DISALLOW_DEBUGGING_FEATURES
2009      */
2010     private fun enforceCallingOrSelfCrossUserPermission(
2011         userId: Int,
2012         enforceFullPermission: Boolean,
2013         enforceShellRestriction: Boolean,
2014         message: String?
2015     ) {
2016         require(userId >= 0) { "userId $userId is invalid" }
2017         val callingUid = Binder.getCallingUid()
2018         val callingUserId = UserHandle.getUserId(callingUid)
2019         if (userId != callingUserId) {
2020             val permissionName = if (enforceFullPermission) {
2021                 Manifest.permission.INTERACT_ACROSS_USERS_FULL
2022             } else {
2023                 Manifest.permission.INTERACT_ACROSS_USERS
2024             }
2025             if (context.checkCallingOrSelfPermission(permissionName) !=
2026                 PackageManager.PERMISSION_GRANTED) {
2027                 val exceptionMessage = buildString {
2028                     if (message != null) {
2029                         append(message)
2030                         append(": ")
2031                     }
2032                     append("Neither user ")
2033                     append(Binder.getCallingUid())
2034                     append(" nor current process has ")
2035                     append(permissionName)
2036                     append(" to access user ")
2037                     append(userId)
2038                 }
2039                 throw SecurityException(exceptionMessage)
2040             }
2041         }
2042         if (enforceShellRestriction && isShell(callingUid)) {
2043             val isShellRestricted = userManagerInternal.hasUserRestriction(
2044                 UserManager.DISALLOW_DEBUGGING_FEATURES, userId
2045             )
2046             if (isShellRestricted) {
2047                 val exceptionMessage = buildString {
2048                     if (message != null) {
2049                         append(message)
2050                         append(": ")
2051                     }
2052                     append("Shell is disallowed to access user ")
2053                     append(userId)
2054                 }
2055                 throw SecurityException(exceptionMessage)
2056             }
2057         }
2058     }
2059 
2060     /**
2061      * If neither you nor the calling process of an IPC you are handling has been granted any of the
2062      * permissions, throw a [SecurityException].
2063      *
2064      * @see Context.enforceCallingOrSelfPermission
2065      */
2066     private fun enforceCallingOrSelfAnyPermission(
2067         message: String?,
2068         vararg permissionNames: String
2069     ) {
2070         val hasAnyPermission = permissionNames.any { permissionName ->
2071             context.checkCallingOrSelfPermission(permissionName) ==
2072                 PackageManager.PERMISSION_GRANTED
2073         }
2074         if (!hasAnyPermission) {
2075             val exceptionMessage = buildString {
2076                 if (message != null) {
2077                     append(message)
2078                     append(": ")
2079                 }
2080                 append("Neither user ")
2081                 append(Binder.getCallingUid())
2082                 append(" nor current process has any of ")
2083                 permissionNames.joinTo(this, ", ")
2084             }
2085             throw SecurityException(exceptionMessage)
2086         }
2087     }
2088 
2089     /**
2090      * Callback invoked when interesting actions have been taken on a permission.
2091      */
2092     private inner class OnPermissionFlagsChangedListener :
2093         UidPermissionPolicy.OnPermissionFlagsChangedListener() {
2094         private var isPermissionFlagsChanged = false
2095 
2096         private val runtimePermissionChangedUids = IntSet()
2097         // Mapping from UID to whether only notifications permissions are revoked.
2098         private val runtimePermissionRevokedUids = IntBooleanMap()
2099         private val gidsChangedUids = IntSet()
2100 
2101         private var isKillRuntimePermissionRevokedUidsSkipped = false
2102         private val killRuntimePermissionRevokedUidsReasons = IndexedSet<String>()
2103 
2104         fun MutateStateScope.skipKillRuntimePermissionRevokedUids() {
2105             isKillRuntimePermissionRevokedUidsSkipped = true
2106         }
2107 
2108         fun MutateStateScope.addKillRuntimePermissionRevokedUidsReason(reason: String) {
2109             killRuntimePermissionRevokedUidsReasons += reason
2110         }
2111 
2112         override fun onPermissionFlagsChanged(
2113             appId: Int,
2114             userId: Int,
2115             permissionName: String,
2116             oldFlags: Int,
2117             newFlags: Int
2118         ) {
2119             isPermissionFlagsChanged = true
2120 
2121             val uid = UserHandle.getUid(userId, appId)
2122             val permission = service.getState {
2123                 with(policy) { getPermissions()[permissionName] }
2124             } ?: return
2125             val wasPermissionGranted = PermissionFlags.isPermissionGranted(oldFlags)
2126             val isPermissionGranted = PermissionFlags.isPermissionGranted(newFlags)
2127 
2128             if (permission.isRuntime) {
2129                 // Different from the old implementation, which notifies the listeners when the
2130                 // permission flags have changed for a non-runtime permission, now we no longer do
2131                 // that because permission flags are only for runtime permissions and the listeners
2132                 // aren't being notified of non-runtime permission grant state changes anyway.
2133                 runtimePermissionChangedUids += uid
2134                 if (wasPermissionGranted && !isPermissionGranted) {
2135                     runtimePermissionRevokedUids[uid] =
2136                         permissionName in NOTIFICATIONS_PERMISSIONS &&
2137                             runtimePermissionRevokedUids.getWithDefault(uid, true)
2138                 }
2139             }
2140 
2141             if (permission.hasGids && !wasPermissionGranted && isPermissionGranted) {
2142                 gidsChangedUids += uid
2143             }
2144         }
2145 
2146         override fun onStateMutated() {
2147             if (isPermissionFlagsChanged) {
2148                 PackageManager.invalidatePackageInfoCache()
2149                 isPermissionFlagsChanged = false
2150             }
2151 
2152             runtimePermissionChangedUids.forEachIndexed { _, uid ->
2153                 onPermissionsChangeListeners.onPermissionsChanged(uid)
2154             }
2155             runtimePermissionChangedUids.clear()
2156 
2157             if (!isKillRuntimePermissionRevokedUidsSkipped) {
2158                 val reason = if (killRuntimePermissionRevokedUidsReasons.isNotEmpty()) {
2159                     killRuntimePermissionRevokedUidsReasons.joinToString(", ")
2160                 } else {
2161                     PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED
2162                 }
2163                 runtimePermissionRevokedUids.forEachIndexed {
2164                     _, uid, areOnlyNotificationsPermissionsRevoked ->
2165                     handler.post {
2166                         if (areOnlyNotificationsPermissionsRevoked &&
2167                             isAppBackupAndRestoreRunning(uid)
2168                         ) {
2169                             return@post
2170                         }
2171                         killUid(uid, reason)
2172                     }
2173                 }
2174             }
2175             runtimePermissionRevokedUids.clear()
2176 
2177             gidsChangedUids.forEachIndexed { _, uid ->
2178                 handler.post { killUid(uid, PermissionManager.KILL_APP_REASON_GIDS_CHANGED) }
2179             }
2180             gidsChangedUids.clear()
2181 
2182             isKillRuntimePermissionRevokedUidsSkipped = false
2183             killRuntimePermissionRevokedUidsReasons.clear()
2184         }
2185 
2186         private fun isAppBackupAndRestoreRunning(uid: Int): Boolean {
2187             if (checkUidPermission(uid, Manifest.permission.BACKUP) !=
2188                 PackageManager.PERMISSION_GRANTED) {
2189                 return false
2190             }
2191             return try {
2192                 val contentResolver = context.contentResolver
2193                 val userId = UserHandle.getUserId(uid)
2194                 val isInSetup = Settings.Secure.getIntForUser(
2195                     contentResolver, Settings.Secure.USER_SETUP_COMPLETE, userId
2196                 ) == 0
2197                 val isInDeferredSetup = Settings.Secure.getIntForUser(
2198                     contentResolver, Settings.Secure.USER_SETUP_PERSONALIZATION_STATE, userId
2199                 ) == Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED
2200                 isInSetup || isInDeferredSetup
2201             } catch (e: Settings.SettingNotFoundException) {
2202                 Log.w(LOG_TAG, "Failed to check if the user is in restore: $e")
2203                 false
2204             }
2205         }
2206     }
2207 
2208     private class OnPermissionsChangeListeners(looper: Looper) : Handler(looper) {
2209         private val listeners = RemoteCallbackList<IOnPermissionsChangeListener>()
2210 
2211         override fun handleMessage(msg: Message) {
2212             when (msg.what) {
2213                 MSG_ON_PERMISSIONS_CHANGED -> {
2214                     val uid = msg.arg1
2215                     handleOnPermissionsChanged(uid)
2216                 }
2217             }
2218         }
2219 
2220         private fun handleOnPermissionsChanged(uid: Int) {
2221             listeners.broadcast { listener ->
2222                 try {
2223                     listener.onPermissionsChanged(uid)
2224                 } catch (e: RemoteException) {
2225                     Log.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e)
2226                 }
2227             }
2228         }
2229 
2230         fun addListener(listener: IOnPermissionsChangeListener) {
2231             listeners.register(listener)
2232         }
2233 
2234         fun removeListener(listener: IOnPermissionsChangeListener) {
2235             listeners.unregister(listener)
2236         }
2237 
2238         fun onPermissionsChanged(uid: Int) {
2239             if (listeners.registeredCallbackCount > 0) {
2240                 obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget()
2241             }
2242         }
2243 
2244         companion object {
2245             private const val MSG_ON_PERMISSIONS_CHANGED = 1
2246         }
2247     }
2248 
2249     companion object {
2250         private val LOG_TAG = PermissionService::class.java.simpleName
2251 
2252         /**
2253          * This change makes it so that apps are told to show rationale for asking for background
2254          * location access every time they request.
2255          */
2256         @ChangeId
2257         @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
2258         private val BACKGROUND_RATIONALE_CHANGE_ID = 147316723L
2259 
2260         private val FULLER_PERMISSIONS = IndexedMap<String, String>().apply {
2261             this[Manifest.permission.ACCESS_COARSE_LOCATION] =
2262                 Manifest.permission.ACCESS_FINE_LOCATION
2263             this[Manifest.permission.INTERACT_ACROSS_USERS] =
2264                 Manifest.permission.INTERACT_ACROSS_USERS_FULL
2265         }
2266 
2267         private val NOTIFICATIONS_PERMISSIONS = indexedSetOf(
2268             Manifest.permission.POST_NOTIFICATIONS
2269         )
2270 
2271         private const val REVIEW_REQUIRED_FLAGS = PermissionFlags.LEGACY_GRANTED or
2272             PermissionFlags.IMPLICIT
2273         private const val UNREQUESTABLE_MASK = PermissionFlags.RESTRICTION_REVOKED or
2274             PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED or
2275             PermissionFlags.USER_FIXED
2276 
2277         private val BACKUP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60)
2278 
2279         /** Cap the size of permission trees that 3rd party apps can define; in characters of text  */
2280         private const val MAX_PERMISSION_TREE_FOOTPRINT = 32768
2281 
2282         private const val PERMISSION_ALLOWLIST_MASK =
2283             PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE or
2284             PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM or
2285             PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER
2286     }
2287 }
2288