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 androidx.lifecycle.LiveData
22 import com.android.permissioncontroller.permission.model.livedatatypes.AppPermGroupUiInfo
23 import com.android.permissioncontroller.permission.model.livedatatypes.PermGroupPackagesUiInfo
24 
25 /**
26  * A LiveData which tracks all app permission groups for a set of permission groups, either platform
27  * or custom, as well as the UI information related to each app permission group, and the permission
28  * group as a whole.
29  *
30  * @param app The current application
31  */
32 class PermGroupsPackagesUiInfoLiveData(
33     private val app: Application,
34     groupNamesLiveData: LiveData<List<String>>
35 ) : SmartUpdateMediatorLiveData<
36     @kotlin.jvm.JvmSuppressWildcards Map<String, PermGroupPackagesUiInfo?>>() {
37 
38     /**
39      * Map<permission group name, PermGroupUiLiveDatas>
40      */
41     private val permGroupPackagesLiveDatas = mutableMapOf<String,
42         SinglePermGroupPackagesUiInfoLiveData>()
43     private val allPackageData = mutableMapOf<String, PermGroupPackagesUiInfo?>()
44 
45     private lateinit var groupNames: List<String>
46 
47     init {
48         addSource(groupNamesLiveData) {
49             groupNames = it ?: emptyList()
50             updateIfActive()
51             getPermGroupPackageLiveDatas()
52         }
53     }
54 
55     private fun getPermGroupPackageLiveDatas() {
56         val getLiveData = { groupName: String -> SinglePermGroupPackagesUiInfoLiveData[groupName] }
57         setSourcesToDifference(groupNames, permGroupPackagesLiveDatas, getLiveData)
58     }
59 
60     private fun getNonSystemTotal(uiInfo: Map<Pair<String, UserHandle>, AppPermGroupUiInfo>): Int {
61         var shownNonSystem = 0
62         for ((_, appPermGroup) in uiInfo) {
63             if (appPermGroup.shouldShow && !appPermGroup.isSystem) {
64                 shownNonSystem++
65             }
66         }
67         return shownNonSystem
68     }
69 
70     private fun getNonSystemGranted(
71         uiInfo: Map<Pair<String, UserHandle>, AppPermGroupUiInfo>
72     ): Int {
73         var granted = 0
74         for ((_, appPermGroup) in uiInfo) {
75             if (appPermGroup.shouldShow && !appPermGroup.isSystem &&
76                 appPermGroup.permGrantState != AppPermGroupUiInfo.PermGrantState.PERMS_DENIED &&
77                 appPermGroup.permGrantState != AppPermGroupUiInfo.PermGrantState.PERMS_ASK) {
78                 granted++
79             }
80         }
81         return granted
82     }
83 
84     override fun onUpdate() {
85         /**
86          * Only update when either-
87          * We have a list of groups, and none have loaded their data, or
88          * All packages have loaded their data
89          */
90         val haveAllLiveDatas = groupNames.all { permGroupPackagesLiveDatas.contains(it) }
91         val allInitialized = permGroupPackagesLiveDatas.all { it.value.isInitialized }
92         for (groupName in groupNames) {
93             allPackageData[groupName] = if (haveAllLiveDatas && allInitialized) {
94                 permGroupPackagesLiveDatas[groupName]?.value?.let { uiInfo ->
95                     PermGroupPackagesUiInfo(groupName,
96                         getNonSystemTotal(uiInfo), getNonSystemGranted(uiInfo))
97                 }
98             } else {
99                 null
100             }
101         }
102         value = allPackageData.toMap()
103     }
104 }
105