/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.broadcast import android.content.BroadcastReceiver import android.content.Context import android.content.IntentFilter import android.os.Handler import android.os.UserHandle import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertFalse import junit.framework.Assert.assertNotNull import junit.framework.Assert.assertNotSame import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.mock import org.mockito.Mockito.nullable import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import java.util.concurrent.Executor @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper @SmallTest class UserBroadcastDispatcherTest : SysuiTestCase() { companion object { private const val ACTION_1 = "com.android.systemui.tests.ACTION_1" private const val ACTION_2 = "com.android.systemui.tests.ACTION_2" private const val USER_ID = 0 private const val FLAG = 3 private val USER_HANDLE = UserHandle.of(USER_ID) fun capture(argumentCaptor: ArgumentCaptor): T = argumentCaptor.capture() fun any(): T = Mockito.any() fun eq(v: T) = Mockito.eq(v) ?: v } @Mock private lateinit var broadcastReceiver: BroadcastReceiver @Mock private lateinit var broadcastReceiverOther: BroadcastReceiver @Mock private lateinit var mockContext: Context @Mock private lateinit var logger: BroadcastDispatcherLogger @Mock private lateinit var removalPendingStore: PendingRemovalStore private lateinit var testableLooper: TestableLooper private lateinit var userBroadcastDispatcher: UserBroadcastDispatcher private lateinit var intentFilter: IntentFilter private lateinit var intentFilterOther: IntentFilter private lateinit var handler: Handler private lateinit var fakeExecutor: FakeExecutor @Before fun setUp() { MockitoAnnotations.initMocks(this) testableLooper = TestableLooper.get(this) handler = Handler(testableLooper.looper) fakeExecutor = FakeExecutor(FakeSystemClock()) userBroadcastDispatcher = object : UserBroadcastDispatcher( mockContext, USER_ID, testableLooper.looper, mock(Executor::class.java), logger, removalPendingStore ) { override fun createActionReceiver( action: String, permission: String?, flags: Int ): ActionReceiver { return mock(ActionReceiver::class.java) } } } @Test fun testSingleReceiverRegistered() { intentFilter = IntentFilter(ACTION_1) val receiverData = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE) userBroadcastDispatcher.registerReceiver(receiverData, FLAG) testableLooper.processAllMessages() val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1, FLAG) assertNotNull(actionReceiver) verify(actionReceiver)?.addReceiverData(receiverData) } @Test fun testDifferentActionReceiversForDifferentFlags() { intentFilter = IntentFilter(ACTION_1) val receiverData = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE) val flag1 = 0 val flag2 = 1 userBroadcastDispatcher.registerReceiver(receiverData, flag1) userBroadcastDispatcher.registerReceiver(receiverData, flag2) testableLooper.processAllMessages() assertNotSame( userBroadcastDispatcher.getActionReceiver(ACTION_1, flag1), userBroadcastDispatcher.getActionReceiver(ACTION_1, flag2) ) } @Test fun testDifferentActionReceiversForDifferentPermissions() { intentFilter = IntentFilter(ACTION_1) val receiverData1 = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE, "PERMISSION1") val receiverData2 = ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE, "PERMISSION2") userBroadcastDispatcher.registerReceiver(receiverData1, 0) userBroadcastDispatcher.registerReceiver(receiverData2, 0) testableLooper.processAllMessages() assertNotSame( userBroadcastDispatcher.getActionReceiver(ACTION_1, 0, "PERMISSION1"), userBroadcastDispatcher.getActionReceiver(ACTION_1, 0, "PERMISSION2") ) } @Test fun testSingleReceiverRegistered_logging() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG) testableLooper.processAllMessages() verify(logger).logReceiverRegistered(USER_HANDLE.identifier, broadcastReceiver, FLAG) } @Test fun testSingleReceiverUnregistered() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG) testableLooper.processAllMessages() userBroadcastDispatcher.unregisterReceiver(broadcastReceiver) testableLooper.processAllMessages() val actionReceiver = userBroadcastDispatcher.getActionReceiver(ACTION_1, FLAG) assertNotNull(actionReceiver) verify(actionReceiver)?.removeReceiver(broadcastReceiver) } @Test fun testSingleReceiverUnregistered_logger() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG) testableLooper.processAllMessages() userBroadcastDispatcher.unregisterReceiver(broadcastReceiver) testableLooper.processAllMessages() verify(logger).logReceiverUnregistered(USER_HANDLE.identifier, broadcastReceiver) } @Test fun testRemoveReceiverReferences() { intentFilter = IntentFilter(ACTION_1) userBroadcastDispatcher.registerReceiver( ReceiverData(broadcastReceiver, intentFilter, fakeExecutor, USER_HANDLE), FLAG) intentFilterOther = IntentFilter(ACTION_1) intentFilterOther.addAction(ACTION_2) userBroadcastDispatcher.registerReceiver( ReceiverData( broadcastReceiverOther, intentFilterOther, fakeExecutor, USER_HANDLE ), FLAG ) userBroadcastDispatcher.unregisterReceiver(broadcastReceiver) testableLooper.processAllMessages() fakeExecutor.runAllReady() assertFalse(userBroadcastDispatcher.isReceiverReferenceHeld(broadcastReceiver)) } @Test fun testCreateActionReceiver_registerWithFlag() { val uBR = UserBroadcastDispatcher( mockContext, USER_ID, testableLooper.looper, fakeExecutor, logger, removalPendingStore ) uBR.registerReceiver( ReceiverData( broadcastReceiver, IntentFilter(ACTION_1), fakeExecutor, USER_HANDLE ), FLAG ) testableLooper.processAllMessages() fakeExecutor.runAllReady() verify(mockContext).registerReceiverAsUser( any(), any(), any(), nullable(String::class.java), any(), eq(FLAG)) } @Test fun testCreateActionReceiver_registerWithPermission() { val permission = "CUSTOM_PERMISSION" val uBR = UserBroadcastDispatcher( mockContext, USER_ID, testableLooper.looper, fakeExecutor, logger, removalPendingStore ) uBR.registerReceiver( ReceiverData( broadcastReceiver, IntentFilter(ACTION_1), fakeExecutor, USER_HANDLE, permission ), FLAG ) testableLooper.processAllMessages() fakeExecutor.runAllReady() verify(mockContext).registerReceiverAsUser( any(), any(), any(), eq(permission), any(), eq(FLAG)) } private fun UserBroadcastDispatcher.getActionReceiver( action: String, flags: Int, permission: String? = null ): ActionReceiver? { return actionsToActionsReceivers.get( UserBroadcastDispatcher.ReceiverProperties( action, flags, permission ) ) } }