package com.android.systemui.qs import android.content.res.Configuration import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableResources import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager import com.android.systemui.media.controls.ui.MediaHost import com.android.systemui.media.controls.ui.MediaHostState import com.android.systemui.plugins.FalsingManager import com.android.systemui.plugins.qs.QSTile import com.android.systemui.qs.customize.QSCustomizerController import com.android.systemui.qs.logging.QSLogger import com.android.systemui.settings.brightness.BrightnessController import com.android.systemui.settings.brightness.BrightnessSliderController import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.tuner.TunerService import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.any import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) class QSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var qsPanel: QSPanel @Mock private lateinit var tunerService: TunerService @Mock private lateinit var qsHost: QSHost @Mock private lateinit var qsCustomizerController: QSCustomizerController @Mock private lateinit var qsTileRevealControllerFactory: QSTileRevealController.Factory @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var metricsLogger: MetricsLogger @Mock private lateinit var uiEventLogger: UiEventLogger @Mock private lateinit var qsLogger: QSLogger @Mock private lateinit var brightnessControllerFactory: BrightnessController.Factory @Mock private lateinit var brightnessController: BrightnessController @Mock private lateinit var brightnessSlider: BrightnessSliderController @Mock private lateinit var brightnessSliderFactory: BrightnessSliderController.Factory @Mock private lateinit var falsingManager: FalsingManager @Mock private lateinit var mediaHost: MediaHost @Mock private lateinit var tile: QSTile @Mock private lateinit var otherTile: QSTile @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager @Mock private lateinit var configuration: Configuration @Mock private lateinit var pagedTileLayout: PagedTileLayout private lateinit var controller: QSPanelController private val testableResources: TestableResources = mContext.orCreateTestableResources @Before fun setUp() { MockitoAnnotations.initMocks(this) whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider) whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController) setShouldUseSplitShade(false) whenever(qsPanel.resources).thenReturn(testableResources.resources) whenever(qsPanel.getOrCreateTileLayout()).thenReturn(pagedTileLayout) whenever(statusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false) whenever(qsPanel.setListening(anyBoolean())).then { whenever(qsPanel.isListening).thenReturn(it.getArgument(0)) } controller = QSPanelController( qsPanel, tunerService, qsHost, qsCustomizerController, /* usingMediaPlayer= */ true, mediaHost, qsTileRevealControllerFactory, dumpManager, metricsLogger, uiEventLogger, qsLogger, brightnessControllerFactory, brightnessSliderFactory, falsingManager, statusBarKeyguardViewManager ) } @After fun tearDown() { reset(mediaHost) } @Test fun onInit_setsMediaAsExpanded() { controller.onInit() verify(mediaHost).expansion = MediaHostState.EXPANDED } @Test fun testSetListeningDoesntRefreshListeningTiles() { whenever(qsHost.getTiles()).thenReturn(listOf(tile, otherTile)) controller.setTiles() whenever(tile.isListening()).thenReturn(false) whenever(otherTile.isListening()).thenReturn(true) controller.setListening(true, true) verify(tile).refreshState() verify(otherTile, Mockito.never()).refreshState() } @Test fun testIsBouncerInTransit() { whenever(statusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true) assertThat(controller.isBouncerInTransit()).isEqualTo(true) whenever(statusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false) assertThat(controller.isBouncerInTransit()).isEqualTo(false) } @Test fun configurationChange_onlySplitShadeConfigChanges_tileAreRedistributed() { setShouldUseSplitShade(false) controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) verify(pagedTileLayout, never()).forceTilesRedistribution(any()) setShouldUseSplitShade(true) controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) verify(pagedTileLayout).forceTilesRedistribution("Split shade state changed") } @Test fun configurationChange_onlySplitShadeConfigChanges_qsPanelCanBeCollapsed() { setShouldUseSplitShade(false) controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) verify(qsPanel, never()).setCanCollapse(anyBoolean()) setShouldUseSplitShade(true) controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) verify(qsPanel).setCanCollapse(false) setShouldUseSplitShade(false) controller.mOnConfigurationChangedListener.onConfigurationChange(configuration) verify(qsPanel).setCanCollapse(true) } @Test fun multipleListeningOnlyCallsBrightnessControllerOnce() { controller.setListening(true, true) controller.setListening(true, false) controller.setListening(true, true) verify(brightnessController).registerCallbacks() controller.setListening(false, true) controller.setListening(false, false) controller.setListening(false, true) verify(brightnessController).unregisterCallbacks() } private fun setShouldUseSplitShade(shouldUse: Boolean) { testableResources.addOverride(R.bool.config_use_split_notification_shade, shouldUse) } }