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.PermissionMapping 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 34 private constructor(private val app: Application, private val permGroupName: String) : 35 SmartUpdateMediatorLiveData<Map<Pair<String, UserHandle>, AppPermGroupUiInfo>>() { 36 37 private val permGroupLiveData = PermGroupLiveData[permGroupName] 38 private val isCustomGroup = 39 !PermissionMapping.getPlatformPermissionGroups().contains(permGroupName) 40 private val permGroupPackagesLiveData = 41 PermGroupsPackagesLiveData.get(customGroups = isCustomGroup) 42 43 /** Map<Pair<package name, UserHandle>, UI data LiveData> */ 44 private val appPermGroupLiveDatas = 45 mutableMapOf<Pair<String, UserHandle>, AppPermGroupUiInfoLiveData>() 46 47 /** Map<Pair<packageName, userHandle>, UI data>. */ 48 private val shownPackages = mutableMapOf<Pair<String, UserHandle>, AppPermGroupUiInfo>() 49 50 init { 51 addSource(permGroupLiveData) { newPermGroup -> 52 if (newPermGroup == null) { 53 invalidateSingle(permGroupName) 54 value = null 55 } 56 } 57 58 addSource(permGroupPackagesLiveData) { update() } 59 } 60 61 override fun onUpdate() { 62 val thisPermGroupPackages = permGroupPackagesLiveData.value?.get(permGroupName) 63 if (thisPermGroupPackages != null) { 64 addAndRemoveAppPermGroupLiveDatas(thisPermGroupPackages.toList()) 65 66 if (thisPermGroupPackages.isEmpty()) { 67 permGroupLiveData.value?.groupInfo?.let { value = emptyMap() } 68 } 69 } 70 } 71 72 private fun addAndRemoveAppPermGroupLiveDatas(pkgs: List<Pair<String, UserHandle>>) { 73 val getLiveData = { key: Pair<String, UserHandle> -> 74 AppPermGroupUiInfoLiveData[key.first, permGroupName, key.second] 75 } 76 77 val (_, removed) = 78 setSourcesToDifference(pkgs, appPermGroupLiveDatas, getLiveData) { key -> 79 val appPermGroupUiInfoLiveData = appPermGroupLiveDatas[key] 80 val appPermGroupUiInfo = appPermGroupUiInfoLiveData?.value 81 shownPackages.remove(key) 82 83 if (appPermGroupUiInfo == null) { 84 if ( 85 appPermGroupUiInfoLiveData != null && 86 appPermGroupUiInfoLiveData.isInitialized 87 ) { 88 removeSource(appPermGroupUiInfoLiveData) 89 appPermGroupLiveDatas.remove(key) 90 } 91 } else { 92 shownPackages[key] = appPermGroupUiInfo 93 } 94 95 if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) { 96 permGroupLiveData.value?.groupInfo?.let { value = shownPackages.toMap() } 97 } 98 } 99 100 for (removedKey in removed) { 101 shownPackages.remove(removedKey) 102 } 103 104 if (appPermGroupLiveDatas.all { entry -> entry.value.isInitialized }) { 105 permGroupLiveData.value?.groupInfo?.let { value = shownPackages.toMap() } 106 } 107 } 108 109 /** 110 * Repository for SinglePermGroupPackagesUiInfoLiveData objects. 111 * 112 * <p> Key value is a string permission group name, value is its corresponding LiveData. 113 */ 114 companion object : DataRepository<String, SinglePermGroupPackagesUiInfoLiveData>() { 115 override fun newValue(key: String): SinglePermGroupPackagesUiInfoLiveData { 116 return SinglePermGroupPackagesUiInfoLiveData(PermissionControllerApplication.get(), key) 117 } 118 } 119 } 120