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