• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2020 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.ui.model
18 
19 import android.Manifest
20 import android.app.Application
21 import android.content.Intent
22 import android.health.connect.HealthPermissions.HEALTH_PERMISSION_GROUP
23 import android.os.Bundle
24 import androidx.fragment.app.Fragment
25 import androidx.lifecycle.AndroidViewModel
26 import androidx.lifecycle.MediatorLiveData
27 import androidx.lifecycle.MutableLiveData
28 import androidx.lifecycle.map
29 import androidx.navigation.fragment.findNavController
30 import com.android.permission.flags.Flags
31 import com.android.permissioncontroller.R
32 import com.android.permissioncontroller.permission.data.PermGroupsPackagesLiveData
33 import com.android.permissioncontroller.permission.data.PermGroupsPackagesUiInfoLiveData
34 import com.android.permissioncontroller.permission.data.SmartUpdateMediatorLiveData
35 import com.android.permissioncontroller.permission.data.StandardPermGroupNamesLiveData
36 import com.android.permissioncontroller.permission.data.unusedAutoRevokePackagesLiveData
37 import com.android.permissioncontroller.permission.utils.Utils
38 import com.android.permissioncontroller.permission.utils.navigateSafe
39 
40 /**
41  * A ViewModel for the ManageStandardPermissionsFragment. Provides a LiveData which watches over all
42  * platform permission groups, and sends async updates when these groups have changes. It also
43  * provides a liveData which watches the custom permission groups of the system, and provides a list
44  * of group names.
45  *
46  * @param app The current application of the fragment
47  */
48 class ManageStandardPermissionsViewModel(private val app: Application) : AndroidViewModel(app) {
49 
50     val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app, StandardPermGroupNamesLiveData)
51     val usedStandardPermGroupsUiInfo =
52         PermGroupsPackagesUiInfoLiveData(
53             app,
54             if (Flags.declutteredPermissionManagerEnabled()) UsedStandardPermGroupNamesLiveData(app)
55             else MutableLiveData<List<String>>(),
56         )
57     val numCustomPermGroups = NumCustomPermGroupsWithPackagesLiveData()
58     val numUnusedStandardPermGroups =
59         MediatorLiveData<Int>().apply {
60             if (Flags.declutteredPermissionManagerEnabled()) {
61                 addSource(UnusedStandardPermGroupNamesLiveData(app)) { groupNames ->
62                     value = groupNames.size
63                 }
64             }
65         }
66     val numAutoRevoked = unusedAutoRevokePackagesLiveData.map { it?.size ?: 0 }
67 
68     /**
69      * Navigate to the Custom Permissions screen
70      *
71      * @param fragment The fragment we are navigating from
72      * @param args The args to pass to the new fragment
73      */
74     fun showCustomPermissions(fragment: Fragment, args: Bundle) {
75         fragment.findNavController().navigateSafe(R.id.standard_to_custom, args)
76     }
77 
78     /**
79      * Navigate to a Permission Apps fragment
80      *
81      * @param fragment The fragment we are navigating from
82      * @param args The args to pass to the new fragment
83      */
84     fun showPermissionApps(fragment: Fragment, args: Bundle) {
85         val groupName = args.getString(Intent.EXTRA_PERMISSION_GROUP_NAME)
86         if (groupName == Manifest.permission_group.NOTIFICATIONS) {
87             Utils.navigateToNotificationSettings(fragment.context!!)
88             return
89         }
90         if (Utils.isHealthPermissionUiEnabled() && groupName == HEALTH_PERMISSION_GROUP) {
91             Utils.navigateToHealthConnectSettings(fragment.context!!)
92             return
93         }
94         fragment.findNavController().navigateSafe(R.id.manage_to_perm_apps, args)
95     }
96 
97     fun showAutoRevoke(fragment: Fragment, args: Bundle) {
98         fragment.findNavController().navigateSafe(R.id.manage_to_auto_revoke, args)
99     }
100 }
101 
102 /**
103  * A LiveData which tracks the number of custom permission groups that are used by at least one
104  * package
105  */
106 class NumCustomPermGroupsWithPackagesLiveData() : SmartUpdateMediatorLiveData<Int>() {
107 
108     private val customPermGroupPackages = PermGroupsPackagesLiveData.get(customGroups = true)
109 
110     init {
<lambda>null111         addSource(customPermGroupPackages) { update() }
112     }
113 
onUpdatenull114     override fun onUpdate() {
115         value = customPermGroupPackages.value?.size ?: 0
116     }
117 }
118 
119 /**
120  * A LiveData that tracks the names of the platform-defined permission groups, such that at least
121  * one of the permissions in the group has been requested at runtime by at least one non-system
122  * application.
123  *
124  * @param app The current application of the fragment
125  */
126 class UsedStandardPermGroupNamesLiveData(private val app: Application) :
127     SmartUpdateMediatorLiveData<List<String>>() {
128     init {
129         addSource(PermGroupsPackagesUiInfoLiveData(app, StandardPermGroupNamesLiveData)) {
permGroupsnull130             permGroups ->
131             if (permGroups.values.any { it != null }) {
132                 value =
<lambda>null133                     permGroups.filterValues { it != null && it.nonSystemTotal > 0 }.keys.toList()
134             }
135         }
136     }
137 
onUpdatenull138     override fun onUpdate() {
139         /* No op override */
140     }
141 }
142 
143 /**
144  * A LiveData that tracks the names of the platform-defined permission groups, such that none of the
145  * the permissions in the group has been requested at runtime by any non-system application.
146  *
147  * @param app The current application of the fragment
148  */
149 class UnusedStandardPermGroupNamesLiveData(private val app: Application) :
150     SmartUpdateMediatorLiveData<List<String>>() {
151     init {
152         addSource(PermGroupsPackagesUiInfoLiveData(app, StandardPermGroupNamesLiveData)) {
permGroupsnull153             permGroups ->
154             value = permGroups.filterValues { it != null && it.nonSystemTotal == 0 }.keys.toList()
155         }
156     }
157 
onUpdatenull158     override fun onUpdate() {
159         /* No op override */
160     }
161 }
162