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.os.UserHandle
21 import com.android.permissioncontroller.PermissionControllerApplication
22 import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
23 import com.android.permissioncontroller.permission.utils.Utils
24 
25 /**
26  * LiveData for the UI info for all packages in a single permission group. Tracks which packages
27  * have permissions in the given group, which should be shown on the UI, and which are granted or
28  * not.
29  *
30  * @param app The current application
31  * @param permGroupName The name of the permission group this LiveData represents
32  */
33 class SinglePermGroupPackagesUiInfoLiveData private constructor(
34     private val app: Application,
35     private val permGroupName: String
36 ) : SmartUpdateMediatorLiveData<Map<Pair<String, UserHandle>, AppPermGroupUiInfo>>() {
37 
38     private val permGroupLiveData = PermGroupLiveData[permGroupName]
39     private val isCustomGroup = !Utils.getPlatformPermissionGroups().contains(permGroupName)
40     private val permGroupPackagesLiveData = PermGroupsPackagesLiveData.get(
41         customGroups = isCustomGroup)
42 
43     /**
44      * Map<Pair<package name, UserHandle>, UI data LiveData>
45      */
46     private val appPermGroupLiveDatas = mutableMapOf<Pair<String, UserHandle>,
47         AppPermGroupUiInfoLiveData>()
48 
49     /**
50      * Map<Pair<packageName, userHandle>, UI data>.
51      */
52     private val shownPackages = mutableMapOf<Pair<String, UserHandle>, AppPermGroupUiInfo>()
53 
54     init {
55         addSource(permGroupLiveData) { newPermGroup ->
56             if (newPermGroup == null) {
57                 invalidateSingle(permGroupName)
58                 value = null
59             }
60         }
61 
62         addSource(permGroupPackagesLiveData) {
63             updateIfActive()
64         }
65     }
66 
67     override fun onUpdate() {
68         val thisPermGroupPackages = permGroupPackagesLiveData.value?.get(permGroupName)
69         if (thisPermGroupPackages != null) {
70             addAndRemoveAppPermGroupLiveDatas(thisPermGroupPackages.toList())
71 
72             if (thisPermGroupPackages.isEmpty()) {
73                 permGroupLiveData.value?.groupInfo?.let {
74                     value = emptyMap()
75                 }
76             }
77         }
78     }
79 
80     private fun addAndRemoveAppPermGroupLiveDatas(pkgs: List<Pair<String, UserHandle>>) {
81         val getLiveData = { key: Pair<String, UserHandle> ->
82             AppPermGroupUiInfoLiveData[key.first, permGroupName, key.second]
83         }
84 
85         setSourcesToDifference(pkgs, appPermGroupLiveDatas, getLiveData) { key ->
86             val appPermGroupUiInfoLiveData = appPermGroupLiveDatas[key]
87             val appPermGroupUiInfo = appPermGroupUiInfoLiveData?.value
88             shownPackages.remove(key)
89 
90             if (appPermGroupUiInfo == null) {
91                 if (appPermGroupUiInfoLiveData != null &&
92                     appPermGroupUiInfoLiveData.isInitialized) {
93                     removeSource(appPermGroupUiInfoLiveData)
94                     appPermGroupLiveDatas.remove(key)
95                 }
96             } else {
97                 shownPackages[key] = appPermGroupUiInfo
98             }
99 
100             if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) {
101                 permGroupLiveData.value?.groupInfo?.let {
102                     value = shownPackages.toMap()
103                 }
104             }
105         }
106     }
107 
108     /**
109      * Repository for SinglePermGroupPackagesUiInfoLiveData objects.
110      * <p> Key value is a string permission group name, value is its corresponding LiveData.
111      */
112     companion object : DataRepository<String,
113         SinglePermGroupPackagesUiInfoLiveData>() {
114         override fun newValue(key: String): SinglePermGroupPackagesUiInfoLiveData {
115             return SinglePermGroupPackagesUiInfoLiveData(PermissionControllerApplication.get(),
116                 key)
117         }
118     }
119 }