From ae80cbfed3cda55cd932c6867bae098214afacaa Mon Sep 17 00:00:00 2001 From: Brian Isganitis Date: Mon, 12 May 2025 15:44:50 -0400 Subject: [PATCH] Refactor test dagger graph to stub PerDisplayRepository instances. These are not being used yet in Taskbar, but they are hardcoding DEFAULT_DISPLAY for the primary ID. In tests, we want the primary to be considered the ID of the virtual display tests are running on. This change also moves dagger classes to its own file for organization. Flag: TEST_ONLY Bug: 415326979 Test: Taskbar multivalent tests Change-Id: Ibd0cdf46bc53dbd7a3dd5f34d7171d9a6cdebb38 --- .../KeyboardQuickSwitchControllerTest.kt | 43 ++--- .../launcher3/taskbar/TaskbarOverflowTest.kt | 15 +- .../taskbar/rules/TaskbarSandboxComponent.kt | 157 ++++++++++++++++++ .../rules/TaskbarWindowSandboxContext.kt | 76 --------- 4 files changed, 175 insertions(+), 116 deletions(-) create mode 100644 quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarSandboxComponent.kt diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/KeyboardQuickSwitchControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/KeyboardQuickSwitchControllerTest.kt index 1bfa527bc5..9185f7e28e 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/KeyboardQuickSwitchControllerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/KeyboardQuickSwitchControllerTest.kt @@ -31,7 +31,7 @@ import com.android.launcher3.Flags.FLAG_ENABLE_ALT_TAB_KQS_ON_CONNECTED_DISPLAYS import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.statehandlers.DesktopVisibilityController import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync -import com.android.launcher3.taskbar.rules.DisplayControllerModule +import com.android.launcher3.taskbar.rules.AllTaskbarSandboxModules import com.android.launcher3.taskbar.rules.MockedRecentsModelHelper import com.android.launcher3.taskbar.rules.MockedRecentsModelTestRule import com.android.launcher3.taskbar.rules.SandboxParams @@ -39,8 +39,6 @@ import com.android.launcher3.taskbar.rules.TaskbarSandboxComponent import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext -import com.android.launcher3.util.AllModulesForTest -import com.android.launcher3.util.FakePrefsModule import com.android.launcher3.util.LauncherMultivalentJUnit import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices import com.android.launcher3.util.TestUtil.getOnUiThread @@ -60,16 +58,15 @@ import com.android.wm.shell.shared.split.SplitScreenConstants import com.google.common.truth.Truth.assertThat import dagger.BindsInstance import dagger.Component -import org.junit.Ignore; +import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentCaptor -import org.mockito.ArgumentMatchers.anyInt +import org.mockito.kotlin.any import org.mockito.kotlin.anyOrNull +import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.doAnswer import org.mockito.kotlin.eq -import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @@ -81,9 +78,8 @@ class KeyboardQuickSwitchControllerTest { private var systemUiProxySpy: SystemUiProxy? = null private var desktopTaskListener: IDesktopTaskListener? = null private val mockRecentsModelHelper: MockedRecentsModelHelper = MockedRecentsModelHelper() - private val desktopVisibilityController: DesktopVisibilityController = mock() - private val taskIdCaptor = ArgumentCaptor.forClass(Int::class.java) - private val transitionCaptor = ArgumentCaptor.forClass(RemoteTransition::class.java) + private val taskIdCaptor = argumentCaptor() + private val transitionCaptor = argumentCaptor() @get:Rule(order = 0) val setFlagsRule = SetFlagsRule() @get:Rule(order = 1) @@ -100,8 +96,7 @@ class KeyboardQuickSwitchControllerTest { }, builderBase = DaggerKeyboardQuickSwitchControllerComponent.builder() - .bindRecentsModel(mockRecentsModelHelper.mockRecentsModel) - .bindDesktopVisibilityController(desktopVisibilityController), + .bindRecentsModel(mockRecentsModelHelper.mockRecentsModel), ) ) @@ -279,15 +274,15 @@ class KeyboardQuickSwitchControllerTest { triggerAltTabAndLaunchFocusedTask() - val deskIdCaptor = ArgumentCaptor.forClass(Int::class.java) + val deskIdCaptor = argumentCaptor() verify(systemUiProxySpy)?.activateDesk(deskIdCaptor.capture(), transitionCaptor.capture()) - assertThat(deskIdCaptor.value).isEqualTo(deskId) - assertThat(transitionCaptor.value.remoteTransition) + assertThat(deskIdCaptor.firstValue).isEqualTo(deskId) + assertThat(transitionCaptor.firstValue.remoteTransition) .isInstanceOf(SlideInRemoteTransition::class.java) verify(systemUiProxySpy) ?.showDesktopApp(taskIdCaptor.capture(), eq(null), eq(DesktopTaskToFrontReason.ALT_TAB)) - assertThat(taskIdCaptor.value).isEqualTo(PREVIOUS_TASK_ID) + assertThat(taskIdCaptor.firstValue).isEqualTo(PREVIOUS_TASK_ID) } @Test @@ -304,8 +299,8 @@ class KeyboardQuickSwitchControllerTest { eq(DesktopModeTransitionSource.KEYBOARD_SHORTCUT), transitionCaptor.capture(), ) - assertThat(taskIdCaptor.value).isEqualTo(PREVIOUS_TASK_ID) - assertThat(transitionCaptor.value.remoteTransition) + assertThat(taskIdCaptor.firstValue).isEqualTo(PREVIOUS_TASK_ID) + assertThat(transitionCaptor.firstValue.remoteTransition) .isInstanceOf(SlideInRemoteTransition::class.java) } @@ -328,7 +323,8 @@ class KeyboardQuickSwitchControllerTest { DesktopTask(deskId, DEFAULT_DISPLAY, taskIds.map { createTask(it) }) private fun enableDesktopMode() { - whenever(desktopVisibilityController.isInDesktopMode(anyInt())).thenReturn(true) + whenever(DesktopVisibilityController.INSTANCE[context].isInDesktopMode(any())) + .thenReturn(true) } /* @@ -374,20 +370,13 @@ class KeyboardQuickSwitchControllerTest { /** KeyboardQuickSwitchControllerComponent used to bind the RecentsModel. */ @LauncherAppSingleton -@Component( - modules = [AllModulesForTest::class, FakePrefsModule::class, DisplayControllerModule::class] -) +@Component(modules = [AllTaskbarSandboxModules::class]) interface KeyboardQuickSwitchControllerComponent : TaskbarSandboxComponent { @Component.Builder interface Builder : TaskbarSandboxComponent.Builder { @BindsInstance fun bindRecentsModel(model: RecentsModel): Builder - @BindsInstance - fun bindDesktopVisibilityController( - desktopVisibilityController: DesktopVisibilityController - ): Builder - override fun build(): KeyboardQuickSwitchControllerComponent } } diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt index 35490abca5..c4b27eda22 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt @@ -41,8 +41,7 @@ import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync import com.android.launcher3.taskbar.TaskbarViewTestUtil.createHotseatItems import com.android.launcher3.taskbar.bubbles.BubbleBarViewController import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController -import com.android.launcher3.taskbar.rules.DesktopVisibilityControllerModule -import com.android.launcher3.taskbar.rules.DisplayControllerModule +import com.android.launcher3.taskbar.rules.AllTaskbarSandboxModules import com.android.launcher3.taskbar.rules.MockedRecentsModelHelper import com.android.launcher3.taskbar.rules.MockedRecentsModelTestRule import com.android.launcher3.taskbar.rules.SandboxParams @@ -54,8 +53,6 @@ import com.android.launcher3.taskbar.rules.TaskbarSandboxComponent import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext -import com.android.launcher3.util.AllModulesForTest -import com.android.launcher3.util.FakePrefsModule import com.android.launcher3.util.LauncherMultivalentJUnit import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices import com.android.launcher3.util.Preconditions.assertNotNull @@ -725,15 +722,7 @@ class TaskbarOverflowTest { /** TaskbarOverflowComponent used to bind the RecentsModel. */ @LauncherAppSingleton -@Component( - modules = - [ - AllModulesForTest::class, - FakePrefsModule::class, - DisplayControllerModule::class, - DesktopVisibilityControllerModule::class, - ] -) +@Component(modules = [AllTaskbarSandboxModules::class]) interface TaskbarOverflowComponent : TaskbarSandboxComponent { @Component.Builder diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarSandboxComponent.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarSandboxComponent.kt new file mode 100644 index 0000000000..b7d49e5695 --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarSandboxComponent.kt @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2025 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.launcher3.taskbar.rules + +import android.content.Context +import com.android.app.displaylib.PerDisplayRepository +import com.android.launcher3.LauncherPrefs +import com.android.launcher3.concurrent.ExecutorsModule +import com.android.launcher3.dagger.ApiWrapperModule +import com.android.launcher3.dagger.AppModule +import com.android.launcher3.dagger.ApplicationContext +import com.android.launcher3.dagger.BasePerDisplayModule +import com.android.launcher3.dagger.DisplayContext +import com.android.launcher3.dagger.LauncherAppComponent +import com.android.launcher3.dagger.LauncherAppSingleton +import com.android.launcher3.dagger.LauncherConcurrencyModule +import com.android.launcher3.dagger.StaticObjectModule +import com.android.launcher3.dagger.WidgetModule +import com.android.launcher3.dagger.WindowContext +import com.android.launcher3.statehandlers.DesktopVisibilityController +import com.android.launcher3.util.DaggerSingletonTracker +import com.android.launcher3.util.DisplayController +import com.android.launcher3.util.FakePrefsModule +import com.android.launcher3.util.SettingsCache +import com.android.launcher3.util.dagger.LauncherExecutorsModule +import com.android.launcher3.util.window.WindowManagerProxy +import com.android.quickstep.FallbackWindowInterface +import com.android.quickstep.RecentsAnimationDeviceState +import com.android.quickstep.RotationTouchHelper +import com.android.quickstep.SystemUiProxy +import com.android.quickstep.TaskAnimationManager +import com.android.quickstep.fallback.window.RecentsWindowManager +import dagger.Binds +import dagger.BindsInstance +import dagger.Component +import dagger.Module +import dagger.Provides +import javax.inject.Inject +import org.mockito.kotlin.mock +import org.mockito.kotlin.spy + +@LauncherAppSingleton +@Component(modules = [AllTaskbarSandboxModules::class]) +interface TaskbarSandboxComponent : LauncherAppComponent { + + @Component.Builder + interface Builder : LauncherAppComponent.Builder { + @BindsInstance fun bindSystemUiProxy(proxy: SystemUiProxy): Builder + + @BindsInstance fun bindSettingsCache(settingsCache: SettingsCache): Builder + + override fun build(): TaskbarSandboxComponent + } +} + +@Module( + includes = + [ + ApiWrapperModule::class, + StaticObjectModule::class, + WidgetModule::class, + AppModule::class, + BasePerDisplayModule::class, + LauncherConcurrencyModule::class, + ExecutorsModule::class, + LauncherExecutorsModule::class, + FakePrefsModule::class, + DisplayControllerModule::class, + TaskbarSandboxWmProxyModule::class, + TaskbarPerDisplayReposModule::class, + DesktopVisibilityControllerModule::class, + ] +) +interface AllTaskbarSandboxModules + +@Module +abstract class DisplayControllerModule { + @Binds abstract fun bindDisplayController(controller: DisplayControllerSpy): DisplayController +} + +/** A wrapper over display controller which allows modifying the underlying info */ +@LauncherAppSingleton +class DisplayControllerSpy +@Inject +constructor( + @ApplicationContext context: Context, + wmProxy: WindowManagerProxy, + prefs: LauncherPrefs, + lifecycle: DaggerSingletonTracker, +) : DisplayController(context, wmProxy, prefs, lifecycle) { + + var infoModifier: ((Info) -> Info)? = null + + override fun getInfo(): Info = infoModifier?.invoke(super.getInfo()) ?: super.getInfo() +} + +@Module +object DesktopVisibilityControllerModule { + @JvmStatic + @Provides + @LauncherAppSingleton + fun provideDesktopVisibilityController( + @ApplicationContext context: Context, + systemUiProxy: SystemUiProxy, + lifecycleTracker: DaggerSingletonTracker, + ): DesktopVisibilityController { + return spy(DesktopVisibilityController(context, systemUiProxy, lifecycleTracker)) + } +} + +@Module +object TaskbarPerDisplayReposModule { + @Provides + @LauncherAppSingleton + fun provideRecentsAnimationDeviceStateRepo(): + PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + fun provideTaskAnimationManagerRepo(): PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + fun provideRotationTouchHandlerRepo(): PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + fun provideFallbackWindowInterfaceRepo(): PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + fun provideRecentsWindowManagerRepo(): PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + @DisplayContext + fun provideDisplayContext(): PerDisplayRepository = mock() + + @Provides + @LauncherAppSingleton + @WindowContext + fun provideWindowContext(): PerDisplayRepository = mock() +} diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarWindowSandboxContext.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarWindowSandboxContext.kt index 579ae6c9e3..115bcbc183 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarWindowSandboxContext.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarWindowSandboxContext.kt @@ -22,32 +22,14 @@ import android.hardware.display.DisplayManager import android.hardware.display.VirtualDisplay import android.view.Display.DEFAULT_DISPLAY import androidx.test.core.app.ApplicationProvider -import com.android.launcher3.LauncherPrefs -import com.android.launcher3.dagger.ApplicationContext -import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppSingleton -import com.android.launcher3.statehandlers.DesktopVisibilityController -import com.android.launcher3.util.AllModulesMinusWMProxy -import com.android.launcher3.util.DaggerSingletonTracker -import com.android.launcher3.util.DisplayController -import com.android.launcher3.util.FakePrefsModule import com.android.launcher3.util.SandboxApplication -import com.android.launcher3.util.SettingsCache import com.android.launcher3.util.SettingsCacheSandbox -import com.android.launcher3.util.window.WindowManagerProxy import com.android.quickstep.SystemUiProxy -import dagger.Binds -import dagger.BindsInstance -import dagger.Component -import dagger.Module -import dagger.Provides -import javax.inject.Inject import org.junit.rules.ExternalResource import org.junit.rules.RuleChain import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement -import org.mockito.kotlin.spy /** * [SandboxApplication] for running Taskbar tests. @@ -117,64 +99,6 @@ private constructor( } } -/** A wrapper over display controller which allows modifying the underlying info */ -@LauncherAppSingleton -class DisplayControllerSpy -@Inject -constructor( - @ApplicationContext context: Context, - wmProxy: WindowManagerProxy, - prefs: LauncherPrefs, - lifecycle: DaggerSingletonTracker, -) : DisplayController(context, wmProxy, prefs, lifecycle) { - - var infoModifier: ((Info) -> Info)? = null - - override fun getInfo(): Info = infoModifier?.invoke(super.getInfo()) ?: super.getInfo() -} - -@Module -abstract class DisplayControllerModule { - @Binds abstract fun bindDisplayController(controller: DisplayControllerSpy): DisplayController -} - -@Module -object DesktopVisibilityControllerModule { - @JvmStatic - @Provides - @LauncherAppSingleton - fun provideDesktopVisibilityController( - @ApplicationContext context: Context, - systemUiProxy: SystemUiProxy, - lifecycleTracker: DaggerSingletonTracker, - ): DesktopVisibilityController { - return spy(DesktopVisibilityController(context, systemUiProxy, lifecycleTracker)) - } -} - -@LauncherAppSingleton -@Component( - modules = - [ - AllModulesMinusWMProxy::class, - FakePrefsModule::class, - DisplayControllerModule::class, - TaskbarSandboxModule::class, - DesktopVisibilityControllerModule::class, - ] -) -interface TaskbarSandboxComponent : LauncherAppComponent { - - @Component.Builder - interface Builder : LauncherAppComponent.Builder { - @BindsInstance fun bindSystemUiProxy(proxy: SystemUiProxy): Builder - - @BindsInstance fun bindSettingsCache(settingsCache: SettingsCache): Builder - - override fun build(): TaskbarSandboxComponent - } -} - /** Include additional bindings when building a [TaskbarSandboxComponent]. */ data class SandboxParams( val systemUiProxyProvider: (Context) -> SystemUiProxy = { SystemUiProxy(it) },