Move RecentsModel to Dagger.
Bug: 361850561
Test: Presubmit
Flag: EXEMPT dagger
Change-Id: I0d459ee3fc012e8e371035071f1b32eb2483cdc5
diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java
index 87b58e6..1d83d42 100644
--- a/quickstep/src/com/android/quickstep/RecentsModel.java
+++ b/quickstep/src/com/android/quickstep/RecentsModel.java
@@ -38,13 +38,18 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
import com.android.launcher3.graphics.ThemeManager;
import com.android.launcher3.graphics.ThemeManager.ThemeChangeListener;
import com.android.launcher3.icons.IconProvider;
+import com.android.launcher3.util.DaggerSingletonObject;
+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.MainThreadInitializedObject;
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;
@@ -65,19 +70,22 @@
import java.util.function.Consumer;
import java.util.function.Predicate;
-import javax.inject.Provider;
+import javax.inject.Inject;
+
+import dagger.Lazy;
/**
* Singleton class to load and manage recents model.
*/
@TargetApi(Build.VERSION_CODES.O)
+@LauncherAppSingleton
public class RecentsModel implements RecentTasksDataSource, TaskStackChangeListener,
TaskVisualsChangeListener, TaskVisualsChangeNotifier,
- ThemeChangeListener, SafeCloseable {
+ ThemeChangeListener {
// We do not need any synchronization for this variable as its only written on UI thread.
- public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
- new MainThreadInitializedObject<>(RecentsModel::new);
+ public static final DaggerSingletonObject<RecentsModel> INSTANCE =
+ new DaggerSingletonObject<>(QuickstepBaseAppComponent::getRecentsModel);
private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor(
new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND));
@@ -85,53 +93,67 @@
private final ConcurrentLinkedQueue<TaskVisualsChangeListener> mThumbnailChangeListeners =
new ConcurrentLinkedQueue<>();
private final Context mContext;
-
private final RecentTasksList mTaskList;
private final TaskIconCache mIconCache;
private final TaskThumbnailCache mThumbnailCache;
- private final ComponentCallbacks mCallbacks;
- private final TaskStackChangeListeners mTaskStackChangeListeners;
- private final SafeCloseable mIconChangeCloseable;
-
- private final LockedUserState mLockedUserState;
- private final Provider<ThemeManager> mThemeManagerProvider;
- private final Runnable mUnlockCallback;
-
- private RecentsModel(Context context) {
- this(context, new IconProvider(context));
+ @Inject
+ public RecentsModel(@ApplicationContext Context context,
+ SystemUiProxy systemUiProxy,
+ TopTaskTracker topTaskTracker,
+ DisplayController displayController,
+ LockedUserState lockedUserState,
+ 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);
}
@SuppressLint("VisibleForTests")
- private RecentsModel(Context context, IconProvider iconProvider) {
+ private RecentsModel(@ApplicationContext Context context,
+ IconProvider iconProvider,
+ SystemUiProxy systemUiProxy,
+ TopTaskTracker topTaskTracker,
+ DisplayController displayController,
+ LockedUserState lockedUserState,
+ Lazy<ThemeManager> themeManagerLazy,
+ DaggerSingletonTracker tracker) {
this(context,
new RecentTasksList(
context,
MAIN_EXECUTOR,
context.getSystemService(KeyguardManager.class),
- SystemUiProxy.INSTANCE.get(context),
- TopTaskTracker.INSTANCE.get(context)),
- new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider),
+ systemUiProxy,
+ topTaskTracker),
+ new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider, displayController),
new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR),
iconProvider,
TaskStackChangeListeners.getInstance(),
- LockedUserState.get(context),
- () -> ThemeManager.INSTANCE.get(context));
+ lockedUserState,
+ themeManagerLazy,
+ tracker);
}
@VisibleForTesting
- RecentsModel(Context context, RecentTasksList taskList, TaskIconCache iconCache,
- TaskThumbnailCache thumbnailCache, IconProvider iconProvider,
+ RecentsModel(@ApplicationContext Context context,
+ RecentTasksList taskList,
+ TaskIconCache iconCache,
+ TaskThumbnailCache thumbnailCache,
+ IconProvider iconProvider,
TaskStackChangeListeners taskStackChangeListeners,
LockedUserState lockedUserState,
- Provider<ThemeManager> themeManagerProvider) {
+ Lazy<ThemeManager> themeManagerLazy,
+ DaggerSingletonTracker tracker) {
mContext = context;
mTaskList = taskList;
mIconCache = iconCache;
mIconCache.registerTaskVisualsChangeListener(this);
mThumbnailCache = thumbnailCache;
if (isCachePreloadingEnabled()) {
- mCallbacks = new ComponentCallbacks() {
+ ComponentCallbacks componentCallbacks = new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration configuration) {
updateCacheSizeAndPreloadIfNeeded();
@@ -141,20 +163,27 @@
public void onLowMemory() {
}
};
- context.registerComponentCallbacks(mCallbacks);
- } else {
- mCallbacks = null;
+ context.registerComponentCallbacks(componentCallbacks);
+ tracker.addCloseable(() -> context.unregisterComponentCallbacks(componentCallbacks));
}
- mTaskStackChangeListeners = taskStackChangeListeners;
- mTaskStackChangeListeners.registerTaskStackListener(this);
- mIconChangeCloseable = iconProvider.registerIconChangeListener(
+ taskStackChangeListeners.registerTaskStackListener(this);
+ SafeCloseable iconChangeCloseable = iconProvider.registerIconChangeListener(
this::onAppIconChanged, MAIN_EXECUTOR.getHandler());
- mLockedUserState = lockedUserState;
- mThemeManagerProvider = themeManagerProvider;
- mUnlockCallback = () -> mThemeManagerProvider.get().addChangeListener(this);
- lockedUserState.runOnUserUnlocked(mUnlockCallback);
+ Runnable unlockCallback = () -> themeManagerLazy.get().addChangeListener(this);
+ lockedUserState.runOnUserUnlocked(unlockCallback);
+
+ tracker.addCloseable(() -> {
+ taskStackChangeListeners.unregisterTaskStackListener(this);
+ iconChangeCloseable.close();
+ mIconCache.removeTaskVisualsChangeListener();
+ if (lockedUserState.isUserUnlocked()) {
+ themeManagerLazy.get().removeChangeListener(this);
+ } else {
+ lockedUserState.removeOnUserUnlockedRunnable(unlockCallback);
+ }
+ });
}
public TaskIconCache getIconCache() {
@@ -407,22 +436,6 @@
}
}
- @Override
- public void close() {
- if (mCallbacks != null) {
- mContext.unregisterComponentCallbacks(mCallbacks);
- }
- mIconCache.removeTaskVisualsChangeListener();
- mTaskStackChangeListeners.unregisterTaskStackListener(this);
- mIconChangeCloseable.close();
-
- if (mLockedUserState.isUserUnlocked()) {
- mThemeManagerProvider.get().removeChangeListener(this);
- } else {
- mLockedUserState.removeOnUserUnlockedRunnable(mUnlockCallback);
- }
- }
-
private boolean isCachePreloadingEnabled() {
return enableGridOnlyOverview() || enableRefactorTaskThumbnail();
}
diff --git a/quickstep/src/com/android/quickstep/TaskIconCache.kt b/quickstep/src/com/android/quickstep/TaskIconCache.kt
index bf94d41..7692e78 100644
--- a/quickstep/src/com/android/quickstep/TaskIconCache.kt
+++ b/quickstep/src/com/android/quickstep/TaskIconCache.kt
@@ -52,6 +52,7 @@
private val context: Context,
private val bgExecutor: Executor,
private val iconProvider: IconProvider,
+ displayController: DisplayController,
) : TaskIconDataSource, DisplayInfoChangeListener {
private val iconCache =
TaskKeyLruCache<TaskCacheEntry>(
@@ -70,7 +71,7 @@
var taskVisualsChangeListener: TaskVisualsChangeListener? = null
init {
- DisplayController.INSTANCE.get(context).addChangeListener(this)
+ displayController.addChangeListener(this)
}
override fun onDisplayInfoChanged(context: Context, info: DisplayController.Info, flags: Int) {
diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
index adc45ae..853511b 100644
--- a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
+++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
@@ -22,6 +22,7 @@
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.RecentsAnimationDeviceState;
+import com.android.quickstep.RecentsModel;
import com.android.quickstep.RotationTouchHelper;
import com.android.quickstep.SimpleOrientationTouchTransformer;
import com.android.quickstep.SystemUiProxy;
@@ -61,6 +62,8 @@
RecentsAnimationDeviceState getRecentsAnimationDeviceState();
+ RecentsModel getRecentsModel();
+
SettingsChangeLogger getSettingsChangeLogger();
SimpleOrientationTouchTransformer getSimpleOrientationTouchTransformer();
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendControllerTest.kt
index 785e585..50d6aff 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendControllerTest.kt
@@ -22,6 +22,7 @@
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_IN_LAUNCHER
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_TOUCHING
+import com.android.launcher3.taskbar.rules.SandboxParams
import com.android.launcher3.taskbar.rules.TaskbarModeRule
import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.TRANSIENT
import com.android.launcher3.taskbar.rules.TaskbarModeRule.TaskbarMode
@@ -46,15 +47,15 @@
@get:Rule(order = 0)
val context =
- TaskbarWindowSandboxContext.create { builder ->
- builder.bindSystemUiProxy(
+ TaskbarWindowSandboxContext.create(
+ SandboxParams({
spy(SystemUiProxy(ApplicationProvider.getApplicationContext())) { proxy ->
doAnswer { latestSuspendNotification = it.getArgument(0) }
.whenever(proxy)
.notifyTaskbarAutohideSuspend(anyOrNull())
}
- )
- }
+ })
+ )
@get:Rule(order = 1) val animatorTestRule = AnimatorTestRule(this)
@get:Rule(order = 2) val taskbarModeRule = TaskbarModeRule(context)
@get:Rule(order = 3) val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)
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 9ca8a1b..bfd53ef 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarOverflowTest.kt
@@ -26,21 +26,29 @@
import com.android.launcher3.Flags.FLAG_ENABLE_MULTI_INSTANCE_MENU_TASKBAR
import com.android.launcher3.Flags.FLAG_TASKBAR_OVERFLOW
import com.android.launcher3.R
+import com.android.launcher3.dagger.LauncherAppSingleton
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
import com.android.launcher3.taskbar.rules.TaskbarModeRule
import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.PINNED
import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.TRANSIENT
import com.android.launcher3.taskbar.rules.TaskbarModeRule.TaskbarMode
+import com.android.launcher3.taskbar.rules.TaskbarSandboxComponent
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
+import com.android.launcher3.util.AllModulesForTest
+import com.android.launcher3.util.FakePrefsModule
import com.android.launcher3.util.LauncherMultivalentJUnit
import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
import com.android.launcher3.util.TestUtil.getOnUiThread
+import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.quickstep.util.DesktopTask
import com.android.systemui.shared.recents.model.Task
@@ -49,6 +57,8 @@
import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR
import com.android.wm.shell.desktopmode.IDesktopTaskListener
import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -70,19 +80,25 @@
class TaskbarOverflowTest {
@get:Rule(order = 0) val setFlagsRule = SetFlagsRule()
+ val mockRecentsModelHelper: MockedRecentsModelHelper = MockedRecentsModelHelper()
+
@get:Rule(order = 1)
val context =
- TaskbarWindowSandboxContext.create { builder ->
- builder.bindSystemUiProxy(
- spy(SystemUiProxy(ApplicationProvider.getApplicationContext())) { proxy ->
- doAnswer { desktopTaskListener = it.getArgument(0) }
- .whenever(proxy)
- .setDesktopTaskListener(anyOrNull())
- }
+ TaskbarWindowSandboxContext.create(
+ SandboxParams(
+ {
+ spy(SystemUiProxy(ApplicationProvider.getApplicationContext())) { proxy ->
+ doAnswer { desktopTaskListener = it.getArgument(0) }
+ .whenever(proxy)
+ .setDesktopTaskListener(anyOrNull())
+ }
+ },
+ DaggerTaskbarOverflowComponent.builder()
+ .bindRecentsModel(mockRecentsModelHelper.mockRecentsModel),
)
- }
+ )
- @get:Rule(order = 2) val recentsModel = MockedRecentsModelTestRule(context)
+ @get:Rule(order = 2) val recentsModel = MockedRecentsModelTestRule(mockRecentsModelHelper)
@get:Rule(order = 3) val taskbarModeRule = TaskbarModeRule(context)
@@ -404,3 +420,18 @@
return maxNumIconViews
}
}
+
+/** TaskbarOverflowComponent used to bind the RecentsModel. */
+@LauncherAppSingleton
+@Component(
+ modules = [AllModulesForTest::class, FakePrefsModule::class, DisplayControllerModule::class]
+)
+interface TaskbarOverflowComponent : TaskbarSandboxComponent {
+
+ @Component.Builder
+ interface Builder : TaskbarSandboxComponent.Builder {
+ @BindsInstance fun bindRecentsModel(model: RecentsModel): Builder
+
+ override fun build(): TaskbarOverflowComponent
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarScrimViewControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarScrimViewControllerTest.kt
index 360f019..ba53dcd 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarScrimViewControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarScrimViewControllerTest.kt
@@ -25,6 +25,7 @@
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController
+import com.android.launcher3.taskbar.rules.SandboxParams
import com.android.launcher3.taskbar.rules.TaskbarModeRule
import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.PINNED
import com.android.launcher3.taskbar.rules.TaskbarModeRule.Mode.TRANSIENT
@@ -55,13 +56,14 @@
@get:Rule(order = 0) val setFlagsRule = SetFlagsRule()
@get:Rule(order = 1)
val context =
- TaskbarWindowSandboxContext.create { builder ->
- builder.bindSystemUiProxy(
+ TaskbarWindowSandboxContext.create(
+ SandboxParams({
spy(SystemUiProxy(ApplicationProvider.getApplicationContext())) {
doAnswer { backPressed = true }.whenever(it).onBackEvent(anyOrNull())
}
- )
- }
+ })
+ )
+
@get:Rule(order = 2) val taskbarModeRule = TaskbarModeRule(context)
@get:Rule(order = 3) val animatorTestRule = AnimatorTestRule(this)
@get:Rule(order = 4) val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelHelper.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelHelper.kt
new file mode 100644
index 0000000..a7bfa9a
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelHelper.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.rules
+
+import com.android.quickstep.RecentsModel
+import com.android.quickstep.RecentsModel.RecentTasksChangedListener
+import com.android.quickstep.TaskIconCache
+import com.android.quickstep.util.GroupTask
+import java.util.function.Consumer
+import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+
+/** Helper class to mock the {@link RecentsModel} object in test */
+class MockedRecentsModelHelper {
+ private val mockIconCache: TaskIconCache = mock()
+ var taskListId = 0
+ var recentTasksChangedListener: RecentTasksChangedListener? = null
+ var taskRequests: MutableList<(List<GroupTask>) -> Unit> = mutableListOf()
+
+ val mockRecentsModel: RecentsModel = mock {
+ on { iconCache } doReturn mockIconCache
+
+ on { unregisterRecentTasksChangedListener() } doAnswer { recentTasksChangedListener = null }
+
+ on { registerRecentTasksChangedListener(any<RecentTasksChangedListener>()) } doAnswer
+ {
+ recentTasksChangedListener = it.getArgument<RecentTasksChangedListener>(0)
+ }
+
+ on { getTasks(anyOrNull(), anyOrNull()) } doAnswer
+ {
+ val request = it.getArgument<Consumer<List<GroupTask>>?>(0)
+ if (request != null) {
+ taskRequests.add { response -> request.accept(response) }
+ }
+ taskListId
+ }
+
+ on { getTasks(anyOrNull()) } doAnswer
+ {
+ val request = it.getArgument<Consumer<List<GroupTask>>?>(0)
+ if (request != null) {
+ taskRequests.add { response -> request.accept(response) }
+ }
+ taskListId
+ }
+
+ on { isTaskListValid(any()) } doAnswer { taskListId == it.getArgument(0) }
+ }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelTestRule.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelTestRule.kt
index ed1443d..359b876 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelTestRule.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/rules/MockedRecentsModelTestRule.kt
@@ -16,64 +16,17 @@
package com.android.launcher3.taskbar.rules
-import com.android.quickstep.RecentsModel
-import com.android.quickstep.RecentsModel.RecentTasksChangedListener
-import com.android.quickstep.TaskIconCache
import com.android.quickstep.util.GroupTask
-import java.util.function.Consumer
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
-import org.mockito.kotlin.any
-import org.mockito.kotlin.anyOrNull
-import org.mockito.kotlin.doAnswer
-import org.mockito.kotlin.doReturn
-import org.mockito.kotlin.mock
-class MockedRecentsModelTestRule(private val context: TaskbarWindowSandboxContext) : TestRule {
-
- private val mockIconCache: TaskIconCache = mock()
-
- private val mockRecentsModel: RecentsModel = mock {
- on { iconCache } doReturn mockIconCache
-
- on { unregisterRecentTasksChangedListener() } doAnswer { recentTasksChangedListener = null }
-
- on { registerRecentTasksChangedListener(any<RecentTasksChangedListener>()) } doAnswer
- {
- recentTasksChangedListener = it.getArgument<RecentTasksChangedListener>(0)
- }
-
- on { getTasks(anyOrNull(), anyOrNull()) } doAnswer
- {
- val request = it.getArgument<Consumer<List<GroupTask>>?>(0)
- if (request != null) {
- taskRequests.add { response -> request.accept(response) }
- }
- taskListId
- }
-
- on { getTasks(anyOrNull()) } doAnswer
- {
- val request = it.getArgument<Consumer<List<GroupTask>>?>(0)
- if (request != null) {
- taskRequests.add { response -> request.accept(response) }
- }
- taskListId
- }
-
- on { isTaskListValid(any()) } doAnswer { taskListId == it.getArgument(0) }
- }
-
+class MockedRecentsModelTestRule(private val modelHelper: MockedRecentsModelHelper) : TestRule {
private var recentTasks: List<GroupTask> = emptyList()
- private var taskListId = 0
- private var recentTasksChangedListener: RecentTasksChangedListener? = null
- private var taskRequests: MutableList<(List<GroupTask>) -> Unit> = mutableListOf()
override fun apply(base: Statement?, description: Description?): Statement {
return object : Statement() {
override fun evaluate() {
- context.putObject(RecentsModel.INSTANCE, mockRecentsModel)
base?.evaluate()
}
}
@@ -82,15 +35,15 @@
// NOTE: For the update to take effect, `resolvePendingTaskRequests()` needs to be called, so
// calbacks to any pending `RecentsModel.getTasks()` get called with the updated task list.
fun updateRecentTasks(tasks: List<GroupTask>) {
- ++taskListId
+ ++modelHelper.taskListId
recentTasks = tasks
- recentTasksChangedListener?.onRecentTasksChanged()
+ modelHelper.recentTasksChangedListener?.onRecentTasksChanged()
}
fun resolvePendingTaskRequests() {
val requests = mutableListOf<(List<GroupTask>) -> Unit>()
- requests.addAll(taskRequests)
- taskRequests.clear()
+ requests.addAll(modelHelper.taskRequests)
+ modelHelper.taskRequests.clear()
requests.forEach { it(recentTasks) }
}
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 e6dc2a2..95e8980 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
@@ -47,10 +47,6 @@
import org.junit.runner.Description
import org.junit.runners.model.Statement
-/** Include additional bindings when building a [TaskbarSandboxComponent]. */
-typealias TaskbarComponentBinder =
- TaskbarWindowSandboxContext.(TaskbarSandboxComponent.Builder) -> Unit
-
/**
* [SandboxApplication] for running Taskbar tests.
*
@@ -61,7 +57,7 @@
private constructor(
private val base: SandboxApplication,
val virtualDisplay: VirtualDisplay,
- private val componentBinder: TaskbarComponentBinder?,
+ private val params: SandboxParams,
) : ContextWrapper(base), ObjectSandbox by base, TestRule {
val settingsCacheSandbox = SettingsCacheSandbox()
@@ -76,10 +72,9 @@
override fun before() {
val context = this@TaskbarWindowSandboxContext
val builder =
- DaggerTaskbarSandboxComponent.builder()
- .bindSystemUiProxy(SystemUiProxy(context))
+ params.builderBase
+ .bindSystemUiProxy(params.systemUiProxyProvider.invoke(context))
.bindSettingsCache(settingsCacheSandbox.cache)
- componentBinder?.invoke(context, builder)
base.initDaggerComponent(builder)
}
}
@@ -95,10 +90,9 @@
private const val VIRTUAL_DISPLAY_NAME = "TaskbarSandboxDisplay"
/** Creates a [SandboxApplication] for Taskbar tests. */
- fun create(componentBinder: TaskbarComponentBinder? = null): TaskbarWindowSandboxContext {
+ fun create(params: SandboxParams = SandboxParams()): TaskbarWindowSandboxContext {
val base = ApplicationProvider.getApplicationContext<Context>()
val displayManager = checkNotNull(base.getSystemService(DisplayManager::class.java))
-
// Create virtual display to avoid clashing with Taskbar on default display.
val virtualDisplay =
base.resources.displayMetrics.let {
@@ -115,7 +109,7 @@
return TaskbarWindowSandboxContext(
SandboxApplication(base.createDisplayContext(virtualDisplay.display)),
virtualDisplay,
- componentBinder,
+ params,
)
}
}
@@ -157,3 +151,9 @@
override fun build(): TaskbarSandboxComponent
}
}
+
+/** Include additional bindings when building a [TaskbarSandboxComponent]. */
+data class SandboxParams(
+ val systemUiProxyProvider: (Context) -> SystemUiProxy = { SystemUiProxy(it) },
+ val builderBase: TaskbarSandboxComponent.Builder = DaggerTaskbarSandboxComponent.builder(),
+)
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsModelTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsModelTest.java
index 722e1da..2eb2e4c 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsModelTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsModelTest.java
@@ -43,6 +43,7 @@
import com.android.launcher3.R;
import com.android.launcher3.graphics.ThemeManager;
import com.android.launcher3.icons.IconProvider;
+import com.android.launcher3.util.DaggerSingletonTracker;
import com.android.launcher3.util.LockedUserState;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.quickstep.util.GroupTask;
@@ -109,7 +110,7 @@
mRecentsModel = new RecentsModel(mContext, mTasksList, mock(TaskIconCache.class),
mThumbnailCache, mock(IconProvider.class), mock(TaskStackChangeListeners.class),
- mLockedUserState, () -> mThemeManager);
+ mLockedUserState, () -> mThemeManager, mock(DaggerSingletonTracker.class));
mResource = mock(Resources.class);
when(mResource.getInteger((R.integer.recentsThumbnailCacheSize))).thenReturn(3);