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 55 init { 56 addSource(packageInfoLiveData) { 57 checkForUidUpdate(it) 58 updateAsync() 59 } 60 61 addSource(groupLiveData) { 62 updateAsync() 63 } 64 } 65 66 /** 67 * Gets the system flags from the package manager, and the grant state from those flags, plus 68 * the RequestedPermissionFlags of the PermState. 69 */ 70 override suspend fun loadDataAndPostValue(job: Job) { 71 if (!packageInfoLiveData.isInitialized || !groupLiveData.isInitialized) { 72 return 73 } 74 75 val packageInfo = packageInfoLiveData.value 76 val permissionGroup = groupLiveData.value 77 if (packageInfo == null || permissionGroup == null) { 78 invalidateSingle(Triple(packageName, permGroupName, user)) 79 postValue(null) 80 return 81 } 82 val permissionStates = mutableMapOf<String, PermState>() 83 for ((index, permissionName) in packageInfo.requestedPermissions.withIndex()) { 84 85 permissionGroup.permissionInfos[permissionName]?.let { permInfo -> 86 val packageFlags = packageInfo.requestedPermissionsFlags[index] 87 val permFlags = context.packageManager.getPermissionFlags(permInfo.name, 88 packageName, user) 89 val granted = packageFlags and PackageInfo.REQUESTED_PERMISSION_GRANTED != 0 && 90 permFlags and PackageManager.FLAG_PERMISSION_REVOKED_COMPAT == 0 91 92 if (job.isCancelled) { 93 return 94 } 95 permissionStates[permissionName] = PermState(permFlags, granted) 96 } 97 } 98 99 postValue(permissionStates) 100 } 101 102 override fun onPermissionChange() { 103 updateAsync() 104 } 105 106 private fun checkForUidUpdate(packageInfo: LightPackageInfo?) { 107 if (packageInfo == null) { 108 registeredUid?.let { 109 PermissionListenerMultiplexer.removeCallback(it, this) 110 } 111 return 112 } 113 uid = packageInfo.uid 114 if (uid != registeredUid && hasActiveObservers()) { 115 PermissionListenerMultiplexer.addOrReplaceCallback( 116 registeredUid, packageInfo.uid, this) 117 registeredUid = uid 118 } 119 } 120 121 override fun onInactive() { 122 super.onInactive() 123 registeredUid?.let { 124 PermissionListenerMultiplexer.removeCallback(it, this) 125 registeredUid = null 126 } 127 } 128 129 override fun onActive() { 130 super.onActive() 131 uid?.let { 132 PermissionListenerMultiplexer.addCallback(it, this) 133 registeredUid = uid 134 } 135 } 136 137 /** 138 * Repository for PermStateLiveDatas. 139 * <p> Key value is a triple of string package name, string permission group name, and UserHandle, 140 * value is its corresponding LiveData. 141 */ 142 companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>, 143 PermStateLiveData>() { 144 override fun newValue(key: Triple<String, String, UserHandle>): PermStateLiveData { 145 return PermStateLiveData(PermissionControllerApplication.get(), 146 key.first, key.second, key.third) 147 } 148 } 149 } 150