mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 03:08:19 +00:00
Don't trigger getRecentTasks() calls when waiting for an old call
TaskbarRecentAppsController#reloadRecentTasksIfNeeded() triggers a call to fetch Recents tasks, that call is expensive as it goes through WM Shell and the system server. If we trigger reloadRecentTasksIfNeeded() multiple times we're queueing up multiple calls to fetch Recents tasks. With this CL we avoid queueing up multiple calls, and instead just make one new call when the old one finishes. That way we can only ever have one call getRecentTasks() call triggered through reloadRecentTasksIfNeeded() posted at any one time. Bug: 415090968 Flag: com.android.window.flags.enable_taskbar_recent_tasks_throttle_bugfix Test: TaskbarRecentAppsControllerTest Change-Id: I58b66e4564af4e64837317a9de7be398395d8568
This commit is contained in:
@@ -24,7 +24,9 @@ import android.content.res.Resources
|
||||
import android.graphics.Rect
|
||||
import android.os.Process
|
||||
import android.os.UserHandle
|
||||
import android.platform.test.annotations.DisableFlags
|
||||
import android.platform.test.annotations.EnableFlags
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import android.view.Display.DEFAULT_DISPLAY
|
||||
import androidx.test.annotation.UiThreadTest
|
||||
import com.android.internal.R
|
||||
@@ -60,6 +62,7 @@ import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argumentCaptor
|
||||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.times
|
||||
@@ -72,6 +75,7 @@ import org.mockito.kotlin.whenever
|
||||
class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
||||
|
||||
@get:Rule val mockitoRule = MockitoJUnit.rule()
|
||||
@get:Rule val setFlagsRule = SetFlagsRule()
|
||||
@get:Rule
|
||||
val disableControllerForCertainTestsWatcher =
|
||||
object : TestWatcher() {
|
||||
@@ -118,6 +122,16 @@ class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
||||
recentAppsController = TaskbarRecentAppsController(mockContext, mockRecentsModel)
|
||||
recentAppsController.canShowRunningApps = canShowRunningAndRecentAppsAtInit
|
||||
recentAppsController.canShowRecentApps = canShowRunningAndRecentAppsAtInit
|
||||
|
||||
// To ensure the initial getTasks() call is not seen as "loading" for the rest of the test,
|
||||
// execute its callback.
|
||||
doAnswer {
|
||||
val callback: Consumer<ArrayList<GroupTask>> = it.getArgument(1)
|
||||
callback.accept(arrayListOf())
|
||||
taskListChangeId
|
||||
}
|
||||
.whenever(mockRecentsModel)
|
||||
.getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
recentAppsController.init(taskbarControllers, emptyList())
|
||||
taskbarControllers.onPostInit()
|
||||
|
||||
@@ -148,7 +162,7 @@ class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
||||
runningTasks = listOf(createTask(1, RUNNING_APP_PACKAGE_1)),
|
||||
recentTaskPackages = listOf(RECENT_PACKAGE_1, RECENT_PACKAGE_2),
|
||||
)
|
||||
verify(mockRecentsModel, never()).getTasks(any<Consumer<List<GroupTask>>>())
|
||||
verify(mockRecentsModel, never()).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -166,6 +180,82 @@ class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
||||
verify(mockRecentsModel, times(1)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENT_TASKS_THROTTLE_BUGFIX)
|
||||
fun recentTasksChanged_duringGetTasksLoading_dontCallGetTasks() {
|
||||
// getTasks() should have been called once from init().
|
||||
verify(mockRecentsModel, times(1)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
// Override the mock answer for getTasks() so it doesn't call the callback immediately.
|
||||
doAnswer { taskListChangeId }
|
||||
.whenever(mockRecentsModel)
|
||||
.getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
// By not invoking the callback passed to getTasks() we here emulate getTasks() loading.
|
||||
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
|
||||
// getTasks() is only called two times overall (init + once more).
|
||||
verify(mockRecentsModel, times(2)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENT_TASKS_THROTTLE_BUGFIX)
|
||||
fun recentTasksChanged_duringGetTasksLoading_getTasksCalledWhenLoadingDone() {
|
||||
val callbackCaptor = argumentCaptor<Consumer<List<GroupTask>>>()
|
||||
// getTasks() should have been called once from init().
|
||||
verify(mockRecentsModel, times(1)).getTasks(any(), callbackCaptor.capture())
|
||||
// Override the mock answer for getTasks() so it doesn't call the callback immediately.
|
||||
doAnswer { taskListChangeId }
|
||||
.whenever(mockRecentsModel)
|
||||
.getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
// By not invoking the callback passed to getTasks() we here emulate getTasks() loading.
|
||||
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
callbackCaptor.lastValue.accept(emptyList())
|
||||
|
||||
// getTasks() is called again now that the first getTasks() call finished.
|
||||
verify(mockRecentsModel, times(3)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENT_TASKS_THROTTLE_BUGFIX)
|
||||
fun recentTasksChanged_duringGetTasksLoading_flagDisabled_callGetTasks() {
|
||||
// getTasks() should have been called once from init().
|
||||
verify(mockRecentsModel, times(1)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
// Override the mock answer for getTasks() so it doesn't call the callback immediately.
|
||||
doAnswer { taskListChangeId }
|
||||
.whenever(mockRecentsModel)
|
||||
.getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
// By not invoking the callback passed to getTasks() we here emulate getTasks() loading.
|
||||
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
|
||||
// getTasks() is called once per onRecentTasksChanged() invocation (and once at init)
|
||||
verify(mockRecentsModel, times(3)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENT_TASKS_THROTTLE_BUGFIX)
|
||||
fun recentTasksChanged_duringGetTasksLoading_flagDisabled_getTasksNotCalledWhenLoadingDone() {
|
||||
val callbackCaptor = argumentCaptor<Consumer<List<GroupTask>>>()
|
||||
// getTasks() should have been called once from init().
|
||||
verify(mockRecentsModel, times(1)).getTasks(any(), callbackCaptor.capture())
|
||||
// Override the mock answer for getTasks() so it doesn't call the callback immediately.
|
||||
doAnswer { taskListChangeId }
|
||||
.whenever(mockRecentsModel)
|
||||
.getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
recentTasksChangedListener?.onRecentTasksChanged()
|
||||
verify(mockRecentsModel, times(3)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
|
||||
callbackCaptor.lastValue.accept(emptyList())
|
||||
|
||||
// getTasks() is called once per onRecentTasksChanged() invocation (and once at init)
|
||||
verify(mockRecentsModel, times(3)).getTasks(any(), any<Consumer<List<GroupTask>>>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDesktopItemState_nullItemInfo_returnsNotRunning() {
|
||||
setInDesktopMode(true)
|
||||
|
||||
Reference in New Issue
Block a user