• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.permissioncontroller.permission.data
18 
19 import android.app.Application
20 import android.content.pm.PackageManager
21 import android.content.pm.PermissionInfo
22 import android.os.Build
23 import android.os.UserHandle
24 import com.android.permissioncontroller.PermissionControllerApplication
25 import com.android.permissioncontroller.permission.utils.Utils
26 import kotlinx.coroutines.Job
27 
28 /**
29  * LiveData with a map representing the runtime permissions a group requests and all of the
30  * installed, non-runtime, normal protection permissions. Key is the group name or
31  * NON_RUNTIME_NORMAL_PERMS, value is the requested runtime permissions in that group (or all
32  * installed non-runtime normal protection permissions, for NON_RUNTME_NORMAL_PERMS).
33  *
34  * @param app The current Application
35  * @param packageName The name of the package this LiveData will watch for mode changes for
36  * @param user The user for whom the packageInfo will be defined
37  */
38 class PackagePermissionsLiveData private constructor(
39     private val app: Application,
40     packageName: String,
41     user: UserHandle
42 ) : SmartAsyncMediatorLiveData<Map<String, List<String>>?>() {
43 
44     private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
45 
46     init {
<lambda>null47         addSource(packageInfoLiveData) {
48             if (packageInfoLiveData.isInitialized && packageInfoLiveData.value == null) {
49                 invalidateSingle(packageName to user)
50                 value = null
51                 return@addSource
52             }
53             update()
54         }
55     }
56 
loadDataAndPostValuenull57     override suspend fun loadDataAndPostValue(job: Job) {
58         val packageInfo = packageInfoLiveData.value ?: return
59         val permissionMap = mutableMapOf<String, MutableList<String>>()
60         for (permName in packageInfo.requestedPermissions) {
61             var groupName = Utils.getGroupOfPlatformPermission(permName)
62             if (groupName == null) {
63                 val permInfo = try {
64                     app.packageManager.getPermissionInfo(permName, 0)
65                 } catch (e: PackageManager.NameNotFoundException) {
66                     continue
67                 }
68 
69                 if (permInfo.flags and PermissionInfo.FLAG_INSTALLED == 0 ||
70                     permInfo.flags and PermissionInfo.FLAG_REMOVED != 0) {
71                     continue
72                 }
73 
74                 if (packageInfo.isInstantApp && permInfo.protectionFlags and
75                     PermissionInfo.PROTECTION_FLAG_INSTANT == 0) {
76                     continue
77                 }
78 
79                 if (packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
80                     (permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) !=
81                     0) {
82                     continue
83                 }
84 
85                 // If this permission is a non-runtime, normal permission, add it to the
86                 // "non runtime" group
87                 if (permInfo.protection != PermissionInfo.PROTECTION_DANGEROUS) {
88                     if (permInfo.protection == PermissionInfo.PROTECTION_NORMAL) {
89                         val otherPermsList =
90                             permissionMap.getOrPut(NON_RUNTIME_NORMAL_PERMS) { mutableListOf() }
91                         otherPermsList.add(permInfo.name)
92                     }
93                     continue
94                 }
95 
96                 groupName = Utils.getGroupOfPermission(permInfo) ?: permName
97             }
98 
99             permissionMap.getOrPut(groupName) { mutableListOf() }.add(permName)
100         }
101 
102         postValue(permissionMap)
103     }
104 
105     /**
106      * Repository for PackagePermissionsLiveData objects
107      * <p> Key value is a string package name and userHandle, value is its corresponding LiveData.
108      */
109     companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
110         PackagePermissionsLiveData>() {
newValuenull111         override fun newValue(key: Pair<String, UserHandle>):
112             PackagePermissionsLiveData {
113             return PackagePermissionsLiveData(PermissionControllerApplication.get(), key.first,
114                 key.second)
115         }
116 
117         const val NON_RUNTIME_NORMAL_PERMS = "nonRuntimeNormalPerms"
118     }
119 }
120