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