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 update() 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 val (_, removed) = 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 for (removedKey in removed) { 108 shownPackages.remove(removedKey) 109 } 110 111 if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) { 112 permGroupLiveData.value?.groupInfo?.let { 113 value = shownPackages.toMap() 114 } 115 } 116 } 117 118 /** 119 * Repository for SinglePermGroupPackagesUiInfoLiveData objects. 120 * <p> Key value is a string permission group name, value is its corresponding LiveData. 121 */ 122 companion object : DataRepository<String, 123 SinglePermGroupPackagesUiInfoLiveData>() { 124 override fun newValue(key: String): SinglePermGroupPackagesUiInfoLiveData { 125 return SinglePermGroupPackagesUiInfoLiveData(PermissionControllerApplication.get(), 126 key) 127 } 128 } 129 }