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.content.pm.PackageItemInfo 21 import android.content.pm.PackageManager 22 import android.content.pm.PermissionGroupInfo 23 import android.content.pm.PermissionInfo 24 import android.os.UserHandle 25 import android.util.Log 26 import com.android.permissioncontroller.PermissionControllerApplication 27 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermGroupInfo 28 import com.android.permissioncontroller.permission.model.livedatatypes.LightPermInfo 29 import com.android.permissioncontroller.permission.model.livedatatypes.PermGroup 30 import com.android.permissioncontroller.permission.utils.Utils 31 32 /** 33 * LiveData for a Permission Group. Contains GroupInfo and a list of PermissionInfos. Loads 34 * synchronously. 35 * 36 * @param app The current application 37 * @param groupName The name of the permission group this LiveData represents 38 */ 39 class PermGroupLiveData 40 private constructor(private val app: Application, private val groupName: String) : 41 SmartUpdateMediatorLiveData<PermGroup>(), PackageBroadcastReceiver.PackageBroadcastListener { 42 43 private val LOG_TAG = this::class.java.simpleName 44 45 private val context = app.applicationContext!! 46 47 /** Map<packageName, LiveData<PackageInfo>> */ 48 private val packageLiveDatas = mutableMapOf<String, LightPackageInfoLiveData>() 49 50 private lateinit var groupInfo: PackageItemInfo 51 52 /** 53 * Called when a package is installed, changed, or removed. 54 * 55 * @param packageName the package which was added or changed 56 */ 57 override fun onPackageUpdate(packageName: String) { 58 update() 59 } 60 61 /** 62 * Initializes this permission group from scratch. Resets the groupInfo, PermissionInfos, and 63 * PackageInfoLiveDatas, then re-adds them. 64 */ 65 override fun onUpdate() { 66 val permissionInfos = mutableMapOf<String, LightPermInfo>() 67 68 groupInfo = 69 Utils.getGroupInfo(groupName, context) 70 ?: run { 71 Log.e(LOG_TAG, "Invalid permission group $groupName") 72 invalidateSingle(groupName) 73 value = null 74 return 75 } 76 77 when (groupInfo) { 78 is PermissionGroupInfo -> { 79 val permInfos = 80 try { 81 Utils.getInstalledRuntimePermissionInfosForGroup( 82 context.packageManager, 83 groupName 84 ) 85 } catch (e: PackageManager.NameNotFoundException) { 86 Log.e(LOG_TAG, "Invalid permission group $groupName") 87 invalidateSingle(groupName) 88 value = null 89 return 90 } 91 92 for (permInfo in permInfos) { 93 permissionInfos[permInfo.name] = LightPermInfo(permInfo) 94 } 95 } 96 is PermissionInfo -> { 97 permissionInfos[groupInfo.name] = LightPermInfo(groupInfo as PermissionInfo) 98 } 99 else -> { 100 value = null 101 return 102 } 103 } 104 105 val permGroup = PermGroup(LightPermGroupInfo(groupInfo), permissionInfos) 106 107 value = permGroup 108 109 val packageNames = 110 permissionInfos.values.map { permInfo -> permInfo.packageName }.toMutableSet() 111 packageNames.add(groupInfo.packageName) 112 113 // TODO ntmyren: What if the package isn't installed for the system user? 114 val getLiveData = { packageName: String -> 115 LightPackageInfoLiveData[packageName, UserHandle.SYSTEM] 116 } 117 setSourcesToDifference(packageNames, packageLiveDatas, getLiveData) 118 } 119 120 override fun onInactive() { 121 super.onInactive() 122 123 PackageBroadcastReceiver.removeAllCallback(this) 124 } 125 126 /** 127 * Load data, and register a package change listener. We must watch for package changes, because 128 * there is currently no listener for permission changes. 129 */ 130 override fun onActive() { 131 update() 132 133 super.onActive() 134 135 PackageBroadcastReceiver.addAllCallback(this) 136 } 137 138 /** 139 * Repository for PermGroupLiveDatas. 140 * 141 * <p> Key value is a string permission group name, value is its corresponding LiveData. 142 */ 143 companion object : DataRepository<String, PermGroupLiveData>() { 144 override fun newValue(key: String): PermGroupLiveData { 145 return PermGroupLiveData(PermissionControllerApplication.get(), key) 146 } 147 } 148 } 149