1 /* <lambda>null2 * Copyright (C) 2021 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 @file:Suppress("DEPRECATION") 17 18 package com.android.permissioncontroller.permission.data 19 20 import android.app.Application 21 import android.app.admin.DeviceAdminReceiver 22 import android.content.Intent 23 import android.content.pm.PackageManager 24 import android.os.UserHandle 25 import com.android.permissioncontroller.DumpableLog 26 import com.android.permissioncontroller.PermissionControllerApplication 27 import com.android.permissioncontroller.hibernation.DEBUG_HIBERNATION_POLICY 28 import com.android.permissioncontroller.permission.utils.Utils.getUserContext 29 import kotlinx.coroutines.Job 30 31 /** 32 * A LiveData which tracks broadcast receivers for a certain type 33 * 34 * @param app The current application 35 * @param intentAction The name of the action the receiver receives 36 * @param permission The permission required for the receiver 37 * @param user The user the receivers should be determined for 38 */ 39 class BroadcastReceiverLiveData( 40 private val app: Application, 41 override val intentAction: String, 42 private val permission: String, 43 private val user: UserHandle 44 ) : 45 SmartAsyncMediatorLiveData<Set<String>>(), 46 PackageBroadcastReceiver.PackageBroadcastListener, 47 HasIntentAction { 48 49 private val name = intentAction.substringAfterLast(".") 50 51 private val enabledDeviceAdminsLiveDataLiveData = EnabledDeviceAdminsLiveData[user] 52 53 init { 54 if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED) { 55 addSource(enabledDeviceAdminsLiveDataLiveData) { updateAsync() } 56 } 57 } 58 59 override fun onPackageUpdate(packageName: String) { 60 updateAsync() 61 } 62 63 override suspend fun loadDataAndPostValue(job: Job) { 64 if (job.isCancelled) { 65 return 66 } 67 if ( 68 intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED && 69 !enabledDeviceAdminsLiveDataLiveData.isInitialized 70 ) { 71 return 72 } 73 74 val packageNames = 75 getUserContext(app, user) 76 .packageManager 77 .queryBroadcastReceivers( 78 Intent(intentAction), 79 PackageManager.GET_RECEIVERS or PackageManager.GET_META_DATA 80 ) 81 .mapNotNull { resolveInfo -> 82 if (resolveInfo?.activityInfo?.permission != permission) { 83 return@mapNotNull null 84 } 85 val packageName = resolveInfo.activityInfo?.packageName 86 if (!isReceiverEnabled(packageName)) { 87 if (DEBUG_HIBERNATION_POLICY) { 88 DumpableLog.i( 89 LOG_TAG, 90 "Not exempting $packageName - not an active $name " + 91 "for u${user.identifier}" 92 ) 93 } 94 return@mapNotNull null 95 } 96 packageName 97 } 98 .toSet() 99 if (DEBUG_HIBERNATION_POLICY) { 100 DumpableLog.i( 101 LOG_TAG, 102 "Detected ${intentAction.substringAfterLast(".")}s: $packageNames" 103 ) 104 } 105 106 postValue(packageNames) 107 } 108 109 private fun isReceiverEnabled(pkg: String?): Boolean { 110 if (pkg == null) { 111 return false 112 } 113 return when (intentAction) { 114 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED -> { 115 pkg in enabledDeviceAdminsLiveDataLiveData.value!! 116 } 117 else -> true 118 } 119 } 120 121 override fun onActive() { 122 super.onActive() 123 124 PackageBroadcastReceiver.addAllCallback(this) 125 } 126 127 override fun onInactive() { 128 super.onInactive() 129 130 PackageBroadcastReceiver.removeAllCallback(this) 131 } 132 133 /** 134 * Repository for [BroadcastReceiverLiveData] 135 * 136 * <p> Key value is a (string intent action, required permission, user) triple, value is its 137 * corresponding LiveData. 138 */ 139 companion object : 140 DataRepositoryForPackage<Triple<String, String, UserHandle>, BroadcastReceiverLiveData>() { 141 private const val LOG_TAG = "BroadcastReceiverLiveData" 142 143 override fun newValue(key: Triple<String, String, UserHandle>): BroadcastReceiverLiveData { 144 return BroadcastReceiverLiveData( 145 PermissionControllerApplication.get(), 146 key.first, 147 key.second, 148 key.third 149 ) 150 } 151 } 152 } 153