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 
27 /**
28  * LiveData with a map representing the runtime permissions a group requests and all of the
29  * installed, non-runtime, normal protection permissions. Key is the group name or
30  * NON_RUNTIME_NORMAL_PERMS, value is the requested runtime permissions in that group (or all
31  * installed non-runtime normal protection permissions, for NON_RUNTME_NORMAL_PERMS).
32  *
33  * @param app The current Application
34  * @param packageName The name of the package this LiveData will watch for mode changes for
35  * @param user The user for whom the packageInfo will be defined
36  */
37 class PackagePermissionsLiveData private constructor(
38     private val app: Application,
39     packageName: String,
40     user: UserHandle
41 ) : SmartUpdateMediatorLiveData<Map<String, List<String>>?>() {
42 
43     private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user]
44 
45     init {
<lambda>null46         addSource(packageInfoLiveData) {
47             if (packageInfoLiveData.isInitialized && packageInfoLiveData.value == null) {
48                 invalidateSingle(packageName to user)
49                 value = null
50                 return@addSource
51             }
52             updateIfActive()
53         }
54     }
55 
onUpdatenull56     override fun onUpdate() {
57         val packageInfo = packageInfoLiveData.value ?: return
58         val permissionMap = mutableMapOf<String, MutableList<String>>()
59         for (permName in packageInfo.requestedPermissions) {
60             val permInfo = try {
61                 app.packageManager.getPermissionInfo(permName, 0)
62             } catch (e: PackageManager.NameNotFoundException) {
63                 continue
64             }
65 
66             if (permInfo.flags and PermissionInfo.FLAG_INSTALLED == 0 ||
67                 permInfo.flags and PermissionInfo.FLAG_REMOVED != 0) {
68                 continue
69             }
70 
71             if (packageInfo.isInstantApp && permInfo.protectionFlags and
72                 PermissionInfo.PROTECTION_FLAG_INSTANT == 0) {
73                 continue
74             }
75 
76             if (packageInfo.targetSdkVersion < Build.VERSION_CODES.M &&
77                 (permInfo.protectionFlags and PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0) {
78                 continue
79             }
80 
81             // If this permission is a non-runtime, normal permission, add it to the "non runtime"
82             // group
83             if (permInfo.protection != PermissionInfo.PROTECTION_DANGEROUS) {
84                 if (permInfo.protection == PermissionInfo.PROTECTION_NORMAL) {
85                     val otherPermsList =
86                         permissionMap.getOrPut(NON_RUNTIME_NORMAL_PERMS) { mutableListOf() }
87                     otherPermsList.add(permInfo.name)
88                 }
89                 continue
90             }
91 
92             val groupName = Utils.getGroupOfPermission(permInfo) ?: permInfo.name
93             if (!permissionMap.containsKey(groupName)) {
94                 permissionMap[groupName] = mutableListOf()
95             }
96             permissionMap[groupName]?.add(permInfo.name)
97         }
98 
99         value = permissionMap
100     }
101 
102     /**
103      * Repository for PackagePermissionsLiveData objects
104      * <p> Key value is a string package name and userHandle, value is its corresponding LiveData.
105      */
106     companion object : DataRepositoryForPackage<Pair<String, UserHandle>,
107         PackagePermissionsLiveData>() {
newValuenull108         override fun newValue(key: Pair<String, UserHandle>):
109             PackagePermissionsLiveData {
110             return PackagePermissionsLiveData(PermissionControllerApplication.get(), key.first,
111                 key.second)
112         }
113 
114         const val NON_RUNTIME_NORMAL_PERMS = "nonRuntimeNormalPerms"
115     }
116 }
117