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) },