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