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