diff options
51 files changed, 400 insertions, 145 deletions
diff --git a/quickstep/src/com/android/launcher3/dagger/Modules.kt b/quickstep/src/com/android/launcher3/dagger/Modules.kt index 52be4132f2..99631bf53f 100644 --- a/quickstep/src/com/android/launcher3/dagger/Modules.kt +++ b/quickstep/src/com/android/launcher3/dagger/Modules.kt @@ -19,8 +19,10 @@ 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.PerDisplayObjectProvider import com.android.launcher3.util.PluginManagerWrapper import com.android.launcher3.util.window.WindowManagerProxy +import com.android.quickstep.fallback.window.RecentsDisplayModel import com.android.quickstep.util.GestureExclusionManager import com.android.quickstep.util.SystemWindowManagerProxy import dagger.Binds @@ -52,3 +54,9 @@ object StaticObjectModule { @JvmStatic fun provideGestureExclusionManager(): GestureExclusionManager = GestureExclusionManager.INSTANCE } + +@Module +abstract class PerDisplayObjectProviderModule { + @Binds + abstract fun bindPerDisplayObjectProvider(impl: RecentsDisplayModel): PerDisplayObjectProvider +} diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 4143157637..3f1bf3cd67 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -202,7 +202,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { @Override public void onLauncherVisibilityChanged(boolean isVisible) { if (DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(mLauncher)) { - DisplayController.INSTANCE.get(mLauncher).notifyConfigChange(); + DisplayController.get(mLauncher).notifyConfigChange(); } onLauncherVisibilityChanged(isVisible, false /* fromInit */); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index a6d3cde387..126888cdb0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -324,9 +324,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new BubbleDragController(this), new BubbleDismissController(this, mDragLayer), new BubbleBarPinController(this, mDragLayer, - () -> DisplayController.INSTANCE.get(this).getInfo().currentSize), + () -> DisplayController.get(this).getInfo().currentSize), new BubblePinController(this, mDragLayer, - () -> DisplayController.INSTANCE.get(this).getInfo().currentSize), + () -> DisplayController.get(this).getInfo().currentSize), bubbleBarSwipeController, new BubbleCreator(this) )); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index f704254f4a..eccccdf4c1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -425,7 +425,7 @@ public class TaskbarManager { */ public void onUserUnlocked() { mUserUnlocked = true; - DisplayController.INSTANCE.get(mPrimaryWindowContext).addChangeListener( + DisplayController.get(mPrimaryWindowContext).addChangeListener( mRecreationListener); recreateTaskbar(); addTaskbarRootViewToWindow(getDefaultDisplayId()); @@ -797,7 +797,7 @@ public class TaskbarManager { mTaskbarBroadcastReceiver.unregisterReceiverSafely(mPrimaryWindowContext); if (mUserUnlocked) { - DisplayController.INSTANCE.get(mPrimaryWindowContext).removeChangeListener( + DisplayController.get(mPrimaryWindowContext).removeChangeListener( mRecreationListener); } SettingsCache.INSTANCE.get(mPrimaryWindowContext) diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java index c00112383b..5025afc783 100644 --- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java @@ -623,7 +623,7 @@ public class BubbleBarView extends FrameLayout { * Get bubble bar top coordinate on screen when bar is resting */ public int getRestingTopPositionOnScreen() { - int displayHeight = DisplayController.INSTANCE.get(getContext()).getInfo().currentSize.y; + int displayHeight = DisplayController.get(getContext()).getInfo().currentSize.y; int bubbleBarHeight = getBubbleBarBounds().height(); return displayHeight - bubbleBarHeight + (int) mController.getBubbleBarTranslationY(); } diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java index 6d588d964e..4ab104e1e3 100644 --- a/quickstep/src/com/android/quickstep/BaseContainerInterface.java +++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java @@ -290,7 +290,7 @@ public abstract class BaseContainerInterface<STATE_TYPE extends BaseState<STATE_ insets = dp.getInsets(); } else { Rect portraitInsets = dp.getInsets(); - DisplayController displayController = DisplayController.INSTANCE.get(context); + DisplayController displayController = DisplayController.get(context); @Nullable List<WindowBounds> windowBounds = displayController.getInfo().getCurrentBounds(); Rect deviceRotationInsets = windowBounds != null diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java index 9b0e75ce5e..93f31ff0c1 100644 --- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java +++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; +@SuppressWarnings("VisibleForTests") public class QuickstepTestInformationHandler extends TestInformationHandler { protected final Context mContext; @@ -229,7 +230,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler { } private void enableTransientTaskbar(boolean enable) { - DisplayController.INSTANCE.get(mContext).enableTransientTaskbarForTests(enable); + DisplayController.get(mContext).enableTransientTaskbarForTests(enable); } /** diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index 090ccdc869..3742d5aa4f 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -73,6 +73,7 @@ import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.NavigationMode; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.SettingsCache; import com.android.quickstep.TopTaskTracker.CachedTaskInfo; import com.android.quickstep.util.ActiveGestureLog; @@ -141,13 +142,13 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E RecentsAnimationDeviceState( @ApplicationContext Context context, GestureExclusionManager exclusionManager, - DisplayController displayController, + PerDisplayObjectProvider displayControllerProvider, ContextualSearchStateManager contextualSearchStateManager, RotationTouchHelper rotationTouchHelper, SettingsCache settingsCache, DaggerSingletonTracker lifeCycle) { mContext = context; - mDisplayController = displayController; + mDisplayController = displayControllerProvider.getDisplayController(DEFAULT_DISPLAY); mExclusionManager = exclusionManager; mContextualSearchStateManager = contextualSearchStateManager; mRotationTouchHelper = rotationTouchHelper; @@ -156,7 +157,7 @@ public class RecentsAnimationDeviceState implements DisplayInfoChangeListener, E // Register for exclusion updates lifeCycle.addCloseable(this::unregisterExclusionListener); - // Register for display changes changes + // Register for display changes mDisplayController.addChangeListener(this); onDisplayInfoChanged(context, mDisplayController.getInfo(), CHANGE_ALL); lifeCycle.addCloseable(() -> mDisplayController.removeChangeListener(this)); diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index 1d83d42781..f53a8b62b2 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -48,11 +48,13 @@ import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.Executors.SimpleThreadFactory; import com.android.launcher3.util.LockedUserState; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.SafeCloseable; import com.android.quickstep.dagger.QuickstepBaseAppComponent; import com.android.quickstep.recents.data.RecentTasksDataSource; import com.android.quickstep.recents.data.TaskVisualsChangeNotifier; import com.android.quickstep.util.DesktopTask; +import com.android.quickstep.util.ExternalDisplaysKt; import com.android.quickstep.util.GroupTask; import com.android.quickstep.util.TaskVisualsChangeListener; import com.android.systemui.shared.recents.model.Task; @@ -61,6 +63,8 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; +import dagger.Lazy; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -72,8 +76,6 @@ import java.util.function.Predicate; import javax.inject.Inject; -import dagger.Lazy; - /** * Singleton class to load and manage recents model. */ @@ -101,15 +103,17 @@ public class RecentsModel implements RecentTasksDataSource, TaskStackChangeListe public RecentsModel(@ApplicationContext Context context, SystemUiProxy systemUiProxy, TopTaskTracker topTaskTracker, - DisplayController displayController, LockedUserState lockedUserState, + PerDisplayObjectProvider perDisplayObjectProvider, Lazy<ThemeManager> themeManagerLazy, DaggerSingletonTracker tracker ) { // Lazily inject the ThemeManager and access themeManager once the device is // unlocked. See b/393248495 for details. this(context, new IconProvider(context), systemUiProxy, topTaskTracker, - displayController, lockedUserState,themeManagerLazy, tracker); + perDisplayObjectProvider.getDisplayController( + ExternalDisplaysKt.getValidDisplayId(context)), + lockedUserState, themeManagerLazy, tracker); } @SuppressLint("VisibleForTests") diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java index a614327e9d..387adfdee8 100644 --- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java +++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java @@ -43,6 +43,7 @@ import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.NavigationMode; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.quickstep.util.RecentsOrientedState; import com.android.systemui.shared.Flags; import com.android.systemui.shared.system.QuickStepContract; @@ -136,11 +137,11 @@ public class RotationTouchHelper implements DisplayInfoChangeListener { @Inject RotationTouchHelper(@ApplicationContext Context context, - DisplayController displayController, + PerDisplayObjectProvider displayControllerProvider, SystemUiProxy systemUiProxy, DaggerSingletonTracker lifeCycle) { mContext = context; - mDisplayController = displayController; + mDisplayController = displayControllerProvider.getDisplayController(DEFAULT_DISPLAY); mSystemUiProxy = systemUiProxy; mDisplayId = DEFAULT_DISPLAY; diff --git a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java index d2a491dd24..9ebaffa828 100644 --- a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java +++ b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java @@ -15,6 +15,8 @@ */ package com.android.quickstep; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN; import static com.android.launcher3.util.DisplayController.CHANGE_ALL; import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION; @@ -27,6 +29,7 @@ import com.android.launcher3.dagger.LauncherAppSingleton; import com.android.launcher3.util.DaggerSingletonObject; import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.DisplayController; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.quickstep.dagger.QuickstepBaseAppComponent; import javax.inject.Inject; @@ -45,8 +48,10 @@ public class SimpleOrientationTouchTransformer implements @Inject public SimpleOrientationTouchTransformer(@ApplicationContext Context context, - DisplayController displayController, + PerDisplayObjectProvider displayControllerProvider, DaggerSingletonTracker tracker) { + DisplayController displayController = displayControllerProvider.getDisplayController( + DEFAULT_DISPLAY); displayController.addChangeListener(this); tracker.addCloseable(() -> displayController.removeChangeListener(this)); diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.kt b/quickstep/src/com/android/quickstep/TaskIconCache.kt index 6a7f1afb84..3fbf59a237 100644 --- a/quickstep/src/com/android/quickstep/TaskIconCache.kt +++ b/quickstep/src/com/android/quickstep/TaskIconCache.kt @@ -153,7 +153,7 @@ class TaskIconCache( private fun createIconFactory() = BaseIconFactory( context, - DisplayController.INSTANCE.get(context).info.densityDpi, + DisplayController.get(context).info.densityDpi, context.resources.getDimensionPixelSize(R.dimen.task_icon_cache_default_icon_size), ) diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index e47223b7a1..7902ad5324 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -230,7 +230,7 @@ public final class TaskViewUtils { // RecentsView never updates the display rotation until swipe-up so the value may // be stale. Use the display value instead. - int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation; + int displayRotation = DisplayController.get(context).getInfo().rotation; tvsLocal.getOrientationState().update(displayRotation, displayRotation); tvsLocal.fullScreenProgress.value = 0; diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index ba4c65a293..7a4c06b750 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -1112,7 +1112,7 @@ public class TouchInteractionService extends Service { pw.println("Input state:"); pw.println("\tmInputMonitorCompat=" + mInputMonitorCompat); pw.println("\tmInputEventReceiver=" + mInputEventReceiver); - DisplayController.INSTANCE.get(this).dump(pw); + DisplayController.get(this).dump(pw); pw.println("TouchState:"); RecentsViewContainer createdOverviewContainer = mOverviewComponentObserver == null ? null : mOverviewComponentObserver.getContainerInterface().getCreatedContainer(); diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java index ec531d8028..a61c1a0bb9 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java @@ -44,7 +44,7 @@ public class FallbackNavBarTouchController implements TouchController, DisplayController.getNavigationMode(mContainer.asContext()); if (sysUINavigationMode == NavigationMode.NO_BUTTON) { NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode, - DisplayController.INSTANCE.get(mContainer.asContext()).getInfo()); + DisplayController.get(mContainer.asContext()).getInfo()); mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mContainer.asContext(), true /* disableHorizontalSwipe */, navBarPosition, this); } else { diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt b/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt index 95a3ec2b86..c7e77b2ff1 100644 --- a/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt +++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsDisplayModel.kt @@ -18,18 +18,23 @@ package com.android.quickstep.fallback.window import android.content.Context import android.util.Log -import android.view.Display +import android.view.Display.INVALID_DISPLAY import com.android.launcher3.Flags +import com.android.launcher3.LauncherPrefs import com.android.launcher3.dagger.ApplicationContext import com.android.launcher3.dagger.LauncherAppSingleton import com.android.launcher3.util.DaggerSingletonObject import com.android.launcher3.util.DaggerSingletonTracker +import com.android.launcher3.util.DisplayController import com.android.launcher3.util.Executors +import com.android.launcher3.util.PerDisplayObjectProvider import com.android.launcher3.util.WallpaperColorHints +import com.android.launcher3.util.window.WindowManagerProxy import com.android.quickstep.DisplayModel import com.android.quickstep.FallbackWindowInterface import com.android.quickstep.dagger.QuickstepBaseAppComponent import com.android.quickstep.fallback.window.RecentsDisplayModel.RecentsDisplayResource +import com.android.quickstep.util.validDisplayId import javax.inject.Inject @LauncherAppSingleton @@ -37,9 +42,11 @@ class RecentsDisplayModel @Inject constructor( @ApplicationContext context: Context, + private val windowManagerProxy: WindowManagerProxy, + private val launcherPrefs: LauncherPrefs, private val wallpaperColorHints: WallpaperColorHints, tracker: DaggerSingletonTracker, -) : DisplayModel<RecentsDisplayResource>(context) { +) : DisplayModel<RecentsDisplayResource>(context), PerDisplayObjectProvider { companion object { private const val TAG = "RecentsDisplayModel" @@ -57,16 +64,17 @@ constructor( } init { - if (enableOverviewInWindow()) { - displayManager.registerDisplayListener(displayListener, Executors.MAIN_EXECUTOR.handler) - // In the scenario where displays were added before this display listener was - // registered, we should store the RecentsDisplayResources for those displays - // directly. - displayManager.displays - .filter { getDisplayResource(it.displayId) == null } - .forEach { storeRecentsDisplayResource(it.displayId, it) } - tracker.addCloseable { destroy() } - } + // Add the display for the context with which we are initialized. + storeRecentsDisplayResource(context.validDisplayId) + + displayManager.registerDisplayListener(displayListener, Executors.MAIN_EXECUTOR.handler) + // In the scenario where displays were added before this display listener was + // registered, we should store the RecentsDisplayResources for those displays + // directly. + displayManager.displays + .filter { getDisplayResource(it.displayId) == null } + .forEach { storeRecentsDisplayResource(it.displayId) } + tracker.addCloseable { destroy() } } override fun createDisplayResource(displayId: Int) { @@ -74,26 +82,34 @@ constructor( getDisplayResource(displayId)?.let { return } + if (displayId == INVALID_DISPLAY) { + Log.e(TAG, "createDisplayResource: INVALID_DISPLAY") + return + } + storeRecentsDisplayResource(displayId) + } + + private fun storeRecentsDisplayResource(displayId: Int): RecentsDisplayResource { val display = displayManager.getDisplay(displayId) if (display == null) { if (DEBUG) Log.w( TAG, - "createDisplayResource: could not create display for displayId=$displayId", - Exception(), + "storeRecentsDisplayResource: could not create display for displayId=$displayId", ) - return } - storeRecentsDisplayResource(displayId, display) - } - - private fun storeRecentsDisplayResource(displayId: Int, display: Display) { - displayResourceArray[displayId] = - RecentsDisplayResource( - displayId, - context.createDisplayContext(display), - wallpaperColorHints.hints, - ) + return displayResourceArray[displayId] + ?: RecentsDisplayResource( + displayId, + context, + windowManagerProxy, + launcherPrefs, + if (enableOverviewInWindow() && display != null) + context.createDisplayContext(display) + else null, + wallpaperColorHints.hints, + ) + .also { displayResourceArray[displayId] = it } } fun getRecentsWindowManager(displayId: Int): RecentsWindowManager? { @@ -104,17 +120,36 @@ constructor( return getDisplayResource(displayId)?.fallbackWindowInterface } + override fun getDisplayController(displayId: Int): DisplayController { + if (DEBUG) Log.d(TAG, "getDisplayController $displayId") + return (getDisplayResource(displayId) + ?: storeRecentsDisplayResource(displayId).also { + // We shouldn't get here because the display should already have been + // initialized. + Log.e(TAG, "getDisplayController no such display: $displayId") + }) + .displayController + } + data class RecentsDisplayResource( var displayId: Int, - var displayContext: Context, + val appContext: Context, + val windowManagerProxy: WindowManagerProxy, + val launcherPrefs: LauncherPrefs, + var displayContext: Context?, // null when OverviewInWindow not enabled val wallpaperColorHints: Int, ) : DisplayResource() { - val recentsWindowManager = RecentsWindowManager(displayContext, wallpaperColorHints) - val fallbackWindowInterface: FallbackWindowInterface = - FallbackWindowInterface(recentsWindowManager) + val recentsWindowManager = + displayContext?.let { RecentsWindowManager(it, wallpaperColorHints) } + val fallbackWindowInterface: FallbackWindowInterface? = + recentsWindowManager?.let { FallbackWindowInterface(recentsWindowManager) } + val lifecycle = DaggerSingletonTracker() + val displayController = + DisplayController(appContext, windowManagerProxy, launcherPrefs, lifecycle, displayId) override fun cleanup() { - recentsWindowManager.destroy() + recentsWindowManager?.destroy() + lifecycle.close() } } } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java index 503b900ce9..6be1098119 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java @@ -122,7 +122,7 @@ public class DeviceLockedInputConsumer implements InputConsumer, mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(mContext); // Do not use DeviceProfile as the user data might be locked - mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().currentSize; + mDisplaySize = DisplayController.get(context).getInfo().currentSize; // Init states mStateCallback = new MultiStateCallback(STATE_NAMES); diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java index afe988d4eb..9a572b90b5 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java @@ -73,7 +73,7 @@ public class NavHandleLongPressInputConsumer extends DelegateInputConsumer { InputMonitorCompat inputMonitor, RecentsAnimationDeviceState deviceState, NavHandle navHandle, GestureState gestureState) { super(delegate, inputMonitor); - mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x; + mScreenWidth = DisplayController.get(context).getInfo().currentSize.x; mDeepPressEnabled = DeviceConfigWrapper.get().getEnableLpnhDeepPress(); ContextualSearchStateManager contextualSearchStateManager = ContextualSearchStateManager.INSTANCE.get(context); diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java index 83b556dc1b..fa9744dc61 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java @@ -69,7 +69,7 @@ public class OneHandedModeInputConsumer extends DelegateInputConsumer { mDragDistThreshold = context.getResources().getDimensionPixelSize( R.dimen.gestures_onehanded_drag_threshold); mSquaredSlop = mDeviceState.getSquaredTouchSlop(); - mDisplaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize; + mDisplaySize = DisplayController.get(mContext).getInfo().currentSize; mNavBarSize = ResourceUtils.getNavbarSize(NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources()); } diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java index c91bebe77d..ca62657909 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java @@ -99,7 +99,7 @@ public class ProgressDelegateInputConsumer implements InputConsumer, mProgress = progress; // Do not use DeviceProfile as the user data might be locked - mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().currentSize; + mDisplaySize = DisplayController.get(context).getInfo().currentSize; // Init states mStateCallback = new MultiStateCallback(STATE_NAMES); diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java index fdbd509b92..bf6c3c38a4 100644 --- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java +++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java @@ -66,7 +66,7 @@ public class NavBarGestureHandler implements OnTouchListener, /* disableHorizontalSwipe= */ true, new NavBarPosition( NavigationMode.NO_BUTTON, - DisplayController.INSTANCE.get(mContext).getInfo()), + DisplayController.get(mContext).getInfo()), /* onSwipeUp= */ this); mMotionPauseDetector = new MotionPauseDetector(context); diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java index 0cc349db38..c27fb60bb4 100644 --- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java +++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java @@ -16,6 +16,8 @@ package com.android.quickstep.logging; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.android.launcher3.LauncherPrefs.getDevicePrefs; import static com.android.launcher3.LauncherPrefs.getPrefs; import static com.android.launcher3.graphics.ThemeManager.KEY_THEMED_ICONS; @@ -54,6 +56,7 @@ import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.NavigationMode; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.SettingsCache; import com.android.quickstep.dagger.QuickstepBaseAppComponent; @@ -94,9 +97,10 @@ public class SettingsChangeLogger implements @Inject SettingsChangeLogger(@ApplicationContext Context context, DaggerSingletonTracker tracker, - DisplayController displayController, + PerDisplayObjectProvider displayControllerProvider, SettingsCache settingsCache) { - this(context, StatsLogManager.newInstance(context), tracker, displayController, + this(context, StatsLogManager.newInstance(context), tracker, + displayControllerProvider.getDisplayController(DEFAULT_DISPLAY), settingsCache); } diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index 594c99a9c8..fb521ab4ea 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -247,7 +247,7 @@ public class StatsLogCompatManager extends StatsLogManager { StatsCompatLogger(Context context, ActivityContext activityContext) { mContext = context; mActivityContext = Optional.ofNullable(activityContext); - mDisplayRotation = DisplayController.INSTANCE.get(mContext).getInfo().rotation; + mDisplayRotation = DisplayController.get(mContext).getInfo().rotation; } @Override diff --git a/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt b/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt index 455b3121ec..9df1fe81f7 100644 --- a/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt +++ b/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt @@ -16,6 +16,8 @@ package com.android.quickstep.util +import android.content.Context +import android.util.Log import android.view.Display.DEFAULT_DISPLAY import android.view.Display.INVALID_DISPLAY import com.android.systemui.shared.recents.model.Task @@ -24,17 +26,30 @@ import com.android.systemui.shared.recents.model.Task val Int.isExternalDisplay get() = this != DEFAULT_DISPLAY -/** Returns displayId of this [Task], default to [DEFAULT_DISPLAY] */ -val Task?.displayId +val Int?.validDisplayId: Int get() = - this?.key?.displayId.let { displayId -> - when (displayId) { - null -> DEFAULT_DISPLAY - INVALID_DISPLAY -> DEFAULT_DISPLAY - else -> displayId - } + when (this) { + null -> DEFAULT_DISPLAY + INVALID_DISPLAY -> DEFAULT_DISPLAY + else -> this } +/** Returns displayId of this [Task], default to [DEFAULT_DISPLAY] */ +val Task?.validDisplayId + get() = this?.key?.displayId?.validDisplayId ?: DEFAULT_DISPLAY + /** Returns if this task belongs tto [DEFAULT_DISPLAY] */ val Task?.isExternalDisplay - get() = displayId.isExternalDisplay + get(): Boolean = this.validDisplayId.isExternalDisplay ?: false + +val Context?.validDisplayId + get() = + try { + this?.display?.displayId?.validDisplayId ?: DEFAULT_DISPLAY + } catch (ignored: UnsupportedOperationException) { + Log.w( + "ExternalDisplays", + "Tried to get a Display from a Context not associated with one", + ) + DEFAULT_DISPLAY + } diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java index a5be89af19..8fb16d7521 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java +++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java @@ -573,7 +573,7 @@ public class RecentsOrientedState implements LauncherPrefChangeListener { */ public DeviceProfile getLauncherDeviceProfile() { InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(mContext); - Point currentSize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize; + Point currentSize = DisplayController.get(mContext).getInfo().currentSize; int width, height; if ((mRecentsActivityRotation == ROTATION_90 || mRecentsActivityRotation == ROTATION_270)) { diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 609262f770..e86d65748e 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -91,8 +91,8 @@ import com.android.quickstep.util.BorderAnimator.Companion.createSimpleBorderAni import com.android.quickstep.util.RecentsOrientedState import com.android.quickstep.util.TaskCornerRadius import com.android.quickstep.util.TaskRemovedDuringLaunchListener -import com.android.quickstep.util.displayId import com.android.quickstep.util.isExternalDisplay +import com.android.quickstep.util.validDisplayId import com.android.quickstep.views.RecentsView.UNBOUND_TASK_VIEW_ID import com.android.systemui.shared.recents.model.Task import com.android.systemui.shared.recents.model.ThumbnailData @@ -144,7 +144,7 @@ constructor( get() = this === recentsView?.runningTaskView val displayId: Int - get() = taskContainers.firstOrNull()?.task.displayId + get() = taskContainers.firstOrNull()?.task.validDisplayId val isExternalDisplay: Boolean get() = displayId.isExternalDisplay diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt index bfd53ef480..2bdc22a086 100644 --- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt @@ -31,7 +31,6 @@ import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync import com.android.launcher3.taskbar.TaskbarViewTestUtil.createHotseatItems import com.android.launcher3.taskbar.bubbles.BubbleBarViewController import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController -import com.android.launcher3.taskbar.rules.DisplayControllerModule import com.android.launcher3.taskbar.rules.MockedRecentsModelHelper import com.android.launcher3.taskbar.rules.MockedRecentsModelTestRule import com.android.launcher3.taskbar.rules.SandboxParams @@ -423,9 +422,7 @@ class TaskbarOverflowTest { /** TaskbarOverflowComponent used to bind the RecentsModel. */ @LauncherAppSingleton -@Component( - modules = [AllModulesForTest::class, FakePrefsModule::class, DisplayControllerModule::class] -) +@Component(modules = [AllModulesForTest::class, FakePrefsModule::class]) interface TaskbarOverflowComponent : TaskbarSandboxComponent { @Component.Builder 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 3cf912c8e3..482d73593a 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,7 +61,7 @@ class TaskbarModeRule(private val context: TaskbarWindowSandboxContext) : TestRu val mode = taskbarMode.mode getInstrumentation().runOnMainSync { - DisplayController.INSTANCE[context].let { + DisplayController.get(context).let { if (it is DisplayControllerSpy) { it.infoModifier = { info -> spy(info) { 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 95e8980cdb..62d6fdc6dc 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 @@ -26,11 +26,12 @@ import com.android.launcher3.LauncherPrefs import com.android.launcher3.dagger.ApplicationContext import com.android.launcher3.dagger.LauncherAppComponent import com.android.launcher3.dagger.LauncherAppSingleton -import com.android.launcher3.util.AllModulesForTest +import com.android.launcher3.util.AllModulesMinusPerDisplayObjectProvider 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.PerDisplayObjectProvider import com.android.launcher3.util.SandboxApplication import com.android.launcher3.util.SettingsCache import com.android.launcher3.util.SettingsCacheSandbox @@ -131,14 +132,31 @@ constructor( override fun getInfo(): Info = infoModifier?.invoke(super.getInfo()) ?: super.getInfo() } +@LauncherAppSingleton +class PerDisplayObjectProviderImpl +@Inject +constructor(private val displayController: DisplayControllerSpy) : PerDisplayObjectProvider { + override fun getDisplayController(displayId: Int): DisplayController { + return displayController + } +} + @Module -abstract class DisplayControllerModule { - @Binds abstract fun bindDisplayController(controller: DisplayControllerSpy): DisplayController +abstract class PerDisplayObjectProviderModule { + @Binds + abstract fun bindPerDisplayObjectProvider( + impl: PerDisplayObjectProviderImpl + ): PerDisplayObjectProvider } @LauncherAppSingleton @Component( - modules = [AllModulesForTest::class, FakePrefsModule::class, DisplayControllerModule::class] + modules = + [ + AllModulesMinusPerDisplayObjectProvider::class, + FakePrefsModule::class, + PerDisplayObjectProviderModule::class, + ] ) interface TaskbarSandboxComponent : LauncherAppComponent { diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt index b652ee8df4..f5de2b0e83 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsAnimationDeviceStateTest.kt @@ -60,7 +60,7 @@ class RecentsAnimationDeviceStateTest { RecentsAnimationDeviceState( context, exclusionManager, - component.displayController, + component.perDisplayObjectProvider, component.contextualSearchStateManager, component.rotationTouchHelper, component.settingsCache, diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java index c1be1cee9b..e875e4d75d 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java @@ -25,15 +25,12 @@ import com.android.launcher3.util.AllModulesForTest; import com.android.launcher3.util.LauncherMultivalentJUnit; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsState; -import com.android.quickstep.fallback.window.RecentsDisplayModel; 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; @@ -46,16 +43,9 @@ public class RecentsWindowSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase RecentsWindowSwipeHandler, FallbackWindowInterface> { - @Mock private RecentsDisplayModel mRecentsDisplayModel; @Mock private FallbackRecentsView<RecentsWindowManager> mRecentsView; @Mock private RecentsWindowManager mRecentsWindowManager; - @Before - public void setRecentsDisplayModel() { - mContext.initDaggerComponent(DaggerRecentsWindowSwipeHandlerTestCase_TestComponent.builder() - .bindRecentsDisplayModel(mRecentsDisplayModel)); - } - @NonNull @Override protected RecentsWindowSwipeHandler createSwipeHandler(long touchTimeMs, @@ -87,7 +77,6 @@ public class RecentsWindowSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase interface TestComponent extends LauncherAppComponent { @Component.Builder interface Builder extends LauncherAppComponent.Builder { - @BindsInstance Builder bindRecentsDisplayModel(RecentsDisplayModel model); @Override LauncherAppComponent build(); } } 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 7776351517..71d377b1b7 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumerTest.java @@ -433,7 +433,7 @@ public class NavHandleLongPressInputConsumerTest { DaggerNavHandleLongPressInputConsumerTest_TopTaskTrackerComponent .builder() .bindTopTaskTracker(mTopTaskTracker)); - mScreenWidth = DisplayController.INSTANCE.get(mContext).getInfo().currentSize.x; + mScreenWidth = DisplayController.get(mContext).getInfo().currentSize.x; mUnderTest = new NavHandleLongPressInputConsumer(mContext, mDelegate, mInputMonitor, mDeviceState, mNavHandle, mGestureState); mUnderTest.setNavHandleLongPressHandler(mNavHandleLongPressHandler); diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt index 14570b54ec..2671b80e10 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt @@ -64,7 +64,7 @@ class SettingsChangeLoggerTest { @Mock private lateinit var mMockLogger: StatsLogManager.StatsLogger @Mock private lateinit var mTracker: DaggerSingletonTracker - private var displayController: DisplayController = DisplayController.INSTANCE.get(mContext) + private var displayController: DisplayController = DisplayController.get(mContext) private var settingsCache: SettingsCache = SettingsCache.INSTANCE.get(mContext) @Captor private lateinit var mEventCaptor: ArgumentCaptor<StatsLogManager.EventEnum> 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 be76f9e86d..ab480657fd 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java @@ -16,6 +16,7 @@ package com.android.quickstep.util; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -37,11 +38,12 @@ 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.AllModulesMinusWMProxyAndPerDisplayObjectProvider; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.LauncherModelHelper; import com.android.launcher3.util.NavigationMode; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.RotationUtils; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.window.CachedDisplayInfo; @@ -166,10 +168,11 @@ public class TaskViewSimulatorTest { LauncherModelHelper helper = new LauncherModelHelper(); try { DisplayController mockController = mock(DisplayController.class); + PerDisplayObjectProvider objectProvider = mock(PerDisplayObjectProvider.class); helper.sandboxContext.initDaggerComponent( DaggerTaskViewSimulatorTest_TaskViewSimulatorTestComponent.builder() - .bindDisplayController(mockController)); + .bindPerDisplayObjectProvider(objectProvider)); int rotation = mDisplaySize.x > mDisplaySize.y ? Surface.ROTATION_90 : Surface.ROTATION_0; CachedDisplayInfo cdi = new CachedDisplayInfo(mDisplaySize, rotation); @@ -201,6 +204,8 @@ public class TaskViewSimulatorTest { Context configurationContext = helper.sandboxContext.createConfigurationContext( configuration); + when(objectProvider.getDisplayController(anyInt())).thenReturn( + mockController); DisplayController.Info info = new Info( configurationContext, wmProxy, perDisplayBoundsCache); when(mockController.getInfo()).thenReturn(info); @@ -281,14 +286,14 @@ public class TaskViewSimulatorTest { } @LauncherAppSingleton - @Component(modules = {AllModulesMinusWMProxy.class}) + @Component(modules = {AllModulesMinusWMProxyAndPerDisplayObjectProvider.class}) interface TaskViewSimulatorTestComponent extends LauncherAppComponent { @Component.Builder interface Builder extends LauncherAppComponent.Builder { @BindsInstance - Builder bindDisplayController(DisplayController controller); + Builder bindPerDisplayObjectProvider(PerDisplayObjectProvider provider); TaskViewSimulatorTestComponent build(); } diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index c713c3dc9a..06c8745f5d 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -71,9 +71,6 @@ public class NavigationModeSwitchRule implements TestRule { private final LauncherInstrumentation mLauncher; - static final DisplayController DISPLAY_CONTROLLER = - DisplayController.INSTANCE.get(getInstrumentation().getTargetContext()); - public NavigationModeSwitchRule(LauncherInstrumentation launcher) { mLauncher = launcher; } @@ -168,11 +165,13 @@ public class NavigationModeSwitchRule implements TestRule { latch.countDown(); } }; + DisplayController displayController = + DisplayController.get(getInstrumentation().getTargetContext()); targetContext.getMainExecutor().execute(() -> - DISPLAY_CONTROLLER.addChangeListener(listener)); + displayController.addChangeListener(listener)); latch.await(60, TimeUnit.SECONDS); targetContext.getMainExecutor().execute(() -> - DISPLAY_CONTROLLER.removeChangeListener(listener)); + displayController.removeChangeListener(listener)); assertTrue(launcher, "Navigation mode didn't change to " + expectedMode, currentSysUiNavigationMode() == expectedMode, description); diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java index a0ec63577d..649b222755 100644 --- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java +++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java @@ -17,6 +17,8 @@ package com.android.quickstep; +import static android.view.Display.DEFAULT_DISPLAY; + import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static com.android.launcher3.util.NavigationMode.NO_BUTTON; @@ -45,6 +47,7 @@ import androidx.test.filters.SmallTest; import com.android.launcher3.testing.shared.ResourceUtils; import com.android.launcher3.util.DaggerSingletonTracker; import com.android.launcher3.util.DisplayController; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.RotationUtils; import com.android.launcher3.util.WindowBounds; import com.android.launcher3.util.window.CachedDisplayInfo; @@ -300,9 +303,14 @@ public class OrientationTouchTransformerTest { @Test public void testSimpleOrientationTouchTransformer() { final DisplayController displayController = mock(DisplayController.class); + final PerDisplayObjectProvider displayControllerProvider = mock( + PerDisplayObjectProvider.class); + doReturn(displayController).when(displayControllerProvider).getDisplayController( + DEFAULT_DISPLAY); doReturn(mInfo).when(displayController).getInfo(); final SimpleOrientationTouchTransformer transformer = - new SimpleOrientationTouchTransformer(getApplicationContext(), displayController, + new SimpleOrientationTouchTransformer(getApplicationContext(), + displayControllerProvider, mock(DaggerSingletonTracker.class)); final MotionEvent move1 = generateMotionEvent(MotionEvent.ACTION_MOVE, 100, 10); transformer.transform(move1, Surface.ROTATION_90); diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 6277e41c14..db4480a5a5 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -178,6 +178,8 @@ public abstract class BaseActivity extends Activity implements ActivityContext, private ActionMode mCurrentActionMode; + private DisplayController mDisplayController; + @Override public ViewCache getViewCache() { return mViewCache; @@ -224,7 +226,8 @@ public abstract class BaseActivity extends Activity implements ActivityContext, protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); registerBackDispatcher(); - DisplayController.INSTANCE.get(this).addChangeListener(this); + mDisplayController = DisplayController.get(this); + mDisplayController.addChangeListener(this); } @Override @@ -272,7 +275,9 @@ public abstract class BaseActivity extends Activity implements ActivityContext, protected void onDestroy() { super.onDestroy(); mEventCallbacks[EVENT_DESTROYED].executeAllAndClear(); - DisplayController.INSTANCE.get(this).removeChangeListener(this); + if (mDisplayController != null) { + mDisplayController.removeChangeListener(this); + } } @Override diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 900f74d3cc..472cac475c 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -16,6 +16,8 @@ package com.android.launcher3; +import static android.view.Display.DEFAULT_DISPLAY; + import static com.android.launcher3.LauncherPrefs.DB_FILE; import static com.android.launcher3.LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE; import static com.android.launcher3.LauncherPrefs.FIXED_LANDSCAPE_MODE; @@ -256,7 +258,7 @@ public class InvariantDeviceProfile implements SafeCloseable { String gridName = getCurrentGridName(context); initGrid(context, gridName); - DisplayController dc = DisplayController.INSTANCE.get(context); + DisplayController dc = DisplayController.get(context, DEFAULT_DISPLAY); dc.setPriorityListener( (displayContext, info, flags) -> { if ((flags & (CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS @@ -315,7 +317,7 @@ public class InvariantDeviceProfile implements SafeCloseable { String gridName = getCurrentGridName(context); // Get the display info based on default display and interpolate it to existing display - Info defaultInfo = DisplayController.INSTANCE.get(context).getInfo(); + Info defaultInfo = DisplayController.get(context, display.getDisplayId()).getInfo(); @DeviceType int defaultDeviceType = defaultInfo.getDeviceType(); DisplayOption defaultDisplayOption = invDistWeightedInterpolate( defaultInfo, @@ -374,7 +376,7 @@ public class InvariantDeviceProfile implements SafeCloseable { + ", dbFile:" + dbFile + ", LauncherPrefs GRID_NAME:" + LauncherPrefs.get(context).get(GRID_NAME) + ", LauncherPrefs DB_FILE:" + LauncherPrefs.get(context).get(DB_FILE)); - Info displayInfo = DisplayController.INSTANCE.get(context).getInfo(); + Info displayInfo = DisplayController.get(context).getInfo(); List<DisplayOption> allOptions = getPredefinedDeviceProfiles( context, gridName, diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt index 2a5cd63752..fba94fdd80 100644 --- a/src/com/android/launcher3/LauncherPrefs.kt +++ b/src/com/android/launcher3/LauncherPrefs.kt @@ -299,7 +299,7 @@ constructor(@ApplicationContext private val encryptedContext: Context) { @JvmField val ALLOW_ROTATION = backedUpItem(RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY, Boolean::class.java) { - RotationHelper.getAllowRotationDefaultValue(DisplayController.INSTANCE.get(it).info) + RotationHelper.getAllowRotationDefaultValue(DisplayController.get(it).info) } @JvmField diff --git a/src/com/android/launcher3/dagger/LauncherAppModule.java b/src/com/android/launcher3/dagger/LauncherAppModule.java index c58a414304..ece0ff0e3d 100644 --- a/src/com/android/launcher3/dagger/LauncherAppModule.java +++ b/src/com/android/launcher3/dagger/LauncherAppModule.java @@ -23,6 +23,7 @@ import dagger.Module; ApiWrapperModule.class, PluginManagerWrapperModule.class, StaticObjectModule.class, + PerDisplayObjectProviderModule.class, AppModule.class }) public class LauncherAppModule { diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java index 7bd7c3ef12..fe23093bc1 100644 --- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java +++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java @@ -26,11 +26,11 @@ import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.pm.UserCache; 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.LockedUserState; import com.android.launcher3.util.MSDLPlayerWrapper; import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.PerDisplayObjectProvider; import com.android.launcher3.util.PluginManagerWrapper; import com.android.launcher3.util.ScreenOnTracker; import com.android.launcher3.util.SettingsCache; @@ -69,7 +69,7 @@ public interface LauncherBaseAppComponent { LauncherPrefs getLauncherPrefs(); ThemeManager getThemeManager(); UserCache getUserCache(); - DisplayController getDisplayController(); + PerDisplayObjectProvider getPerDisplayObjectProvider(); WallpaperColorHints getWallpaperColorHints(); LockedUserState getLockedUserState(); diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java index 911064cbc0..4c39aa0337 100644 --- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java @@ -284,7 +284,7 @@ public class LauncherPreviewRenderer extends ContextWrapper * Returns the insets of the screen closest to the display given by the context */ private Rect getInsets(Context context) { - DisplayController.Info info = DisplayController.INSTANCE.get(context).getInfo(); + DisplayController.Info info = DisplayController.get(context).getInfo(); float maxDiff = Float.MAX_VALUE; Display display = context.getDisplay(); Rect insets = new Rect(); diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java index 6008287492..1771627376 100644 --- a/src/com/android/launcher3/settings/SettingsActivity.java +++ b/src/com/android/launcher3/settings/SettingsActivity.java @@ -292,7 +292,7 @@ public class SettingsActivity extends FragmentActivity * will remove that preference from the list. */ protected boolean initPreference(Preference preference) { - DisplayController.Info info = DisplayController.INSTANCE.get(getContext()).getInfo(); + DisplayController.Info info = DisplayController.get(getContext()).getInfo(); switch (preference.getKey()) { case NOTIFICATION_DOTS_PREFERENCE_KEY: return BuildConfig.NOTIFICATION_DOTS_ENABLED; diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java index 9376518ddb..f6017c1068 100644 --- a/src/com/android/launcher3/states/RotationHelper.java +++ b/src/com/android/launcher3/states/RotationHelper.java @@ -189,7 +189,7 @@ public class RotationHelper implements LauncherPrefChangeListener, public void initialize() { if (mInitialized) return; mInitialized = true; - DisplayController displayController = DisplayController.INSTANCE.get(mActivity); + DisplayController displayController = DisplayController.get(mActivity); DisplayController.Info info = displayController.getInfo(); setIgnoreAutoRotateSettings(info.isTablet(info.realBounds)); displayController.addChangeListener(this); @@ -201,7 +201,7 @@ public class RotationHelper implements LauncherPrefChangeListener, if (mDestroyed) return; mDestroyed = true; mActivity.removeOnDeviceProfileChangeListener(this); - DisplayController.INSTANCE.get(mActivity).removeChangeListener(this); + DisplayController.get(mActivity).removeChangeListener(this); LauncherPrefs.get(mActivity).removeListener(this, ALLOW_ROTATION); } diff --git a/src/com/android/launcher3/util/DaggerSingletonTracker.java b/src/com/android/launcher3/util/DaggerSingletonTracker.java index b7a88dbf44..1de32e00d6 100644 --- a/src/com/android/launcher3/util/DaggerSingletonTracker.java +++ b/src/com/android/launcher3/util/DaggerSingletonTracker.java @@ -38,7 +38,7 @@ public class DaggerSingletonTracker implements SafeCloseable { private boolean mClosed = false; @Inject - DaggerSingletonTracker() { + public DaggerSingletonTracker() { } /** diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index ee1af810f7..5ad22bfcad 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -16,6 +16,7 @@ package com.android.launcher3.util; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY; @@ -55,7 +56,6 @@ 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; @@ -71,13 +71,10 @@ import java.util.Set; import java.util.StringJoiner; import java.util.concurrent.CopyOnWriteArrayList; -import javax.inject.Inject; - /** * Utility class to cache properties of default display to avoid a system RPC on every call. */ @SuppressLint("NewApi") -@LauncherAppSingleton public class DisplayController implements ComponentCallbacks, DesktopVisibilityListener { @@ -89,8 +86,8 @@ public class DisplayController implements ComponentCallbacks, // TODO(b/254119092) remove all logs with this tag public static final String TASKBAR_NOT_DESTROYED_TAG = "b/254119092"; - public static final DaggerSingletonObject<DisplayController> INSTANCE = - new DaggerSingletonObject<>(LauncherAppComponent::getDisplayController); + public static final DaggerSingletonObject<PerDisplayObjectProvider> PROVIDER = + new DaggerSingletonObject<>(LauncherAppComponent::getPerDisplayObjectProvider); public static final int CHANGE_ACTIVE_SCREEN = 1 << 0; public static final int CHANGE_ROTATION = 1 << 1; @@ -125,14 +122,54 @@ public class DisplayController implements ComponentCallbacks, private Info mInfo; private boolean mDestroyed = false; + private final int mDisplayId; - @Inject - protected DisplayController(@ApplicationContext Context context, + /** + * Get a DisplayController associated with the given Context. + * @param context the context (must return a valid display id) + * @return the DisplayController instance associated with the display id of the context + */ + public static DisplayController get(Context context) { + int displayId = DEFAULT_DISPLAY; + if (context != null) { + try { + displayId = context.getDisplay().getDisplayId(); + } catch (UnsupportedOperationException ignored) { + Log.w(TAG, "DisplayController access from non-display context"); + } + } + if (displayId == INVALID_DISPLAY) { + displayId = DEFAULT_DISPLAY; + } + return PROVIDER.get(context).getDisplayController(displayId); + } + + /** + * Get a DisplayController associated with the given display id. + * @param context a context + * @param displayId a display id + * @return the DisplayController instance associated with the given display id + */ + public static DisplayController get(Context context, int displayId) { + return PROVIDER.get(context).getDisplayController(displayId); + } + + @VisibleForTesting + public DisplayController(@ApplicationContext Context context, WindowManagerProxy wmProxy, LauncherPrefs prefs, DaggerSingletonTracker lifecycle) { + this(context, wmProxy, prefs, lifecycle, DEFAULT_DISPLAY); + } + + public DisplayController(@ApplicationContext Context context, + WindowManagerProxy wmProxy, + LauncherPrefs prefs, + DaggerSingletonTracker lifecycle, + int displayId) { mContext = context; mWMProxy = wmProxy; + mDisplayId = displayId; if (enableTaskbarPinning()) { LauncherPrefChangeListener prefListener = key -> { @@ -150,11 +187,17 @@ public class DisplayController implements ComponentCallbacks, 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)); + prefListener, TASKBAR_PINNING, TASKBAR_PINNING_IN_DESKTOP_MODE)); } Display display = context.getSystemService(DisplayManager.class) - .getDisplay(DEFAULT_DISPLAY); + .getDisplay(displayId); + if (display == null) { + // Race when a display is rapidly added then removed. + mWindowContext = null; + mInfo = null; + return; + } mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null); mWindowContext.registerComponentCallbacks(this); @@ -174,20 +217,25 @@ public class DisplayController implements ComponentCallbacks, }); } + public int getDisplayId() { + return mDisplayId; + } + /** - * Returns the current navigation mode + * Returns the current navigation mode for the display associated with the given Context. */ public static NavigationMode getNavigationMode(Context context) { - return INSTANCE.get(context).getInfo().getNavigationMode(); + return get(context).getInfo().getNavigationMode(); } /** - * Returns whether taskbar is transient or persistent. + * Returns whether taskbar is transient or persistent for the display associated with the given + * Context. * * @return {@code true} if transient, {@code false} if persistent. */ public static boolean isTransientTaskbar(Context context) { - return INSTANCE.get(context).getInfo().isTransientTaskbar(); + return get(context).getInfo().isTransientTaskbar(); } /** @@ -207,25 +255,27 @@ public class DisplayController implements ComponentCallbacks, } /** - * Returns whether the taskbar is pinned in gesture navigation mode. + * Returns whether the taskbar is pinned in gesture navigation mode for the display associated + * with the given Context. */ public static boolean isPinnedTaskbar(Context context) { - return INSTANCE.get(context).getInfo().isPinnedTaskbar(); + return get(context).getInfo().isPinnedTaskbar(); } /** - * Returns whether the taskbar is forced to be pinned when home is visible. + * Returns whether the taskbar is forced to be pinned when home is visible for the display + * associated with the given Context. */ public static boolean showLockedTaskbarOnHome(Context context) { - return INSTANCE.get(context).getInfo().showLockedTaskbarOnHome(); + return get(context).getInfo().showLockedTaskbarOnHome(); } /** * Returns whether desktop taskbar (pinned taskbar that shows desktop tasks) is to be used - * on the display because the display is a freeform display. + * on the display associated with the given Context because the display is a freeform display. */ public static boolean showDesktopTaskbarForFreeformDisplay(Context context) { - return INSTANCE.get(context).getInfo().showDesktopTaskbarForFreeformDisplay(); + return get(context).getInfo().showDesktopTaskbarForFreeformDisplay(); } @Override @@ -261,6 +311,7 @@ public class DisplayController implements ComponentCallbacks, @Override public final void onConfigurationChanged(Configuration config) { Log.d(TASKBAR_NOT_DESTROYED_TAG, "DisplayController#onConfigurationChanged: " + config); + if (mWindowContext == null || mInfo == null) return; if (config.densityDpi != mInfo.densityDpi || config.fontScale != mInfo.fontScale || !mInfo.mScreenSizeDp.equals( @@ -295,6 +346,7 @@ public class DisplayController implements ComponentCallbacks, @AnyThread public void notifyConfigChange() { + if (mWindowContext == null || mInfo == null) return; Info oldInfo = mInfo; Context displayInfoContext = mWindowContext; @@ -348,6 +400,7 @@ public class DisplayController implements ComponentCallbacks, } private void notifyChange(Context context, int flags) { + if (mInfo == null) return; if (mPriorityListener != null) { mPriorityListener.onDisplayInfoChanged(context, mInfo, flags); } @@ -582,6 +635,7 @@ public class DisplayController implements ComponentCallbacks, * Dumps the current state information */ public void dump(PrintWriter pw) { + if (mInfo == null) return; Info info = mInfo; pw.println("DisplayController.Info:"); pw.println(" normalizedDisplayInfo=" + info.normalizedDisplayInfo); diff --git a/src/com/android/launcher3/util/PerDisplayObjectProvider.java b/src/com/android/launcher3/util/PerDisplayObjectProvider.java new file mode 100644 index 0000000000..8cb4e206e0 --- /dev/null +++ b/src/com/android/launcher3/util/PerDisplayObjectProvider.java @@ -0,0 +1,31 @@ +/* + * 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; + +/** + * Interface for providers of objects for which there is one per display. The lifecycle of the + * object is for the time the display is connected or is that of the app, whichever is shorter. + */ +public interface PerDisplayObjectProvider { + /** + * Get the DisplayController the given display id. + * + * @param displayId The display id + * @return Returns the display controller if the display id is valid and otherwise throws an + * IllegalArgumentException. + */ + DisplayController getDisplayController(int displayId); +} diff --git a/src_no_quickstep/com/android/launcher3/dagger/Modules.kt b/src_no_quickstep/com/android/launcher3/dagger/Modules.kt index c3bf7c532b..8872b7931d 100644 --- a/src_no_quickstep/com/android/launcher3/dagger/Modules.kt +++ b/src_no_quickstep/com/android/launcher3/dagger/Modules.kt @@ -16,7 +16,16 @@ package com.android.launcher3.dagger +import android.content.Context +import android.view.Display.DEFAULT_DISPLAY +import com.android.launcher3.LauncherPrefs +import com.android.launcher3.util.DaggerSingletonTracker +import com.android.launcher3.util.DisplayController +import com.android.launcher3.util.PerDisplayObjectProvider +import com.android.launcher3.util.window.WindowManagerProxy +import dagger.Binds import dagger.Module +import javax.inject.Inject private object Modules {} @@ -28,5 +37,30 @@ private object Modules {} @Module object StaticObjectModule {} +@LauncherAppSingleton +class DefaultPerDisplayObjectProvider +@Inject +constructor( + @ApplicationContext context: Context, + wmProxy: WindowManagerProxy, + launcherPrefs: LauncherPrefs, + lifecycleTracker: DaggerSingletonTracker, +) : PerDisplayObjectProvider { + val displayController = + DisplayController(context, wmProxy, launcherPrefs, lifecycleTracker, DEFAULT_DISPLAY) + + override fun getDisplayController(displayId: Int): DisplayController { + return displayController + } +} + +@Module +abstract class PerDisplayObjectProviderModule { + @Binds + abstract fun bindPerDisplayObjectProvider( + impl: DefaultPerDisplayObjectProvider + ): PerDisplayObjectProvider +} + // Module containing bindings for the final derivative app @Module abstract class AppModule {} diff --git a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index 9c64ec9704..56a0543d2f 100644 --- a/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -25,16 +25,18 @@ import android.platform.test.rule.DeviceProduct import android.platform.test.rule.IgnoreLimit import android.platform.test.rule.LimitDevicesRule import android.util.DisplayMetrics +import android.view.Display.DEFAULT_DISPLAY 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.LauncherAppSingleton import com.android.launcher3.testing.shared.ResourceUtils -import com.android.launcher3.util.AllModulesMinusWMProxy +import com.android.launcher3.util.AllModulesMinusWMProxyAndPerDisplayObjectProvider import com.android.launcher3.util.DisplayController import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext import com.android.launcher3.util.NavigationMode +import com.android.launcher3.util.PerDisplayObjectProvider import com.android.launcher3.util.WindowBounds import com.android.launcher3.util.rule.TestStabilityRule import com.android.launcher3.util.rule.setFlags @@ -68,6 +70,7 @@ abstract class AbstractDeviceProfileTest { protected val testContext: Context = InstrumentationRegistry.getInstrumentation().context protected lateinit var context: SandboxContext protected open val runningContext: Context = getApplicationContext() + private val displayControllerProvider: PerDisplayObjectProvider = mock() private val displayController: DisplayController = mock() private val windowManagerProxy: WindowManagerProxy = mock() private val launcherPrefs: LauncherPrefs = mock() @@ -312,7 +315,7 @@ abstract class AbstractDeviceProfileTest { DaggerAbsDPTestSandboxComponent.builder() .bindWMProxy(windowManagerProxy) .bindLauncherPrefs(launcherPrefs) - .bindDisplayController(displayController) + .bindDisplayControllerProvider(displayControllerProvider) ) whenever(launcherPrefs.get(LauncherPrefs.TASKBAR_PINNING)).thenReturn(false) @@ -323,6 +326,8 @@ abstract class AbstractDeviceProfileTest { whenever(launcherPrefs.get(LauncherPrefs.WORKSPACE_SIZE)).thenReturn("") whenever(launcherPrefs.get(LauncherPrefs.DB_FILE)).thenReturn("") whenever(launcherPrefs.get(LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE)).thenReturn(true) + whenever(displayControllerProvider.getDisplayController(DEFAULT_DISPLAY)) + .thenReturn(displayController) val info = spy(DisplayController.Info(context, windowManagerProxy, perDisplayBoundsCache)) whenever(displayController.info).thenReturn(info) whenever(info.isTransientTaskbar).thenReturn(isGestureMode) @@ -365,7 +370,7 @@ abstract class AbstractDeviceProfileTest { } @LauncherAppSingleton -@Component(modules = [AllModulesMinusWMProxy::class]) +@Component(modules = [AllModulesMinusWMProxyAndPerDisplayObjectProvider::class]) interface AbsDPTestSandboxComponent : LauncherAppComponent { @Component.Builder @@ -374,7 +379,7 @@ interface AbsDPTestSandboxComponent : LauncherAppComponent { @BindsInstance fun bindLauncherPrefs(prefs: LauncherPrefs): Builder - @BindsInstance fun bindDisplayController(displayController: DisplayController): Builder + @BindsInstance fun bindDisplayControllerProvider(dc: PerDisplayObjectProvider): Builder override fun build(): AbsDPTestSandboxComponent } diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt b/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt index b66a9d3330..815255233a 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DaggerGraphs.kt @@ -20,6 +20,7 @@ import com.android.launcher3.FakeLauncherPrefs import com.android.launcher3.LauncherPrefs import com.android.launcher3.dagger.ApiWrapperModule import com.android.launcher3.dagger.AppModule +import com.android.launcher3.dagger.PerDisplayObjectProviderModule import com.android.launcher3.dagger.StaticObjectModule import com.android.launcher3.dagger.WindowManagerProxyModule import dagger.Binds @@ -39,15 +40,47 @@ abstract class FakePrefsModule { ApiWrapperModule::class, WindowManagerProxyModule::class, StaticObjectModule::class, + PerDisplayObjectProviderModule::class, AppModule::class, ] ) class AllModulesForTest /** All modules except the WMProxy */ -@Module(includes = [ApiWrapperModule::class, StaticObjectModule::class, AppModule::class]) +@Module( + includes = + [ + ApiWrapperModule::class, + StaticObjectModule::class, + PerDisplayObjectProviderModule::class, + AppModule::class, + ] +) class AllModulesMinusWMProxy /** All modules except the ApiWrapper */ -@Module(includes = [WindowManagerProxyModule::class, StaticObjectModule::class, AppModule::class]) +@Module( + includes = + [ + WindowManagerProxyModule::class, + StaticObjectModule::class, + PerDisplayObjectProviderModule::class, + AppModule::class, + ] +) class AllModulesMinusApiWrapper + +@Module(includes = [ApiWrapperModule::class, StaticObjectModule::class, AppModule::class]) +class AllModulesMinusWMProxyAndPerDisplayObjectProvider + +/** All modules except PerDisplayObjectProvider */ +@Module( + includes = + [ + ApiWrapperModule::class, + WindowManagerProxyModule::class, + StaticObjectModule::class, + AppModule::class, + ] +) +class AllModulesMinusPerDisplayObjectProvider diff --git a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt index 588a668b7a..acf5908b2e 100644 --- a/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/util/DisplayControllerTest.kt @@ -139,7 +139,7 @@ class DisplayControllerTest { whenever(context.resources).thenReturn(resources) // Initialize DisplayController - displayController = DisplayController.INSTANCE.get(context) + displayController = DisplayController.get(context) displayController.addChangeListener(displayInfoChangeListener) } |