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