Moving DisplayController to dagger
Separating various overrides to individual modules so that they can be reused in tests
Removing ContextualEduStatsManager and directly using SysUiProxy as all the usescases
are only in quickstep/
This avoids additional Module definition and delegation
Bug: 361850561
Test: Presubmit
Flag: EXEMPT dagger
Change-Id: I096459d638553991ed01766002b874589c6b976e
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 0000000..04c1d5e
--- /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 3fa0e8e..7c6c7ac 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.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 @@
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 d1f9be0..1adb2e9 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.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 @@
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 @@
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 @@
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 @@
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 1d9e492..3f0839d 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.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 @@
}
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 b562838..a74b350 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.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 @@
@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 e27b607..0042c8a 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.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.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.OptionalInt;
import java.util.function.Consumer;
-import kotlin.Unit;
-
/**
* Handles the navigation gestures when Launcher is the default home activity.
*/
@@ -1413,7 +1412,7 @@
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 @@
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 a7405a0..f2cedba 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt
@@ -63,6 +63,7 @@
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 @@
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 6a72537..0000000
--- 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 a6feff0..0000000
--- 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 c682990..a8f3500 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 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 @@
SystemUiProxy mockSystemUiProxy;
@Mock
- ContextualEduStatsManager mockContextualEduStatsManager;
-
- @Mock
TouchInteractionService mockService;
@Mock
Handler mockHandler;
@@ -118,7 +114,6 @@
mockService,
mCallbacks,
mockSystemUiProxy,
- mockContextualEduStatsManager,
mockHandler,
mockContextualSearchInvoker);
}
@@ -132,8 +127,8 @@
@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 @@
@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 @@
@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 74b154a..3cf912c 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 @@
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 @@
}
}
}
- },
- )
+ }
+ }
}
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 31c5a4c..e6dc2a2 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.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 @@
}
}
+/** 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) {
- override fun getLauncherPrefs(): FakeLauncherPrefs
+ 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
+}
+
+@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 0738336..4541fdb 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 @@
verify(systemUiProxy)
.updateContextualEduStats(
/* isTrackpadGesture= */ eq(true),
- eq(GestureType.HOME.toString()),
+ eq(GestureType.HOME),
)
}
@@ -107,7 +107,7 @@
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 dcb45e5..c1be1ce 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 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.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 @@
}
@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 8879a01..7776351 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.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 @@
}
@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 fa81680..be76f9e 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 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.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 @@
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 @@
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 @@
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 5664174..0000000
--- 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
similarity index 79%
rename from quickstep/dagger/com/android/launcher3/dagger/LauncherAppModule.java
rename to src/com/android/launcher3/dagger/LauncherAppModule.java
index 1711fc1..ef136d0 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 4b43d49..5883a88 100644
--- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
+++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
@@ -19,13 +19,13 @@
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 @@
public interface LauncherBaseAppComponent {
DaggerSingletonTracker getDaggerSingletonTracker();
ApiWrapper getApiWrapper();
- ContextualEduStatsManager getContextualEduStatsManager();
CustomWidgetManager getCustomWidgetManager();
DynamicResource getDynamicResource();
IconShape getIconShape();
@@ -66,6 +65,7 @@
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 74a0966..3817563 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.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 @@
} else {
logReachedState(mToState);
}
- updateContextualEduStats(targetState);
}
protected void goToTargetState(LauncherState targetState) {
@@ -406,18 +403,6 @@
.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 d8a2a3d..9472f5f 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.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.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 @@
// 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 @@
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 @@
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 @@
// 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 @@
}
@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 @@
|| !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 @@
@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/LauncherAppModule.java
deleted file mode 100644
index f7b8489..0000000
--- a/src_no_quickstep/com/android/launcher3/dagger/LauncherAppModule.java
+++ /dev/null
@@ -1,22 +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.launcher3.dagger;
-
-import dagger.Module;
-
-@Module
-public class LauncherAppModule { }
diff --git a/quickstep/dagger/com/android/launcher3/dagger/LauncherAppModule.java b/src_no_quickstep/com/android/launcher3/dagger/Modules.kt
similarity index 66%
copy from quickstep/dagger/com/android/launcher3/dagger/LauncherAppModule.java
copy to src_no_quickstep/com/android/launcher3/dagger/Modules.kt
index 1711fc1..dab33a0 100644
--- a/quickstep/dagger/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,11 +14,14 @@
* limitations under the License.
*/
-package com.android.launcher3.dagger;
+package com.android.launcher3.dagger
-import com.android.quickstep.dagger.QuickStepModule;
+import dagger.Module
-import dagger.Module;
+private object Modules {}
-@Module(includes = QuickStepModule.class)
-public class LauncherAppModule {}
+@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 6676766..9c64ec9 100644
--- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -29,9 +29,9 @@
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 @@
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 @@
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 @@
}
}
-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 fcbb94b..97ecafe 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.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 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 43bbad9..43b7b68 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.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 @@
}
@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 0000000..68da9ff
--- /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 e6e156f..7e76e19 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.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.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.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 @@
whenever(context.resources).thenReturn(resources)
// Initialize DisplayController
- displayController = DisplayController(context)
+ displayController = DisplayController.INSTANCE.get(context)
displayController.addChangeListener(displayInfoChangeListener)
}
@@ -235,14 +234,12 @@
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