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 17 package com.android.permissioncontroller.permission.data 18 19 import android.accessibilityservice.AccessibilityService 20 import android.app.Application 21 import android.app.admin.DevicePolicyManager 22 import android.content.Intent 23 import android.content.pm.PackageManager 24 import android.os.UserHandle 25 import android.printservice.PrintService 26 import android.service.autofill.AutofillService 27 import android.service.dreams.DreamService 28 import android.service.notification.NotificationListenerService 29 import android.service.voice.VoiceInteractionService 30 import android.service.wallpaper.WallpaperService 31 import android.view.inputmethod.InputMethod 32 import com.android.permissioncontroller.DumpableLog 33 import com.android.permissioncontroller.PermissionControllerApplication 34 import com.android.permissioncontroller.hibernation.DEBUG_HIBERNATION_POLICY 35 import com.android.permissioncontroller.permission.utils.Utils.getUserContext 36 import kotlinx.coroutines.Job 37 38 /** 39 * A LiveData which tracks services for a certain type 40 * 41 * @param app The current application 42 * @param intentAction The name of interface the service implements 43 * @param permission The permission required for the service 44 * @param user The user the services should be determined for 45 */ 46 class ServiceLiveData( 47 private val app: Application, 48 override val intentAction: String, 49 private val permission: String, 50 private val user: UserHandle 51 ) : SmartAsyncMediatorLiveData<Set<String>>(), 52 PackageBroadcastReceiver.PackageBroadcastListener, 53 HasIntentAction { 54 55 private val name = intentAction.substringAfterLast(".") 56 57 private val enabledAccessibilityServicesLiveData = EnabledAccessibilityServicesLiveData[user] 58 private val enabledInputMethodsLiveData = EnabledInputMethodsLiveData[user] 59 private val enabledNotificationListenersLiveData = EnabledNotificationListenersLiveData[user] 60 private val selectedWallpaperServiceLiveData = SelectedWallpaperServiceLiveData[user] 61 private val selectedVoiceInteractionServiceLiveData = 62 SelectedVoiceInteractionServiceLiveData[user] 63 private val selectedAutofillServiceLiveData = SelectedAutofillServiceLiveData[user] 64 private val enabledDreamServicesLiveData = EnabledDreamServicesLiveData[user] 65 private val disabledPrintServicesLiveData = DisabledPrintServicesLiveData[user] 66 private val enabledDeviceAdminsLiveDataLiveData = EnabledDeviceAdminsLiveData[user] 67 68 init { 69 if (intentAction == AccessibilityService.SERVICE_INTERFACE) { 70 addSource(enabledAccessibilityServicesLiveData) { 71 updateAsync() 72 } 73 } 74 if (intentAction == InputMethod.SERVICE_INTERFACE) { 75 addSource(enabledInputMethodsLiveData) { 76 updateAsync() 77 } 78 } 79 if (intentAction == NotificationListenerService.SERVICE_INTERFACE) { 80 addSource(enabledNotificationListenersLiveData) { 81 updateAsync() 82 } 83 } 84 if (intentAction == WallpaperService.SERVICE_INTERFACE) { 85 addSource(selectedWallpaperServiceLiveData) { 86 updateAsync() 87 } 88 } 89 if (intentAction == VoiceInteractionService.SERVICE_INTERFACE) { 90 addSource(selectedVoiceInteractionServiceLiveData) { 91 updateAsync() 92 } 93 } 94 if (intentAction == AutofillService.SERVICE_INTERFACE) { 95 addSource(selectedAutofillServiceLiveData) { 96 updateAsync() 97 } 98 } 99 if (intentAction == DreamService.SERVICE_INTERFACE) { 100 addSource(enabledDreamServicesLiveData) { 101 updateAsync() 102 } 103 } 104 if (intentAction == PrintService.SERVICE_INTERFACE) { 105 addSource(disabledPrintServicesLiveData) { 106 updateAsync() 107 } 108 } 109 if (intentAction == DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE) { 110 addSource(enabledDeviceAdminsLiveDataLiveData) { 111 updateAsync() 112 } 113 } 114 } 115 116 override fun onPackageUpdate(packageName: String) { 117 updateAsync() 118 } 119 120 override suspend fun loadDataAndPostValue(job: Job) { 121 if (job.isCancelled) { 122 return 123 } 124 if (intentAction == AccessibilityService.SERVICE_INTERFACE && 125 !enabledAccessibilityServicesLiveData.isInitialized) { 126 return 127 } 128 if (intentAction == InputMethod.SERVICE_INTERFACE && 129 !enabledInputMethodsLiveData.isInitialized) { 130 return 131 } 132 if (intentAction == NotificationListenerService.SERVICE_INTERFACE && 133 !enabledNotificationListenersLiveData.isInitialized) { 134 return 135 } 136 137 if (intentAction == WallpaperService.SERVICE_INTERFACE && 138 !selectedWallpaperServiceLiveData.isInitialized) { 139 return 140 } 141 if (intentAction == VoiceInteractionService.SERVICE_INTERFACE && 142 !selectedVoiceInteractionServiceLiveData.isInitialized) { 143 return 144 } 145 if (intentAction == AutofillService.SERVICE_INTERFACE && 146 !selectedAutofillServiceLiveData.isInitialized) { 147 return 148 } 149 if (intentAction == DreamService.SERVICE_INTERFACE && 150 !enabledDreamServicesLiveData.isInitialized) { 151 return 152 } 153 if (intentAction == PrintService.SERVICE_INTERFACE && 154 !disabledPrintServicesLiveData.isInitialized) { 155 return 156 } 157 if (intentAction == DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE && 158 !enabledDeviceAdminsLiveDataLiveData.isInitialized) { 159 return 160 } 161 162 val packageNames = getUserContext(app, user).packageManager 163 .queryIntentServices( 164 Intent(intentAction), 165 PackageManager.GET_SERVICES or PackageManager.GET_META_DATA) 166 .mapNotNull { resolveInfo -> 167 if (resolveInfo?.serviceInfo?.permission != permission) { 168 return@mapNotNull null 169 } 170 val packageName = resolveInfo?.serviceInfo?.packageName 171 if (!isServiceEnabled(packageName)) { 172 if (DEBUG_HIBERNATION_POLICY) { 173 DumpableLog.i(LOG_TAG, 174 "Not exempting $packageName - not an active $name " + 175 "for u${user.identifier}") 176 } 177 return@mapNotNull null 178 } 179 packageName 180 }.toSet() 181 if (DEBUG_HIBERNATION_POLICY) { 182 DumpableLog.i(LOG_TAG, 183 "Detected ${name}s: $packageNames") 184 } 185 186 postValue(packageNames) 187 } 188 189 suspend fun isServiceEnabled(pkg: String?): Boolean { 190 if (pkg == null) { 191 return false 192 } 193 return when (intentAction) { 194 AccessibilityService.SERVICE_INTERFACE -> { 195 pkg in enabledAccessibilityServicesLiveData.value!! 196 } 197 InputMethod.SERVICE_INTERFACE -> { 198 pkg in enabledInputMethodsLiveData.value!! 199 } 200 NotificationListenerService.SERVICE_INTERFACE -> { 201 pkg in enabledNotificationListenersLiveData.value!! 202 } 203 WallpaperService.SERVICE_INTERFACE -> { 204 pkg == selectedWallpaperServiceLiveData.value 205 } 206 VoiceInteractionService.SERVICE_INTERFACE -> { 207 pkg == selectedVoiceInteractionServiceLiveData.value 208 } 209 AutofillService.SERVICE_INTERFACE -> { 210 pkg == selectedAutofillServiceLiveData.value 211 } 212 DreamService.SERVICE_INTERFACE -> { 213 pkg in enabledDreamServicesLiveData.value!! 214 } 215 PrintService.SERVICE_INTERFACE -> { 216 pkg !in disabledPrintServicesLiveData.value!! 217 } 218 DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE -> { 219 pkg in enabledDeviceAdminsLiveDataLiveData.value!! 220 } 221 else -> true 222 } 223 } 224 225 override fun onActive() { 226 super.onActive() 227 228 PackageBroadcastReceiver.addAllCallback(this) 229 } 230 231 override fun onInactive() { 232 super.onInactive() 233 234 PackageBroadcastReceiver.removeAllCallback(this) 235 } 236 237 /** 238 * Repository for [ServiceLiveData] 239 * 240 * <p> Key value is a (string service name, required permission, user) triple, value is its 241 * corresponding LiveData. 242 */ 243 companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>, 244 ServiceLiveData>() { 245 private const val LOG_TAG = "ServiceLiveData" 246 247 override fun newValue(key: Triple<String, String, UserHandle>): ServiceLiveData { 248 return ServiceLiveData(PermissionControllerApplication.get(), 249 key.first, key.second, key.third) 250 } 251 } 252 } 253