• 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.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 ) : SmartAsyncMediatorLiveData<Set<String>>(),
45         PackageBroadcastReceiver.PackageBroadcastListener,
46         HasIntentAction {
47 
48     private val name = intentAction.substringAfterLast(".")
49 
50     private val enabledDeviceAdminsLiveDataLiveData = EnabledDeviceAdminsLiveData[user]
51 
52     init {
53         if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED) {
54             addSource(enabledDeviceAdminsLiveDataLiveData) {
55                 updateAsync()
56             }
57         }
58     }
59 
60     override fun onPackageUpdate(packageName: String) {
61         updateAsync()
62     }
63 
64     override suspend fun loadDataAndPostValue(job: Job) {
65         if (job.isCancelled) {
66             return
67         }
68         if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED &&
69                 !enabledDeviceAdminsLiveDataLiveData.isInitialized) {
70             return
71         }
72 
73         val packageNames = getUserContext(app, user).packageManager
74                 .queryBroadcastReceivers(
75                         Intent(intentAction),
76                         PackageManager.GET_RECEIVERS or PackageManager.GET_META_DATA)
77                 .mapNotNull { resolveInfo ->
78                     if (resolveInfo?.activityInfo?.permission != permission) {
79                         return@mapNotNull null
80                     }
81                     val packageName = resolveInfo.activityInfo?.packageName
82                     if (!isReceiverEnabled(packageName)) {
83                         if (DEBUG_HIBERNATION_POLICY) {
84                             DumpableLog.i(LOG_TAG,
85                                     "Not exempting $packageName - not an active $name " +
86                                             "for u${user.identifier}")
87                         }
88                         return@mapNotNull null
89                     }
90                     packageName
91                 }.toSet()
92         if (DEBUG_HIBERNATION_POLICY) {
93             DumpableLog.i(LOG_TAG,
94                     "Detected ${intentAction.substringAfterLast(".")}s: $packageNames")
95         }
96 
97         postValue(packageNames)
98     }
99 
100     private fun isReceiverEnabled(pkg: String?): Boolean {
101         if (pkg == null) {
102             return false
103         }
104         return when (intentAction) {
105             DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED -> {
106                 pkg in enabledDeviceAdminsLiveDataLiveData.value!!
107             }
108             else -> true
109         }
110     }
111 
112     override fun onActive() {
113         super.onActive()
114 
115         PackageBroadcastReceiver.addAllCallback(this)
116     }
117 
118     override fun onInactive() {
119         super.onInactive()
120 
121         PackageBroadcastReceiver.removeAllCallback(this)
122     }
123 
124     /**
125      * Repository for [BroadcastReceiverLiveData]
126      *
127      * <p> Key value is a (string intent action, required permission, user) triple, value is its
128      * corresponding LiveData.
129      */
130     companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
131             BroadcastReceiverLiveData>() {
132         private const val LOG_TAG = "BroadcastReceiverLiveData"
133 
134         override fun newValue(key: Triple<String, String, UserHandle>): BroadcastReceiverLiveData {
135             return BroadcastReceiverLiveData(PermissionControllerApplication.get(),
136                     key.first, key.second, key.third)
137         }
138     }
139 }