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