1 /*
<lambda>null2  * 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.PackageItemInfo
21 import android.content.pm.PackageManager
22 import android.content.pm.PermissionGroupInfo
23 import android.content.pm.PermissionInfo
24 import android.os.UserHandle
25 import android.util.Log
26 import com.android.permissioncontroller.PermissionControllerApplication
27 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermGroupInfo
28 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo
29 import com.android.permissioncontroller.permission.model.livedatatypes.PermGroup
30 import com.android.permissioncontroller.permission.utils.Utils
31 
32 /**
33  * LiveData for a Permission Group. Contains GroupInfo and a list of PermissionInfos. Loads
34  * synchronously.
35  *
36  * @param app The current application
37  * @param groupName The name of the permission group this LiveData represents
38  */
39 class PermGroupLiveData
40 private constructor(private val app: Application, private val groupName: String) :
41     SmartUpdateMediatorLiveData<PermGroup>(), PackageBroadcastReceiver.PackageBroadcastListener {
42 
43     private val LOG_TAG = this::class.java.simpleName
44 
45     private val context = app.applicationContext!!
46 
47     /** Map<packageName, LiveData<PackageInfo>> */
48     private val packageLiveDatas = mutableMapOf<String, LightPackageInfoLiveData>()
49 
50     private lateinit var groupInfo: PackageItemInfo
51 
52     /**
53      * Called when a package is installed, changed, or removed.
54      *
55      * @param packageName the package which was added or changed
56      */
57     override fun onPackageUpdate(packageName: String) {
58         update()
59     }
60 
61     /**
62      * Initializes this permission group from scratch. Resets the groupInfo, PermissionInfos, and
63      * PackageInfoLiveDatas, then re-adds them.
64      */
65     override fun onUpdate() {
66         val permissionInfos = mutableMapOf<String, LightPermInfo>()
67 
68         groupInfo =
69             Utils.getGroupInfo(groupName, context)
70                 ?: run {
71                     Log.e(LOG_TAG, "Invalid permission group $groupName")
72                     invalidateSingle(groupName)
73                     value = null
74                     return
75                 }
76 
77         when (groupInfo) {
78             is PermissionGroupInfo -> {
79                 val permInfos =
80                     try {
81                         Utils.getInstalledRuntimePermissionInfosForGroup(
82                             context.packageManager,
83                             groupName
84                         )
85                     } catch (e: PackageManager.NameNotFoundException) {
86                         Log.e(LOG_TAG, "Invalid permission group $groupName")
87                         invalidateSingle(groupName)
88                         value = null
89                         return
90                     }
91 
92                 for (permInfo in permInfos) {
93                     permissionInfos[permInfo.name] = LightPermInfo(permInfo)
94                 }
95             }
96             is PermissionInfo -> {
97                 permissionInfos[groupInfo.name] = LightPermInfo(groupInfo as PermissionInfo)
98             }
99             else -> {
100                 value = null
101                 return
102             }
103         }
104 
105         val permGroup = PermGroup(LightPermGroupInfo(groupInfo), permissionInfos)
106 
107         value = permGroup
108 
109         val packageNames =
110             permissionInfos.values.map { permInfo -> permInfo.packageName }.toMutableSet()
111         packageNames.add(groupInfo.packageName)
112 
113         // TODO ntmyren: What if the package isn't installed for the system user?
114         val getLiveData = { packageName: String ->
115             LightPackageInfoLiveData[packageName, UserHandle.SYSTEM]
116         }
117         setSourcesToDifference(packageNames, packageLiveDatas, getLiveData)
118     }
119 
120     override fun onInactive() {
121         super.onInactive()
122 
123         PackageBroadcastReceiver.removeAllCallback(this)
124     }
125 
126     /**
127      * Load data, and register a package change listener. We must watch for package changes, because
128      * there is currently no listener for permission changes.
129      */
130     override fun onActive() {
131         update()
132 
133         super.onActive()
134 
135         PackageBroadcastReceiver.addAllCallback(this)
136     }
137 
138     /**
139      * Repository for PermGroupLiveDatas.
140      *
141      * <p> Key value is a string permission group name, value is its corresponding LiveData.
142      */
143     companion object : DataRepository<String, PermGroupLiveData>() {
144         override fun newValue(key: String): PermGroupLiveData {
145             return PermGroupLiveData(PermissionControllerApplication.get(), key)
146         }
147     }
148 }
149