diff options
27 files changed, 271 insertions, 280 deletions
diff --git a/quickstep/src/com/android/launcher3/dagger/Modules.kt b/quickstep/src/com/android/launcher3/dagger/Modules.kt new file mode 100644 index 0000000000..04c1d5e461 --- /dev/null +++ b/quickstep/src/com/android/launcher3/dagger/Modules.kt @@ -0,0 +1,44 @@ +/* + * 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.dagger + +import com.android.launcher3.uioverrides.SystemApiWrapper +import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl +import com.android.launcher3.util.ApiWrapper +import com.android.launcher3.util.PluginManagerWrapper +import com.android.launcher3.util.window.WindowManagerProxy +import com.android.quickstep.util.SystemWindowManagerProxy +import dagger.Binds +import dagger.Module + +private object Modules {} + +@Module +abstract class WindowManagerProxyModule { + @Binds abstract fun bindWindowManagerProxy(proxy: SystemWindowManagerProxy): WindowManagerProxy +} + +@Module +abstract class ApiWrapperModule { + @Binds abstract fun bindApiWrapper(systemApiWrapper: SystemApiWrapper): ApiWrapper +} + +@Module +abstract class PluginManagerWrapperModule { + @Binds + abstract fun bindPluginManagerWrapper(impl: PluginManagerWrapperImpl): PluginManagerWrapper +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 3fa0e8e426..7c6c7ac121 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -61,7 +61,6 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks; import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider; @@ -270,7 +269,6 @@ public class TaskbarManager { context, navCallbacks, SystemUiProxy.INSTANCE.get(mWindowContext), - ContextualEduStatsManager.INSTANCE.get(mWindowContext), new Handler(), new ContextualSearchInvoker(mWindowContext)); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java index d1f9be0b91..1adb2e909e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java @@ -51,7 +51,6 @@ import androidx.annotation.Nullable; import androidx.annotation.StringRes; import com.android.launcher3.R; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; @@ -120,7 +119,6 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa private final Context mContext; private final TaskbarNavButtonCallbacks mCallbacks; private final SystemUiProxy mSystemUiProxy; - private final ContextualEduStatsManager mContextualEduStatsManager; private final Handler mHandler; private final ContextualSearchInvoker mContextualSearchInvoker; @Nullable private StatsLogManager mStatsLogManager; @@ -131,13 +129,11 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa Context context, TaskbarNavButtonCallbacks callbacks, SystemUiProxy systemUiProxy, - ContextualEduStatsManager contextualEduStatsManager, Handler handler, ContextualSearchInvoker contextualSearchInvoker) { mContext = context; mCallbacks = callbacks; mSystemUiProxy = systemUiProxy; - mContextualEduStatsManager = contextualEduStatsManager; mHandler = handler; mContextualSearchInvoker = contextualSearchInvoker; } @@ -159,13 +155,13 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa break; case BUTTON_HOME: logEvent(LAUNCHER_TASKBAR_HOME_BUTTON_TAP); - mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false, + mSystemUiProxy.updateContextualEduStats(/* isTrackpadGesture= */ false, GestureType.HOME); navigateHome(); break; case BUTTON_RECENTS: logEvent(LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP); - mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false, + mSystemUiProxy.updateContextualEduStats(/* isTrackpadGesture= */ false, GestureType.OVERVIEW); navigateToOverview(); break; @@ -364,7 +360,7 @@ public class TaskbarNavButtonController implements TaskbarControllers.LoggableTa private void executeBack(@Nullable KeyEvent keyEvent) { if (keyEvent == null || (keyEvent.getAction() == ACTION_UP && !keyEvent.isCanceled())) { logEvent(LAUNCHER_TASKBAR_BACK_BUTTON_TAP); - mContextualEduStatsManager.updateEduStats(/* isTrackpadGesture= */ false, + mSystemUiProxy.updateContextualEduStats(/* isTrackpadGesture= */ false, GestureType.BACK); } mSystemUiProxy.onBackEvent(keyEvent); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index 1d9e49201d..3f0839da92 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -45,11 +45,11 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.touch.SingleAxisSwipeDetector; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.TouchController; +import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskUtils; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.OverviewToHomeAnim; @@ -221,7 +221,7 @@ public class NavBarToHomeTouchController implements TouchController, } if (mStartState != mEndState) { logHomeGesture(); - ContextualEduStatsManager.INSTANCE.get(mLauncher).updateEduStats( + SystemUiProxy.INSTANCE.get(mLauncher).updateContextualEduStats( mSwipeDetector.isTrackpadGesture(), GestureType.HOME); } AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(mLauncher); diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index b562838091..a74b350a64 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -37,6 +37,7 @@ import com.android.launcher3.uioverrides.states.OverviewState; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.views.RecentsView; +import com.android.systemui.contextualeducation.GestureType; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; /** @@ -163,8 +164,19 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr @Override protected void onSwipeInteractionCompleted(LauncherState targetState) { super.onSwipeInteractionCompleted(targetState); + SystemUiProxy sysUIProxy = SystemUiProxy.INSTANCE.get(mLauncher); if (mStartState == NORMAL && targetState == OVERVIEW) { - SystemUiProxy.INSTANCE.get(mLauncher).onOverviewShown(true, TAG); + sysUIProxy.onOverviewShown(true, TAG); + } + + if (targetState == OVERVIEW) { + sysUIProxy.updateContextualEduStats( + mDetector.isTrackpadGesture(), GestureType.OVERVIEW); + } else if (targetState == ALL_APPS && !mDetector.isTrackpadGesture()) { + // Only update if it is touch gesture as trackpad gesture is not relevant for all apps + // which only provides keyboard education. + sysUIProxy.updateContextualEduStats( + /* isTrackpadGesture= */ false, GestureType.ALL_APPS); } } diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index e27b6079df..0042c8ac72 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -118,7 +118,6 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.compat.AccessibilityManagerCompat; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; @@ -174,6 +173,8 @@ import com.android.wm.shell.shared.startingsurface.SplashScreenExitAnimationUtil import com.google.android.msdl.data.model.MSDLToken; +import kotlin.Unit; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -183,8 +184,6 @@ import java.util.Optional; import java.util.OptionalInt; import java.util.function.Consumer; -import kotlin.Unit; - /** * Handles the navigation gestures when Launcher is the default home activity. */ @@ -1413,7 +1412,7 @@ public abstract class AbsSwipeUpHandler< duration = mContainer != null && mContainer.getDeviceProfile().isTaskbarPresent ? QuickstepTransitionManager.getTaskbarToHomeDuration(isPinnedTaskbar) : StaggeredWorkspaceAnim.DURATION_MS; - ContextualEduStatsManager.INSTANCE.get(mContext).updateEduStats( + SystemUiProxy.INSTANCE.get(mContext).updateContextualEduStats( mGestureState.isTrackpadGesture(), GestureType.HOME); } else if (endTarget == RECENTS) { if (mRecentsView != null) { @@ -1439,7 +1438,7 @@ public abstract class AbsSwipeUpHandler< if (!mGestureState.isHandlingAtomicEvent() || isScrolling) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } - ContextualEduStatsManager.INSTANCE.get(mContext).updateEduStats( + SystemUiProxy.INSTANCE.get(mContext).updateContextualEduStats( mGestureState.isTrackpadGesture(), GestureType.OVERVIEW); } } else if (endTarget == LAST_TASK && mRecentsView != null diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.kt b/quickstep/src/com/android/quickstep/SystemUiProxy.kt index a7405a0bae..f2cedbaa71 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt @@ -63,6 +63,7 @@ import com.android.launcher3.util.SplitConfigurationOptions.StagePosition import com.android.quickstep.util.ActiveGestureProtoLogProxy import com.android.quickstep.util.ContextualSearchInvoker import com.android.quickstep.util.unfold.ProxyUnfoldTransitionProvider +import com.android.systemui.contextualeducation.GestureType import com.android.systemui.shared.recents.ISystemUiProxy import com.android.systemui.shared.recents.model.ThumbnailData.Companion.wrap import com.android.systemui.shared.system.QuickStepContract @@ -216,9 +217,9 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context: systemUiProxy?.onImeSwitcherLongPress() } - fun updateContextualEduStats(isTrackpadGesture: Boolean, gestureType: String) = + fun updateContextualEduStats(isTrackpadGesture: Boolean, gestureType: GestureType) = executeWithErrorLog({ "Failed call updateContextualEduStats" }) { - systemUiProxy?.updateContextualEduStats(isTrackpadGesture, gestureType) + systemUiProxy?.updateContextualEduStats(isTrackpadGesture, gestureType.name) } fun setHomeRotationEnabled(enabled: Boolean) = diff --git a/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java b/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java deleted file mode 100644 index 6a725370ba..0000000000 --- a/quickstep/src/com/android/quickstep/contextualeducation/SystemContextualEduStatsManager.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2024 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.quickstep.contextualeducation; - -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; -import com.android.launcher3.dagger.LauncherAppSingleton; -import com.android.quickstep.SystemUiProxy; -import com.android.systemui.contextualeducation.GestureType; - -import javax.inject.Inject; - -/** - * A class to update contextual education data via {@link SystemUiProxy} - */ -@LauncherAppSingleton -public class SystemContextualEduStatsManager extends ContextualEduStatsManager { - private final SystemUiProxy mSystemUiProxy; - - @Inject - public SystemContextualEduStatsManager(SystemUiProxy systemUiProxy) { - mSystemUiProxy = systemUiProxy; - } - - @Override - public void updateEduStats(boolean isTrackpadGesture, GestureType gestureType) { - mSystemUiProxy.updateContextualEduStats(isTrackpadGesture, - gestureType.name()); - } -} diff --git a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java b/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java deleted file mode 100644 index a6feff0652..0000000000 --- a/quickstep/src/com/android/quickstep/dagger/QuickStepModule.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2024 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.quickstep.dagger; - -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; -import com.android.launcher3.uioverrides.SystemApiWrapper; -import com.android.launcher3.uioverrides.plugins.PluginManagerWrapperImpl; -import com.android.launcher3.util.ApiWrapper; -import com.android.launcher3.util.PluginManagerWrapper; -import com.android.launcher3.util.window.WindowManagerProxy; -import com.android.quickstep.contextualeducation.SystemContextualEduStatsManager; -import com.android.quickstep.util.SystemWindowManagerProxy; - -import dagger.Binds; -import dagger.Module; - -@Module -public abstract class QuickStepModule { - - @Binds abstract PluginManagerWrapper bindPluginManagerWrapper(PluginManagerWrapperImpl impl); - @Binds abstract ApiWrapper bindApiWrapper(SystemApiWrapper systemApiWrapper); - @Binds abstract ContextualEduStatsManager bindContextualEduStatsManager( - SystemContextualEduStatsManager manager); - @Binds abstract WindowManagerProxy bindWindowManagerProxy(SystemWindowManagerProxy proxy); -} diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java index c68299035d..a8f3500a72 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java @@ -40,7 +40,6 @@ import android.view.inputmethod.Flags; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarNavButtonCallbacks; import com.android.quickstep.SystemUiProxy; @@ -65,9 +64,6 @@ public class TaskbarNavButtonControllerTest { SystemUiProxy mockSystemUiProxy; @Mock - ContextualEduStatsManager mockContextualEduStatsManager; - - @Mock TouchInteractionService mockService; @Mock Handler mockHandler; @@ -118,7 +114,6 @@ public class TaskbarNavButtonControllerTest { mockService, mCallbacks, mockSystemUiProxy, - mockContextualEduStatsManager, mockHandler, mockContextualSearchInvoker); } @@ -132,8 +127,8 @@ public class TaskbarNavButtonControllerTest { @Test public void testPressBack_updateContextualEduData() { mNavButtonController.onButtonClick(BUTTON_BACK, mockView); - verify(mockContextualEduStatsManager, times(1)) - .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.BACK)); + verify(mockSystemUiProxy, times(1)) + .updateContextualEduStats(/* isTrackpad= */ eq(false), eq(GestureType.BACK)); } @Test @@ -223,8 +218,8 @@ public class TaskbarNavButtonControllerTest { @Test public void testPressHome_updateContextualEduData() { mNavButtonController.onButtonClick(BUTTON_HOME, mockView); - verify(mockContextualEduStatsManager, times(1)) - .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.HOME)); + verify(mockSystemUiProxy, times(1)) + .updateContextualEduStats(/* isTrackpad= */ eq(false), eq(GestureType.HOME)); } @Test @@ -236,8 +231,8 @@ public class TaskbarNavButtonControllerTest { @Test public void testPressRecents_updateContextualEduData() { mNavButtonController.onButtonClick(BUTTON_RECENTS, mockView); - verify(mockContextualEduStatsManager, times(1)) - .updateEduStats(/* isTrackpad= */ eq(false), eq(GestureType.OVERVIEW)); + verify(mockSystemUiProxy, times(1)) + .updateContextualEduStats(/* isTrackpad= */ eq(false), eq(GestureType.OVERVIEW)); } @Test diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarModeRule.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarModeRule.kt index 74b154a53d..3cf912c8e3 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarModeRule.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/TaskbarModeRule.kt @@ -61,11 +61,10 @@ class TaskbarModeRule(private val context: TaskbarWindowSandboxContext) : TestRu val mode = taskbarMode.mode getInstrumentation().runOnMainSync { - context.putObject( - DisplayController.INSTANCE, - object : DisplayController(context) { - override fun getInfo(): Info { - return spy(super.getInfo()) { + DisplayController.INSTANCE[context].let { + if (it is DisplayControllerSpy) { + it.infoModifier = { info -> + spy(info) { on { isTransientTaskbar } doReturn (mode == Mode.TRANSIENT) on { isPinnedTaskbar } doReturn (mode == Mode.PINNED) on { navigationMode } doReturn @@ -76,8 +75,8 @@ class TaskbarModeRule(private val context: TaskbarWindowSandboxContext) : TestRu } } } - }, - ) + } + } } base.evaluate() 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 31c5a4c950..e6dc2a209e 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,17 +22,25 @@ 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.FakeLauncherPrefs +import com.android.launcher3.LauncherPrefs +import com.android.launcher3.dagger.ApplicationContext import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppModule import com.android.launcher3.dagger.LauncherAppSingleton +import com.android.launcher3.util.AllModulesForTest +import com.android.launcher3.util.DaggerSingletonTracker +import com.android.launcher3.util.DisplayController +import com.android.launcher3.util.FakePrefsModule import com.android.launcher3.util.MainThreadInitializedObject.ObjectSandbox 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 javax.inject.Inject import org.junit.rules.ExternalResource import org.junit.rules.RuleChain import org.junit.rules.TestRule @@ -113,11 +121,32 @@ private constructor( } } +/** A wrapper over display controller which allows modifying the underlying info */ @LauncherAppSingleton -@Component(modules = [LauncherAppModule::class]) -interface TaskbarSandboxComponent : LauncherAppComponent { +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 +} - override fun getLauncherPrefs(): FakeLauncherPrefs +@LauncherAppSingleton +@Component( + modules = [AllModulesForTest::class, FakePrefsModule::class, DisplayControllerModule::class] +) +interface TaskbarSandboxComponent : LauncherAppComponent { @Component.Builder interface Builder : LauncherAppComponent.Builder { diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt index 073833665f..4541fdb3ed 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2Test.kt @@ -97,7 +97,7 @@ class LauncherSwipeHandlerV2Test { verify(systemUiProxy) .updateContextualEduStats( /* isTrackpadGesture= */ eq(true), - eq(GestureType.HOME.toString()), + eq(GestureType.HOME), ) } @@ -107,7 +107,7 @@ class LauncherSwipeHandlerV2Test { verify(systemUiProxy) .updateContextualEduStats( /* isTrackpadGesture= */ eq(false), - eq(GestureType.HOME.toString()), + eq(GestureType.HOME), ) } } diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java index dcb45e5ef0..c1be1cee9b 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java @@ -21,8 +21,8 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.dagger.LauncherAppComponent; import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.util.AllModulesForTest; import com.android.launcher3.util.LauncherMultivalentJUnit; -import com.android.quickstep.dagger.QuickStepModule; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsState; import com.android.quickstep.fallback.window.RecentsDisplayModel; @@ -30,13 +30,13 @@ import com.android.quickstep.fallback.window.RecentsWindowManager; import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler; import com.android.quickstep.views.RecentsViewContainer; +import dagger.BindsInstance; +import dagger.Component; + import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.Mock; -import dagger.BindsInstance; -import dagger.Component; - @SmallTest @RunWith(LauncherMultivalentJUnit.class) public class RecentsWindowSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase< @@ -83,7 +83,7 @@ public class RecentsWindowSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase } @LauncherAppSingleton - @Component(modules = { QuickStepModule.class }) + @Component(modules = {AllModulesForTest.class}) interface TestComponent extends LauncherAppComponent { @Component.Builder interface Builder extends LauncherAppComponent.Builder { diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java index 8879a0103d..7776351517 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java @@ -46,8 +46,8 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.android.launcher3.dagger.LauncherAppComponent; -import com.android.launcher3.dagger.LauncherAppModule; import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.util.AllModulesForTest; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext; import com.android.quickstep.DeviceConfigWrapper; @@ -461,12 +461,11 @@ public class NavHandleLongPressInputConsumerTest { } @LauncherAppSingleton - @Component(modules = LauncherAppModule.class) + @Component(modules = AllModulesForTest.class) public interface TopTaskTrackerComponent extends LauncherAppComponent { @Component.Builder interface Builder extends LauncherAppComponent.Builder { - @BindsInstance - Builder bindTopTaskTracker(TopTaskTracker topTaskTracker); + @BindsInstance Builder bindTopTaskTracker(TopTaskTracker topTaskTracker); @Override TopTaskTrackerComponent build(); diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java index fa81680cb8..be76f9e86d 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java @@ -35,6 +35,9 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.dagger.LauncherAppComponent; +import com.android.launcher3.dagger.LauncherAppSingleton; +import com.android.launcher3.util.AllModulesMinusWMProxy; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.LauncherModelHelper; @@ -46,6 +49,9 @@ import com.android.launcher3.util.window.WindowManagerProxy; import com.android.quickstep.FallbackActivityInterface; import com.android.quickstep.util.SurfaceTransaction.MockProperties; +import dagger.BindsInstance; +import dagger.Component; + import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; import org.junit.Assert; @@ -159,6 +165,11 @@ public class TaskViewSimulatorTest { void verifyNoTransforms() { LauncherModelHelper helper = new LauncherModelHelper(); try { + DisplayController mockController = mock(DisplayController.class); + + helper.sandboxContext.initDaggerComponent( + DaggerTaskViewSimulatorTest_TaskViewSimulatorTestComponent.builder() + .bindDisplayController(mockController)); int rotation = mDisplaySize.x > mDisplaySize.y ? Surface.ROTATION_90 : Surface.ROTATION_0; CachedDisplayInfo cdi = new CachedDisplayInfo(mDisplaySize, rotation); @@ -192,10 +203,7 @@ public class TaskViewSimulatorTest { DisplayController.Info info = new Info( configurationContext, wmProxy, perDisplayBoundsCache); - - DisplayController mockController = mock(DisplayController.class); when(mockController.getInfo()).thenReturn(info); - helper.sandboxContext.putObject(DisplayController.INSTANCE, mockController); mDeviceProfile = InvariantDeviceProfile.INSTANCE.get(helper.sandboxContext) .getBestMatch(mAppBounds.width(), mAppBounds.height(), rotation); @@ -271,4 +279,18 @@ public class TaskViewSimulatorTest { description.appendValue(mExpected); } } + + @LauncherAppSingleton + @Component(modules = {AllModulesMinusWMProxy.class}) + interface TaskViewSimulatorTestComponent extends LauncherAppComponent { + + @Component.Builder + interface Builder extends LauncherAppComponent.Builder { + + @BindsInstance + Builder bindDisplayController(DisplayController controller); + + TaskViewSimulatorTestComponent build(); + } + } } diff --git a/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java b/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java deleted file mode 100644 index 5664174014..0000000000 --- a/src/com/android/launcher3/contextualeducation/ContextualEduStatsManager.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2024 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.contextualeducation; - -import com.android.launcher3.dagger.LauncherAppSingleton; -import com.android.launcher3.dagger.LauncherBaseAppComponent; -import com.android.launcher3.util.DaggerSingletonObject; -import com.android.systemui.contextualeducation.GestureType; - -import javax.inject.Inject; - -/** - * A class to update contextual education data. It is a no-op implementation and could be - * overridden through dagger modules to provide a real implementation. - */ -@LauncherAppSingleton -public class ContextualEduStatsManager { - public static final DaggerSingletonObject<ContextualEduStatsManager> INSTANCE = - new DaggerSingletonObject<>(LauncherBaseAppComponent::getContextualEduStatsManager); - - @Inject - public ContextualEduStatsManager() { } - - - /** - * Updates contextual education stats when a gesture is triggered - * @param isTrackpadGesture indicates if the gesture is triggered by trackpad - * @param gestureType type of gesture triggered - */ - public void updateEduStats(boolean isTrackpadGesture, GestureType gestureType) { - } -} diff --git a/quickstep/dagger/com/android/launcher3/dagger/LauncherAppModule.java b/src/com/android/launcher3/dagger/LauncherAppModule.java index 1711fc13e5..ef136d07b9 100644 --- a/quickstep/dagger/com/android/launcher3/dagger/LauncherAppModule.java +++ b/src/com/android/launcher3/dagger/LauncherAppModule.java @@ -16,9 +16,12 @@ package com.android.launcher3.dagger; -import com.android.quickstep.dagger.QuickStepModule; - import dagger.Module; -@Module(includes = QuickStepModule.class) -public class LauncherAppModule {} +@Module(includes = { + WindowManagerProxyModule.class, + ApiWrapperModule.class, + PluginManagerWrapperModule.class +}) +public class LauncherAppModule { +} diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index 4b43d490e9..5883a88a51 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -19,13 +19,13 @@ package com.android.launcher3.dagger; import android.content.Context; import com.android.launcher3.LauncherPrefs; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.graphics.IconShape; import com.android.launcher3.graphics.ThemeManager; import com.android.launcher3.model.ItemInstallQueue; import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.util.ApiWrapper; import com.android.launcher3.util.DaggerSingletonTracker; +import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DynamicResource; import com.android.launcher3.util.MSDLPlayerWrapper; import com.android.launcher3.util.PackageManagerHelper; @@ -50,7 +50,6 @@ import dagger.BindsInstance; public interface LauncherBaseAppComponent { DaggerSingletonTracker getDaggerSingletonTracker(); ApiWrapper getApiWrapper(); - ContextualEduStatsManager getContextualEduStatsManager(); CustomWidgetManager getCustomWidgetManager(); DynamicResource getDynamicResource(); IconShape getIconShape(); @@ -66,6 +65,7 @@ public interface LauncherBaseAppComponent { WindowManagerProxy getWmProxy(); LauncherPrefs getLauncherPrefs(); ThemeManager getThemeManager(); + DisplayController getDisplayController(); /** Builder for LauncherBaseAppComponent. */ interface Builder { diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 74a09669a7..3817563b0b 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -40,13 +40,11 @@ import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.LauncherState; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.contextualeducation.ContextualEduStatsManager; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.util.FlingBlockCheck; import com.android.launcher3.util.TouchController; -import com.android.systemui.contextualeducation.GestureType; /** * TouchController for handling state changes @@ -390,7 +388,6 @@ public abstract class AbstractStateChangeTouchController } else { logReachedState(mToState); } - updateContextualEduStats(targetState); } protected void goToTargetState(LauncherState targetState) { @@ -406,18 +403,6 @@ public abstract class AbstractStateChangeTouchController .setDuration(0).start(); } - private void updateContextualEduStats(LauncherState targetState) { - if (targetState == OVERVIEW) { - ContextualEduStatsManager.INSTANCE.get( - mLauncher).updateEduStats(mDetector.isTrackpadGesture(), GestureType.OVERVIEW); - } else if (targetState == ALL_APPS && !mDetector.isTrackpadGesture()) { - // Only update if it is touch gesture as trackpad gesture is not relevant for all apps - // which only provides keyboard education. - ContextualEduStatsManager.INSTANCE.get( - mLauncher).updateEduStats(/* isTrackpadGesture= */ false, GestureType.ALL_APPS); - } - } - private void logReachedState(LauncherState targetState) { if (mStartState == targetState) { return; diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index d8a2a3d2ec..9472f5fa43 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -53,6 +53,9 @@ import com.android.launcher3.InvariantDeviceProfile.DeviceType; import com.android.launcher3.LauncherPrefChangeListener; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.Utilities; +import com.android.launcher3.dagger.ApplicationContext; +import com.android.launcher3.dagger.LauncherAppComponent; +import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.logging.FileLog; import com.android.launcher3.util.window.CachedDisplayInfo; import com.android.launcher3.util.window.WindowManagerProxy; @@ -67,11 +70,14 @@ import java.util.Objects; import java.util.Set; import java.util.StringJoiner; +import javax.inject.Inject; + /** * Utility class to cache properties of default display to avoid a system RPC on every call. */ @SuppressLint("NewApi") -public class DisplayController implements ComponentCallbacks, SafeCloseable, +@LauncherAppSingleton +public class DisplayController implements ComponentCallbacks, DesktopVisibilityListener { private static final String TAG = "DisplayController"; @@ -82,8 +88,8 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, // TODO(b/254119092) remove all logs with this tag public static final String TASKBAR_NOT_DESTROYED_TAG = "b/254119092"; - public static final MainThreadInitializedObject<DisplayController> INSTANCE = - new MainThreadInitializedObject<>(DisplayController::new); + public static final DaggerSingletonObject<DisplayController> INSTANCE = + new DaggerSingletonObject<>(LauncherAppComponent::getDisplayController); public static final int CHANGE_ACTIVE_SCREEN = 1 << 0; public static final int CHANGE_ROTATION = 1 << 1; @@ -101,6 +107,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, private static final String TARGET_OVERLAY_PACKAGE = "android"; private final Context mContext; + private final WindowManagerProxy mWMProxy; // Null for SDK < S private final Context mWindowContext; @@ -117,13 +124,31 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, private Info mInfo; private boolean mDestroyed = false; - private LauncherPrefChangeListener mTaskbarPinningPreferenceChangeListener; - - @VisibleForTesting - protected DisplayController(Context context) { + @Inject + protected DisplayController(@ApplicationContext Context context, + WindowManagerProxy wmProxy, + LauncherPrefs prefs, + DaggerSingletonTracker lifecycle) { mContext = context; + mWMProxy = wmProxy; + if (enableTaskbarPinning()) { - attachTaskbarPinningSharedPreferenceChangeListener(mContext); + LauncherPrefChangeListener prefListener = key -> { + boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key) + && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING); + boolean isTaskbarPinningDesktopModeChanged = + TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key) + && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get( + TASKBAR_PINNING_IN_DESKTOP_MODE); + if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) { + notifyConfigChange(); + } + }; + + prefs.addListener(prefListener, TASKBAR_PINNING); + prefs.addListener(prefListener, TASKBAR_PINNING_IN_DESKTOP_MODE); + lifecycle.addCloseable(() -> prefs.removeListener( + prefListener, TASKBAR_PINNING, TASKBAR_PINNING_IN_DESKTOP_MODE)); } Display display = context.getSystemService(DisplayManager.class) @@ -134,31 +159,17 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, // Initialize navigation mode change listener mReceiver.registerPkgActions(mContext, TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED); - WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context); mInfo = new Info(mWindowContext, wmProxy, wmProxy.estimateInternalDisplayBounds(mWindowContext)); wmProxy.registerDesktopVisibilityListener(this); FileLog.i(TAG, "(CTOR) perDisplayBounds: " + mInfo.mPerDisplayBounds); - } - private void attachTaskbarPinningSharedPreferenceChangeListener(Context context) { - mTaskbarPinningPreferenceChangeListener = key -> { - LauncherPrefs prefs = LauncherPrefs.get(mContext); - boolean isTaskbarPinningChanged = TASKBAR_PINNING_KEY.equals(key) - && mInfo.mIsTaskbarPinned != prefs.get(TASKBAR_PINNING); - boolean isTaskbarPinningDesktopModeChanged = - TASKBAR_PINNING_DESKTOP_MODE_KEY.equals(key) - && mInfo.mIsTaskbarPinnedInDesktopMode != prefs.get( - TASKBAR_PINNING_IN_DESKTOP_MODE); - if (isTaskbarPinningChanged || isTaskbarPinningDesktopModeChanged) { - notifyConfigChange(); - } - }; - - LauncherPrefs.get(context).addListener( - mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING); - LauncherPrefs.get(context).addListener( - mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING_IN_DESKTOP_MODE); + lifecycle.addCloseable(() -> { + mDestroyed = true; + mWindowContext.unregisterComponentCallbacks(this); + mReceiver.unregisterReceiverSafely(mContext); + wmProxy.unregisterDesktopVisibilityListener(this); + }); } /** @@ -208,20 +219,6 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, } @Override - public void close() { - mDestroyed = true; - if (enableTaskbarPinning()) { - LauncherPrefs.get(mContext).removeListener( - mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING); - LauncherPrefs.get(mContext).removeListener( - mTaskbarPinningPreferenceChangeListener, TASKBAR_PINNING_IN_DESKTOP_MODE); - } - mWindowContext.unregisterComponentCallbacks(this); - mReceiver.unregisterReceiverSafely(mContext); - WindowManagerProxy.INSTANCE.get(mContext).unregisterDesktopVisibilityListener(this); - } - - @Override public void onDesktopVisibilityChanged(boolean visible) { notifyConfigChange(); } @@ -259,7 +256,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, || !mInfo.mScreenSizeDp.equals( new PortraitSize(config.screenHeightDp, config.screenWidthDp)) || mWindowContext.getDisplay().getRotation() != mInfo.rotation - || WindowManagerProxy.INSTANCE.get(mContext).showLockedTaskbarOnHome(mWindowContext) + || mWMProxy.showLockedTaskbarOnHome(mWindowContext) != mInfo.showLockedTaskbarOnHome()) { notifyConfigChange(); } @@ -286,17 +283,16 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable, @AnyThread public void notifyConfigChange() { - WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(mContext); Info oldInfo = mInfo; Context displayInfoContext = mWindowContext; - Info newInfo = new Info(displayInfoContext, wmProxy, oldInfo.mPerDisplayBounds); + Info newInfo = new Info(displayInfoContext, mWMProxy, oldInfo.mPerDisplayBounds); if (newInfo.densityDpi != oldInfo.densityDpi || newInfo.fontScale != oldInfo.fontScale || newInfo.getNavigationMode() != oldInfo.getNavigationMode()) { // Cache may not be valid anymore, recreate without cache - newInfo = new Info(displayInfoContext, wmProxy, - wmProxy.estimateInternalDisplayBounds(displayInfoContext)); + newInfo = new Info(displayInfoContext, mWMProxy, + mWMProxy.estimateInternalDisplayBounds(displayInfoContext)); } int change = 0; diff --git a/src_no_quickstep/com/android/launcher3/dagger/LauncherAppModule.java b/src_no_quickstep/com/android/launcher3/dagger/Modules.kt index f7b8489f62..dab33a04ee 100644 --- a/src_no_quickstep/com/android/launcher3/dagger/LauncherAppModule.java +++ b/src_no_quickstep/com/android/launcher3/dagger/Modules.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 The Android Open Source Project + * 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. @@ -14,9 +14,14 @@ * limitations under the License. */ -package com.android.launcher3.dagger; +package com.android.launcher3.dagger -import dagger.Module; +import dagger.Module -@Module -public class LauncherAppModule { } +private object Modules {} + +@Module abstract class WindowManagerProxyModule {} + +@Module abstract class ApiWrapperModule {} + +@Module abstract class PluginManagerWrapperModule {} diff --git a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index 6676766632..9c64ec9704 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -29,9 +29,9 @@ import android.view.Surface import androidx.test.core.app.ApplicationProvider.getApplicationContext import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppModule import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.testing.shared.ResourceUtils +import com.android.launcher3.util.AllModulesMinusWMProxy import com.android.launcher3.util.DisplayController import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext import com.android.launcher3.util.NavigationMode @@ -69,7 +69,7 @@ abstract class AbstractDeviceProfileTest { protected lateinit var context: SandboxContext protected open val runningContext: Context = getApplicationContext() private val displayController: DisplayController = mock() - private val windowManagerProxy: MyWmProxy = mock() + private val windowManagerProxy: WindowManagerProxy = mock() private val launcherPrefs: LauncherPrefs = mock() @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT) @@ -312,8 +312,8 @@ abstract class AbstractDeviceProfileTest { DaggerAbsDPTestSandboxComponent.builder() .bindWMProxy(windowManagerProxy) .bindLauncherPrefs(launcherPrefs) + .bindDisplayController(displayController) ) - context.putObject(DisplayController.INSTANCE, displayController) whenever(launcherPrefs.get(LauncherPrefs.TASKBAR_PINNING)).thenReturn(false) whenever(launcherPrefs.get(LauncherPrefs.TASKBAR_PINNING_IN_DESKTOP_MODE)).thenReturn(true) @@ -364,20 +364,18 @@ abstract class AbstractDeviceProfileTest { } } -class MyWmProxy : WindowManagerProxy() - @LauncherAppSingleton -@Component(modules = [LauncherAppModule::class]) +@Component(modules = [AllModulesMinusWMProxy::class]) interface AbsDPTestSandboxComponent : LauncherAppComponent { - override fun getWmProxy(): MyWmProxy - @Component.Builder interface Builder : LauncherAppComponent.Builder { - @BindsInstance fun bindWMProxy(proxy: MyWmProxy): Builder + @BindsInstance fun bindWMProxy(proxy: WindowManagerProxy): Builder @BindsInstance fun bindLauncherPrefs(prefs: LauncherPrefs): Builder + @BindsInstance fun bindDisplayController(displayController: DisplayController): Builder + override fun build(): AbsDPTestSandboxComponent } } diff --git a/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt index fcbb94be9c..97ecafeeab 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AutoInstallsLayoutTest.kt @@ -42,10 +42,10 @@ import com.android.launcher3.LauncherSettings.Favorites.SPANX import com.android.launcher3.LauncherSettings.Favorites.SPANY import com.android.launcher3.LauncherSettings.Favorites._ID import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppModule import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.model.data.AppInfo import com.android.launcher3.pm.UserCache +import com.android.launcher3.util.AllModulesMinusApiWrapper import com.android.launcher3.util.ApiWrapper import com.android.launcher3.util.Executors import com.android.launcher3.util.LauncherLayoutBuilder @@ -224,17 +224,15 @@ class AutoInstallsLayoutTest { } } -class MyApiWrapper : ApiWrapper(null) {} +class MyApiWrapper : ApiWrapper(null) @LauncherAppSingleton -@Component(modules = [LauncherAppModule::class]) +@Component(modules = [AllModulesMinusApiWrapper::class]) interface AutoInstallsLayoutTestComponent : LauncherAppComponent { - override fun getApiWrapper(): MyApiWrapper - @Component.Builder interface Builder : LauncherAppComponent.Builder { - @BindsInstance fun bindApiWrapper(wrapper: MyApiWrapper): Builder + @BindsInstance fun bindApiWrapper(wrapper: ApiWrapper): Builder override fun build(): AutoInstallsLayoutTestComponent } diff --git a/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt b/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt index 43bbad9e68..43b7b68d57 100644 --- a/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/graphics/ThemeManagerTest.kt @@ -20,9 +20,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.FakeLauncherPrefs import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppModule import com.android.launcher3.dagger.LauncherAppSingleton +import com.android.launcher3.util.AllModulesForTest import com.android.launcher3.util.Executors.MAIN_EXECUTOR +import com.android.launcher3.util.FakePrefsModule import com.android.launcher3.util.SandboxApplication import com.android.launcher3.util.TestUtil import dagger.Component @@ -91,7 +92,7 @@ class ThemeManagerTest { } @LauncherAppSingleton -@Component(modules = [LauncherAppModule::class]) +@Component(modules = [AllModulesForTest::class, FakePrefsModule::class]) interface ThemeManagerComponent : LauncherAppComponent { override fun getLauncherPrefs(): FakeLauncherPrefs diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt b/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt new file mode 100644 index 0000000000..68da9ff4d6 --- /dev/null +++ b/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt @@ -0,0 +1,41 @@ +/* + * 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.util + +import com.android.launcher3.FakeLauncherPrefs +import com.android.launcher3.LauncherPrefs +import com.android.launcher3.dagger.ApiWrapperModule +import com.android.launcher3.dagger.WindowManagerProxyModule +import dagger.Binds +import dagger.Module + +private class DaggerGraphs {} + +@Module +abstract class FakePrefsModule { + @Binds abstract fun bindLauncherPrefs(prefs: FakeLauncherPrefs): LauncherPrefs +} + +/** All modules. We also exclude the plugin module from tests */ +@Module(includes = [ApiWrapperModule::class, WindowManagerProxyModule::class]) +class AllModulesForTest + +/** All modules except the WMProxy */ +@Module(includes = [ApiWrapperModule::class]) class AllModulesMinusWMProxy + +/** All modules except the ApiWrapper */ +@Module(includes = [WindowManagerProxyModule::class]) class AllModulesMinusApiWrapper diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt index e6e156fb1e..7e76e1965c 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt @@ -30,7 +30,6 @@ import com.android.launcher3.LauncherPrefs import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING import com.android.launcher3.LauncherPrefs.Companion.TASKBAR_PINNING_IN_DESKTOP_MODE import com.android.launcher3.dagger.LauncherAppComponent -import com.android.launcher3.dagger.LauncherAppModule import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.util.DisplayController.CHANGE_DENSITY import com.android.launcher3.util.DisplayController.CHANGE_ROTATION @@ -43,6 +42,7 @@ import dagger.BindsInstance import dagger.Component import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue +import kotlin.math.min import org.junit.After import org.junit.Before import org.junit.Test @@ -57,7 +57,6 @@ import org.mockito.kotlin.spy import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.mockito.stubbing.Answer -import kotlin.math.min /** Unit tests for {@link DisplayController} */ @SmallTest @@ -139,7 +138,7 @@ class DisplayControllerTest { whenever(context.resources).thenReturn(resources) // Initialize DisplayController - displayController = DisplayController(context) + displayController = DisplayController.INSTANCE.get(context) displayController.addChangeListener(displayInfoChangeListener) } @@ -235,14 +234,12 @@ class DisplayControllerTest { class MyWmProxy : WindowManagerProxy() @LauncherAppSingleton -@Component(modules = [LauncherAppModule::class]) +@Component(modules = [AllModulesMinusWMProxy::class]) interface DisplayControllerTestComponent : LauncherAppComponent { - override fun getWmProxy(): MyWmProxy - @Component.Builder interface Builder : LauncherAppComponent.Builder { - @BindsInstance fun bindWMProxy(proxy: MyWmProxy): Builder + @BindsInstance fun bindWMProxy(proxy: WindowManagerProxy): Builder @BindsInstance fun bindLauncherPrefs(prefs: LauncherPrefs): Builder |