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.PackageInfo 21 import android.content.pm.PackageManager 22 import android.os.UserHandle 23 import com.android.permissioncontroller.PermissionControllerApplication 24 import com.android.permissioncontroller.permission.model.livedatatypes.LightPackageInfo 25 import com.android.permissioncontroller.permission.model.livedatatypes.PermState 26 import com.android.permissioncontroller.permission.utils.Utils 27 import kotlinx.coroutines.Job 28 29 /** 30 * A LiveData which tracks the permission state for one permission group for one package. It 31 * includes both the granted state of every permission in the group, and the flags stored 32 * in the PermissionController service. 33 * 34 * @param app The current application 35 * @param packageName The name of the package this LiveData will watch for mode changes for 36 * @param permGroupName The name of the permission group whose app ops this LiveData 37 * will watch 38 * @param user The user of the package 39 */ 40 class PermStateLiveData private constructor( 41 private val app: Application, 42 private val packageName: String, 43 private val permGroupName: String, 44 private val user: UserHandle 45 ) : SmartAsyncMediatorLiveData<Map<String, PermState>>(), 46 PermissionListenerMultiplexer.PermissionChangeCallback { 47 48 private val context = Utils.getUserContext(app, user) 49 private val packageInfoLiveData = LightPackageInfoLiveData[packageName, user] 50 private val groupLiveData = PermGroupLiveData[permGroupName] 51 52 private var uid: Int? = null 53 private var registeredUid: Int? = null 54 private var currentPackageInfo: LightPackageInfo? = null 55 56 init { 57 addSource(packageInfoLiveData) { 58 checkForUidUpdate(it) 59 currentPackageInfo = it 60 updateAsync() 61 } 62 63 addSource(groupLiveData) { 64 updateAsync() 65 } 66 } 67 68 /** 69 * Gets the system flags from the package manager, and the grant state from those flags, plus 70 * the RequestedPermissionFlags of the PermState. 71 */ 72 override suspend fun loadDataAndPostValue(job: Job) { 73 if (!packageInfoLiveData.isInitialized || !groupLiveData.isInitialized) { 74 return 75 } 76 77 val packageInfo = currentPackageInfo 78 val permissionGroup = groupLiveData.value 79 if (packageInfo == null || permissionGroup == null) { 80 invalidateSingle(Triple(packageName, permGroupName, user)) 81 postValue(null) 82 return 83 } 84 val permissionStates = mutableMapOf<String, PermState>() 85 for ((index, permissionName) in packageInfo.requestedPermissions.withIndex()) { 86 87 permissionGroup.permissionInfos[permissionName]?.let { permInfo -> 88 val packageFlags = packageInfo.requestedPermissionsFlags[index] 89 val permFlags = context.packageManager.getPermissionFlags(permInfo.name, 90 packageName, user) 91 val granted = packageFlags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0 && 92 permFlags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT == 0 93 94 if (job.isCancelled) { 95 return 96 } 97 permissionStates[permissionName] = PermState(permFlags, granted) 98 } 99 } 100 101 postValue(permissionStates) 102 } 103 104 override fun onPermissionChange() { 105 updateAsync() 106 } 107 108 private fun checkForUidUpdate(packageInfo: LightPackageInfo?) { 109 if (packageInfo == null) { 110 registeredUid?.let { 111 PermissionListenerMultiplexer.removeCallback(it, this) 112 } 113 return 114 } 115 uid = packageInfo.uid 116 if (uid != registeredUid && hasActiveObservers()) { 117 PermissionListenerMultiplexer.addOrReplaceCallback( 118 registeredUid, packageInfo.uid, this) 119 registeredUid = uid 120 } 121 } 122 123 override fun onInactive() { 124 super.onInactive() 125 registeredUid?.let { 126 PermissionListenerMultiplexer.removeCallback(it, this) 127 registeredUid = null 128 } 129 } 130 131 override fun onActive() { 132 super.onActive() 133 uid?.let { 134 PermissionListenerMultiplexer.addCallback(it, this) 135 registeredUid = uid 136 } 137 updateAsync() 138 } 139 140 /** 141 * Repository for PermStateLiveDatas. 142 * <p> Key value is a triple of string package name, string permission group name, and UserHandle, 143 * value is its corresponding LiveData. 144 */ 145 companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>, 146 PermStateLiveData>() { 147 override fun newValue(key: Triple<String, String, UserHandle>): PermStateLiveData { 148 return PermStateLiveData(PermissionControllerApplication.get(), 149 key.first, key.second, key.third) 150 } 151 } 152 } 153