• 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 
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