1 /* 2 * 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.MutableLiveData 27 import androidx.lifecycle.ViewModel 28 import androidx.lifecycle.ViewModelProvider 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.utils.Utils 36 import com.android.permissioncontroller.permission.utils.navigateSafe 37 38 /** 39 * A ViewModel for the ManageCustomPermissionsFragment. Provides a LiveData which watches over all 40 * custom permission groups, and sends async updates when these groups have changes. 41 * 42 * @param app The current application of the fragment 43 */ 44 class ManageCustomPermissionsViewModel(private val app: Application) : AndroidViewModel(app) { 45 46 val uiDataLiveData = PermGroupsPackagesUiInfoLiveData(app, UsedCustomPermGroupNamesLiveData()) 47 val additionaPermGroupsUiInfo = 48 PermGroupsPackagesUiInfoLiveData( 49 app, 50 if (Flags.declutteredPermissionManagerEnabled()) AdditionalPermGroupNamesLiveData(app) 51 else MutableLiveData<List<String>>(), 52 ) 53 54 /** 55 * Navigate to a Permission Apps fragment 56 * 57 * @param fragment The fragment we are navigating from 58 * @param args The args to pass to the new fragment 59 */ showPermissionAppsnull60 fun showPermissionApps(fragment: Fragment, args: Bundle) { 61 val groupName = args.getString(Intent.EXTRA_PERMISSION_GROUP_NAME) 62 if (groupName == Manifest.permission_group.NOTIFICATIONS) { 63 Utils.navigateToNotificationSettings(fragment.context!!) 64 return 65 } 66 if (Utils.isHealthPermissionUiEnabled() && groupName == HEALTH_PERMISSION_GROUP) { 67 Utils.navigateToHealthConnectSettings(fragment.context!!) 68 return 69 } 70 fragment.findNavController().navigateSafe(R.id.manage_to_perm_apps, args) 71 } 72 } 73 74 /** 75 * Factory for a ManageCustomPermissionsViewModel 76 * 77 * @param app The current application of the fragment 78 */ 79 class ManageCustomPermissionsViewModelFactory(private val app: Application) : 80 ViewModelProvider.Factory { createnull81 override fun <T : ViewModel> create(modelClass: Class<T>): T { 82 @Suppress("UNCHECKED_CAST") 83 return ManageCustomPermissionsViewModel(app) as T 84 } 85 } 86 87 /** 88 * A LiveData which tracks the names of Custom Permission Groups which are used by at least one 89 * package. This includes single-permission permission groups, as well as the Undefined permission 90 * group, and any other permission groups not defined by the system. 91 */ 92 class UsedCustomPermGroupNamesLiveData : SmartUpdateMediatorLiveData<List<String>>() { 93 94 init { <lambda>null95 addSource(PermGroupsPackagesLiveData.get(customGroups = true)) { value = it.keys.toList() } 96 } 97 onUpdatenull98 override fun onUpdate() { 99 /* No op override */ 100 } 101 } 102 103 /** 104 * A LiveData that is the union of LiveData UsedCustomPermGroupNamesLiveData and 105 * UnusedStandardPermGroupNamesLiveData. 106 * 107 * @param app The current application of the fragment 108 */ 109 class AdditionalPermGroupNamesLiveData(private val app: Application) : 110 SmartUpdateMediatorLiveData<List<String>>() { 111 112 val usedCustomGroupNames = UsedCustomPermGroupNamesLiveData() 113 val unusedStandardGroupNames = UnusedStandardPermGroupNamesLiveData(app) 114 115 init { <lambda>null116 addSource(usedCustomGroupNames) { update() } <lambda>null117 addSource(unusedStandardGroupNames) { update() } 118 } 119 combineGroupNamesnull120 private fun combineGroupNames( 121 groupNames1: List<String>?, 122 groupNames2: List<String>?, 123 ): List<String> { 124 return (groupNames1 ?: emptyList()) + (groupNames2 ?: emptyList()) 125 } 126 onUpdatenull127 override fun onUpdate() { 128 value = combineGroupNames(usedCustomGroupNames.value, unusedStandardGroupNames.value) 129 } 130 } 131