• 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.app.Application
20 import android.app.admin.DeviceAdminReceiver
21 import android.content.Intent
22 import android.content.pm.PackageManager
23 import android.os.UserHandle
24 import com.android.permissioncontroller.DumpableLog
25 import com.android.permissioncontroller.PermissionControllerApplication
26 import com.android.permissioncontroller.hibernation.DEBUG_HIBERNATION_POLICY
27 import com.android.permissioncontroller.permission.utils.Utils.getUserContext
28 import kotlinx.coroutines.Job
29 
30 /**
31  * A LiveData which tracks broadcast receivers for a certain type
32  *
33  * @param app The current application
34  * @param intentAction The name of the action the receiver receives
35  * @param permission The permission required for the receiver
36  * @param user The user the receivers should be determined for
37  */
38 class BroadcastReceiverLiveData(
39     private val app: Application,
40     override val intentAction: String,
41     private val permission: String,
42     private val user: UserHandle
43 ) : SmartAsyncMediatorLiveData<Set<String>>(),
44         PackageBroadcastReceiver.PackageBroadcastListener,
45         HasIntentAction {
46 
47     private val name = intentAction.substringAfterLast(".")
48 
49     private val enabledDeviceAdminsLiveDataLiveData = EnabledDeviceAdminsLiveData[user]
50 
51     init {
52         if (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED) {
53             addSource(enabledDeviceAdminsLiveDataLiveData) {
54                 updateAsync()
55             }
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 (intentAction == DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED &&
68                 !enabledDeviceAdminsLiveDataLiveData.isInitialized) {
69             return
70         }
71 
72         val packageNames = getUserContext(app, user).packageManager
73                 .queryBroadcastReceivers(
74                         Intent(intentAction),
75                         PackageManager.GET_RECEIVERS or PackageManager.GET_META_DATA)
76                 .mapNotNull { resolveInfo ->
77                     if (resolveInfo?.activityInfo?.permission != permission) {
78                         return@mapNotNull null
79                     }
80                     val packageName = resolveInfo?.activityInfo?.packageName
81                     if (!isReceiverEnabled(packageName)) {
82                         if (DEBUG_HIBERNATION_POLICY) {
83                             DumpableLog.i(LOG_TAG,
84                                     "Not exempting $packageName - not an active $name " +
85                                             "for u${user.identifier}")
86                         }
87                         return@mapNotNull null
88                     }
89                     packageName
90                 }.toSet()
91         if (DEBUG_HIBERNATION_POLICY) {
92             DumpableLog.i(LOG_TAG,
93                     "Detected ${intentAction.substringAfterLast(".")}s: $packageNames")
94         }
95 
96         postValue(packageNames)
97     }
98 
99     private fun isReceiverEnabled(pkg: String?): Boolean {
100         if (pkg == null) {
101             return false
102         }
103         return when (intentAction) {
104             DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED -> {
105                 pkg in enabledDeviceAdminsLiveDataLiveData.value!!
106             }
107             else -> true
108         }
109     }
110 
111     override fun onActive() {
112         super.onActive()
113 
114         PackageBroadcastReceiver.addAllCallback(this)
115     }
116 
117     override fun onInactive() {
118         super.onInactive()
119 
120         PackageBroadcastReceiver.removeAllCallback(this)
121     }
122 
123     /**
124      * Repository for [BroadcastReceiverLiveData]
125      *
126      * <p> Key value is a (string intent action, required permission, user) triple, value is its
127      * corresponding LiveData.
128      */
129     companion object : DataRepositoryForPackage<Triple<String, String, UserHandle>,
130             BroadcastReceiverLiveData>() {
131         private const val LOG_TAG = "BroadcastReceiverLiveData"
132 
133         override fun newValue(key: Triple<String, String, UserHandle>): BroadcastReceiverLiveData {
134             return BroadcastReceiverLiveData(PermissionControllerApplication.get(),
135                     key.first, key.second, key.third)
136         }
137     }
138 }