1 /* 2 * Copyright (C) 2020 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.systemui.broadcast 18 19 import android.content.BroadcastReceiver 20 import android.content.Context 21 import android.content.Intent 22 import android.content.IntentFilter 23 import android.os.UserHandle 24 import androidx.test.filters.SmallTest 25 import android.testing.AndroidTestingRunner 26 import android.testing.TestableLooper 27 import com.android.systemui.SysuiTestCase 28 import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger 29 import com.android.systemui.util.concurrency.FakeExecutor 30 import com.android.systemui.util.mockito.any 31 import com.android.systemui.util.mockito.capture 32 import com.android.systemui.util.mockito.eq 33 import com.android.systemui.util.time.FakeSystemClock 34 import org.junit.Assert.assertFalse 35 import org.junit.Assert.assertTrue 36 import org.junit.Before 37 import org.junit.Test 38 import org.junit.runner.RunWith 39 import org.mockito.ArgumentCaptor 40 import org.mockito.ArgumentMatchers.anyInt 41 import org.mockito.ArgumentMatchers.anyString 42 import org.mockito.Captor 43 import org.mockito.Mock 44 import org.mockito.Mockito 45 import org.mockito.Mockito.`when` 46 import org.mockito.Mockito.mock 47 import org.mockito.Mockito.never 48 import org.mockito.Mockito.verify 49 import org.mockito.MockitoAnnotations 50 import java.lang.IllegalArgumentException 51 import java.lang.IllegalStateException 52 import java.util.concurrent.Executor 53 54 @RunWith(AndroidTestingRunner::class) 55 @TestableLooper.RunWithLooper 56 @SmallTest 57 class ActionReceiverTest : SysuiTestCase() { 58 59 companion object { 60 private const val ACTION1 = "TEST_ACTION1" 61 private const val ACTION2 = "TEST_ACTION2" 62 private const val CATEGORY = "TEST_CATEGORY" 63 private val USER = UserHandle.of(0) sameNotNullnull64 private fun <T : Any> sameNotNull(arg: T): T = Mockito.same(arg) ?: arg 65 66 fun IntentFilter.matchesOther(it: IntentFilter): Boolean { 67 val actions = actionsIterator()?.asSequence()?.toSet() ?: emptySet() 68 val categories = categoriesIterator()?.asSequence()?.toSet() ?: emptySet() 69 return (it.actionsIterator()?.asSequence()?.toSet() ?: emptySet()) == actions && 70 (it.categoriesIterator()?.asSequence()?.toSet() ?: emptySet()) == categories && 71 it.countDataAuthorities() == 0 && 72 it.countDataPaths() == 0 && 73 it.countDataSchemes() == 0 && 74 it.countDataTypes() == 0 && 75 it.countMimeGroups() == 0 && 76 it.priority == 0 77 } 78 } 79 80 @Mock 81 private lateinit var registerFunction: BroadcastReceiver.(IntentFilter) -> Unit 82 @Mock 83 private lateinit var unregisterFunction: BroadcastReceiver.() -> Unit 84 @Mock 85 private lateinit var isPendingRemovalFunction: (BroadcastReceiver, Int) -> Boolean 86 @Mock 87 private lateinit var receiver1: BroadcastReceiver 88 @Mock 89 private lateinit var receiver2: BroadcastReceiver 90 @Mock 91 private lateinit var logger: BroadcastDispatcherLogger 92 @Captor 93 private lateinit var intentFilterCaptor: ArgumentCaptor<IntentFilter> 94 95 private lateinit var executor: FakeExecutor 96 private lateinit var actionReceiver: ActionReceiver <lambda>null97 private val directExecutor = Executor { it.run() } 98 99 @Before setUpnull100 fun setUp() { 101 MockitoAnnotations.initMocks(this) 102 executor = FakeExecutor(FakeSystemClock()) 103 104 `when`(isPendingRemovalFunction(any(), anyInt())).thenReturn(false) 105 106 actionReceiver = ActionReceiver( 107 ACTION1, 108 USER.identifier, 109 registerFunction, 110 unregisterFunction, 111 executor, 112 logger, 113 isPendingRemovalFunction 114 ) 115 } 116 117 @Test testStartsUnregisterednull118 fun testStartsUnregistered() { 119 assertFalse(actionReceiver.registered) 120 verify(registerFunction, never()).invoke(sameNotNull(actionReceiver), 121 any(IntentFilter::class.java)) 122 } 123 124 @Test testRegistersOnFirstAddnull125 fun testRegistersOnFirstAdd() { 126 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 127 128 actionReceiver.addReceiverData(receiverData) 129 130 assertTrue(actionReceiver.registered) 131 verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor)) 132 133 assertTrue(IntentFilter(ACTION1).matchesOther(intentFilterCaptor.value)) 134 } 135 136 @Test testRegistersOnlyOncenull137 fun testRegistersOnlyOnce() { 138 val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 139 val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER) 140 141 actionReceiver.addReceiverData(receiverData1) 142 actionReceiver.addReceiverData(receiverData2) 143 144 verify(registerFunction).invoke(sameNotNull(actionReceiver), any(IntentFilter::class.java)) 145 } 146 147 @Test testRemovingLastReceiverUnregistersnull148 fun testRemovingLastReceiverUnregisters() { 149 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 150 151 actionReceiver.addReceiverData(receiverData) 152 153 actionReceiver.removeReceiver(receiver1) 154 155 assertFalse(actionReceiver.registered) 156 verify(unregisterFunction).invoke(sameNotNull(actionReceiver)) 157 } 158 159 @Test testRemovingWhileOtherReceiversDoesntUnregisternull160 fun testRemovingWhileOtherReceiversDoesntUnregister() { 161 val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 162 val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER) 163 164 actionReceiver.addReceiverData(receiverData1) 165 actionReceiver.addReceiverData(receiverData2) 166 167 actionReceiver.removeReceiver(receiver1) 168 169 assertTrue(actionReceiver.registered) 170 verify(unregisterFunction, never()).invoke(any(BroadcastReceiver::class.java)) 171 } 172 173 @Test testReceiverHasCategoriesnull174 fun testReceiverHasCategories() { 175 val filter = IntentFilter(ACTION1) 176 filter.addCategory(CATEGORY) 177 178 val receiverData = ReceiverData(receiver1, filter, directExecutor, USER) 179 180 actionReceiver.addReceiverData(receiverData) 181 182 verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor)) 183 assertTrue(intentFilterCaptor.value.hasCategory(CATEGORY)) 184 } 185 186 @Test(expected = IllegalArgumentException::class) testNotRegisteredWithWrongAction_throwsExceptionnull187 fun testNotRegisteredWithWrongAction_throwsException() { 188 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION2), directExecutor, USER) 189 190 actionReceiver.addReceiverData(receiverData) 191 } 192 193 @Test testReceiverGetsBroadcastnull194 fun testReceiverGetsBroadcast() { 195 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 196 actionReceiver.addReceiverData(receiverData) 197 198 val intent = Intent(ACTION1) 199 200 actionReceiver.onReceive(mContext, intent) 201 202 executor.runAllReady() 203 204 verify(receiver1).onReceive(any(Context::class.java), sameNotNull(intent)) 205 } 206 207 @Test testReceiverGetsPendingResultnull208 fun testReceiverGetsPendingResult() { 209 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 210 actionReceiver.addReceiverData(receiverData) 211 212 val intent = Intent(ACTION1) 213 val pendingResult = mock(BroadcastReceiver.PendingResult::class.java) 214 215 actionReceiver.pendingResult = pendingResult 216 actionReceiver.onReceive(mContext, intent) 217 218 executor.runAllReady() 219 verify(receiver1).pendingResult = pendingResult 220 } 221 222 @Test testBroadcastIsDispatchedInExecutornull223 fun testBroadcastIsDispatchedInExecutor() { 224 val executor = FakeExecutor(FakeSystemClock()) 225 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), executor, USER) 226 actionReceiver.addReceiverData(receiverData) 227 228 val intent = Intent(ACTION1) 229 actionReceiver.onReceive(mContext, intent) 230 231 this.executor.runAllReady() 232 233 verify(receiver1, never()).onReceive(mContext, intent) 234 235 executor.runAllReady() 236 // Dispatched after executor is processed 237 verify(receiver1).onReceive(mContext, intent) 238 } 239 240 @Test testBroadcastReceivedDispatched_loggernull241 fun testBroadcastReceivedDispatched_logger() { 242 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 243 244 actionReceiver.addReceiverData(receiverData) 245 246 val intent = Intent(ACTION1) 247 actionReceiver.onReceive(mContext, intent) 248 verify(logger).logBroadcastReceived(anyInt(), eq(USER.identifier), eq(intent)) 249 250 verify(logger, never()).logBroadcastDispatched(anyInt(), anyString(), 251 any(BroadcastReceiver::class.java)) 252 253 executor.runAllReady() 254 255 verify(logger).logBroadcastDispatched(anyInt(), eq(ACTION1), sameNotNull(receiver1)) 256 } 257 258 @Test testBroadcastNotDispatchingOnPendingRemovalnull259 fun testBroadcastNotDispatchingOnPendingRemoval() { 260 `when`(isPendingRemovalFunction(receiver1, USER.identifier)).thenReturn(true) 261 262 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 263 264 actionReceiver.addReceiverData(receiverData) 265 266 val intent = Intent(ACTION1) 267 actionReceiver.onReceive(mContext, intent) 268 executor.runAllReady() 269 verify(receiver1, never()).onReceive(any(), eq(intent)) 270 } 271 272 @Test(expected = IllegalStateException::class) testBroadcastWithWrongAction_throwsExceptionnull273 fun testBroadcastWithWrongAction_throwsException() { 274 actionReceiver.onReceive(mContext, Intent(ACTION2)) 275 } 276 }