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 android.test.suitebuilder.annotation.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.mock 46 import org.mockito.Mockito.never 47 import org.mockito.Mockito.verify 48 import org.mockito.MockitoAnnotations 49 import java.lang.IllegalArgumentException 50 import java.lang.IllegalStateException 51 import java.util.concurrent.Executor 52 53 @RunWith(AndroidTestingRunner::class) 54 @TestableLooper.RunWithLooper 55 @SmallTest 56 class ActionReceiverTest : SysuiTestCase() { 57 58 companion object { 59 private const val ACTION1 = "TEST_ACTION1" 60 private const val ACTION2 = "TEST_ACTION2" 61 private const val CATEGORY = "TEST_CATEGORY" 62 private val USER = UserHandle.of(0) sameNotNullnull63 private fun <T : Any> sameNotNull(arg: T): T = Mockito.same(arg) ?: arg 64 65 fun IntentFilter.matchesOther(it: IntentFilter): Boolean { 66 val actions = actionsIterator()?.asSequence()?.toSet() ?: emptySet() 67 val categories = categoriesIterator()?.asSequence()?.toSet() ?: emptySet() 68 return (it.actionsIterator()?.asSequence()?.toSet() ?: emptySet()) == actions && 69 (it.categoriesIterator()?.asSequence()?.toSet() ?: emptySet()) == categories && 70 it.countDataAuthorities() == 0 && 71 it.countDataPaths() == 0 && 72 it.countDataSchemes() == 0 && 73 it.countDataTypes() == 0 && 74 it.countMimeGroups() == 0 && 75 it.priority == 0 76 } 77 } 78 79 @Mock 80 private lateinit var registerFunction: BroadcastReceiver.(IntentFilter) -> Unit 81 @Mock 82 private lateinit var unregisterFunction: BroadcastReceiver.() -> Unit 83 @Mock 84 private lateinit var receiver1: BroadcastReceiver 85 @Mock 86 private lateinit var receiver2: BroadcastReceiver 87 @Mock 88 private lateinit var logger: BroadcastDispatcherLogger 89 @Captor 90 private lateinit var intentFilterCaptor: ArgumentCaptor<IntentFilter> 91 92 private lateinit var executor: FakeExecutor 93 private lateinit var actionReceiver: ActionReceiver <lambda>null94 private val directExecutor = Executor { it.run() } 95 96 @Before setUpnull97 fun setUp() { 98 MockitoAnnotations.initMocks(this) 99 executor = FakeExecutor(FakeSystemClock()) 100 101 actionReceiver = ActionReceiver( 102 ACTION1, 103 USER.identifier, 104 registerFunction, 105 unregisterFunction, 106 executor, 107 logger 108 ) 109 } 110 111 @Test testStartsUnregisterednull112 fun testStartsUnregistered() { 113 assertFalse(actionReceiver.registered) 114 verify(registerFunction, never()).invoke(sameNotNull(actionReceiver), 115 any(IntentFilter::class.java)) 116 } 117 118 @Test testRegistersOnFirstAddnull119 fun testRegistersOnFirstAdd() { 120 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 121 122 actionReceiver.addReceiverData(receiverData) 123 124 assertTrue(actionReceiver.registered) 125 verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor)) 126 127 assertTrue(IntentFilter(ACTION1).matchesOther(intentFilterCaptor.value)) 128 } 129 130 @Test testRegistersOnlyOncenull131 fun testRegistersOnlyOnce() { 132 val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 133 val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER) 134 135 actionReceiver.addReceiverData(receiverData1) 136 actionReceiver.addReceiverData(receiverData2) 137 138 verify(registerFunction).invoke(sameNotNull(actionReceiver), any(IntentFilter::class.java)) 139 } 140 141 @Test testRemovingLastReceiverUnregistersnull142 fun testRemovingLastReceiverUnregisters() { 143 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 144 145 actionReceiver.addReceiverData(receiverData) 146 147 actionReceiver.removeReceiver(receiver1) 148 149 assertFalse(actionReceiver.registered) 150 verify(unregisterFunction).invoke(sameNotNull(actionReceiver)) 151 } 152 153 @Test testRemovingWhileOtherReceiversDoesntUnregisternull154 fun testRemovingWhileOtherReceiversDoesntUnregister() { 155 val receiverData1 = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 156 val receiverData2 = ReceiverData(receiver2, IntentFilter(ACTION1), directExecutor, USER) 157 158 actionReceiver.addReceiverData(receiverData1) 159 actionReceiver.addReceiverData(receiverData2) 160 161 actionReceiver.removeReceiver(receiver1) 162 163 assertTrue(actionReceiver.registered) 164 verify(unregisterFunction, never()).invoke(any(BroadcastReceiver::class.java)) 165 } 166 167 @Test testReceiverHasCategoriesnull168 fun testReceiverHasCategories() { 169 val filter = IntentFilter(ACTION1) 170 filter.addCategory(CATEGORY) 171 172 val receiverData = ReceiverData(receiver1, filter, directExecutor, USER) 173 174 actionReceiver.addReceiverData(receiverData) 175 176 verify(registerFunction).invoke(sameNotNull(actionReceiver), capture(intentFilterCaptor)) 177 assertTrue(intentFilterCaptor.value.hasCategory(CATEGORY)) 178 } 179 180 @Test(expected = IllegalArgumentException::class) testNotRegisteredWithWrongAction_throwsExceptionnull181 fun testNotRegisteredWithWrongAction_throwsException() { 182 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION2), directExecutor, USER) 183 184 actionReceiver.addReceiverData(receiverData) 185 } 186 187 @Test testReceiverGetsBroadcastnull188 fun testReceiverGetsBroadcast() { 189 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 190 actionReceiver.addReceiverData(receiverData) 191 192 val intent = Intent(ACTION1) 193 194 actionReceiver.onReceive(mContext, intent) 195 196 executor.runAllReady() 197 198 verify(receiver1).onReceive(any(Context::class.java), sameNotNull(intent)) 199 } 200 201 @Test testReceiverGetsPendingResultnull202 fun testReceiverGetsPendingResult() { 203 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 204 actionReceiver.addReceiverData(receiverData) 205 206 val intent = Intent(ACTION1) 207 val pendingResult = mock(BroadcastReceiver.PendingResult::class.java) 208 209 actionReceiver.pendingResult = pendingResult 210 actionReceiver.onReceive(mContext, intent) 211 212 executor.runAllReady() 213 verify(receiver1).pendingResult = pendingResult 214 } 215 216 @Test testBroadcastIsDispatchedInExecutornull217 fun testBroadcastIsDispatchedInExecutor() { 218 val executor = FakeExecutor(FakeSystemClock()) 219 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), executor, USER) 220 actionReceiver.addReceiverData(receiverData) 221 222 val intent = Intent(ACTION1) 223 actionReceiver.onReceive(mContext, intent) 224 225 this.executor.runAllReady() 226 227 verify(receiver1, never()).onReceive(mContext, intent) 228 229 executor.runAllReady() 230 // Dispatched after executor is processed 231 verify(receiver1).onReceive(mContext, intent) 232 } 233 234 @Test testBroadcastReceivedDispatched_loggernull235 fun testBroadcastReceivedDispatched_logger() { 236 val receiverData = ReceiverData(receiver1, IntentFilter(ACTION1), directExecutor, USER) 237 238 actionReceiver.addReceiverData(receiverData) 239 240 val intent = Intent(ACTION1) 241 actionReceiver.onReceive(mContext, intent) 242 verify(logger).logBroadcastReceived(anyInt(), eq(USER.identifier), eq(intent)) 243 244 verify(logger, never()).logBroadcastDispatched(anyInt(), anyString(), 245 any(BroadcastReceiver::class.java)) 246 247 executor.runAllReady() 248 249 verify(logger).logBroadcastDispatched(anyInt(), eq(ACTION1), sameNotNull(receiver1)) 250 } 251 252 @Test(expected = IllegalStateException::class) testBroadcastWithWrongAction_throwsExceptionnull253 fun testBroadcastWithWrongAction_throwsException() { 254 actionReceiver.onReceive(mContext, Intent(ACTION2)) 255 } 256 }