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