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