Merge "[Action Corner] Handle overview action in launcher" into main
This commit is contained in:
@@ -48,11 +48,12 @@ import com.android.launcher3.util.RunnableList
|
||||
import com.android.launcher3.util.coroutines.DispatcherProvider
|
||||
import com.android.launcher3.util.coroutines.ProductionDispatchers
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandInfo.CommandStatus
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.HIDE
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.HIDE_ALT_TAB
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.HOME
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.KEYBOARD_INPUT
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW_ALT_TAB
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.SHOW_WITH_FOCUS
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE_OVERVIEW_PREVIOUS
|
||||
import com.android.quickstep.fallback.window.RecentsWindowFlags.Companion.enableOverviewInWindow
|
||||
import com.android.quickstep.util.ActiveGestureLog
|
||||
import com.android.quickstep.util.ActiveGestureProtoLogProxy
|
||||
@@ -159,7 +160,10 @@ constructor(
|
||||
.toIntArray(),
|
||||
)
|
||||
|
||||
fun canStartHomeSafely(): Boolean = commandQueue.isEmpty() || commandQueue.first().type == HOME
|
||||
fun canStartHomeSafely(): Boolean =
|
||||
commandQueue.isEmpty() ||
|
||||
commandQueue.first().type == HOME ||
|
||||
commandQueue.first().type == TOGGLE_OVERVIEW_PREVIOUS
|
||||
|
||||
/** Clear pending or completed commands from the queue */
|
||||
fun clearPendingCommands() {
|
||||
@@ -248,9 +252,9 @@ constructor(
|
||||
onCallbackResult: () -> Unit,
|
||||
): Boolean =
|
||||
when (command.type) {
|
||||
SHOW -> true // already visible
|
||||
KEYBOARD_INPUT,
|
||||
HIDE -> {
|
||||
SHOW_WITH_FOCUS -> true // already visible
|
||||
SHOW_ALT_TAB,
|
||||
HIDE_ALT_TAB -> {
|
||||
if (recentsView.isHandlingTouch) {
|
||||
true
|
||||
} else {
|
||||
@@ -269,7 +273,15 @@ constructor(
|
||||
onCallbackResult,
|
||||
)
|
||||
}
|
||||
|
||||
TOGGLE_OVERVIEW_PREVIOUS -> {
|
||||
val taskView = recentsView.runningTaskView
|
||||
if (taskView == null) {
|
||||
recentsView.startHome()
|
||||
} else {
|
||||
taskView.launchWithAnimation()
|
||||
}
|
||||
true
|
||||
}
|
||||
HOME -> {
|
||||
recentsView.startHome()
|
||||
true
|
||||
@@ -341,7 +353,7 @@ constructor(
|
||||
}
|
||||
|
||||
when (command.type) {
|
||||
HIDE -> {
|
||||
HIDE_ALT_TAB -> {
|
||||
if (
|
||||
taskbarUIController == null ||
|
||||
!shouldShowAltTabKqs(deviceProfile, command.displayId)
|
||||
@@ -353,7 +365,7 @@ constructor(
|
||||
if (keyboardTaskFocusIndex == -1) return true
|
||||
}
|
||||
|
||||
KEYBOARD_INPUT ->
|
||||
SHOW_ALT_TAB ->
|
||||
if (
|
||||
taskbarUIController != null &&
|
||||
shouldShowAltTabKqs(deviceProfile, command.displayId)
|
||||
@@ -374,14 +386,15 @@ constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
SHOW ->
|
||||
SHOW_WITH_FOCUS ->
|
||||
// When Recents is not currently visible, the command's type is SHOW
|
||||
// when overview is triggered via the keyboard overview button or Action+Tab
|
||||
// keys (Not Alt+Tab which is KQS). The overview button on-screen in 3-button
|
||||
// nav is TYPE_TOGGLE.
|
||||
keyboardTaskFocusIndex = 0
|
||||
|
||||
TOGGLE -> {}
|
||||
TOGGLE,
|
||||
TOGGLE_OVERVIEW_PREVIOUS -> {}
|
||||
}
|
||||
|
||||
recentsView?.setKeyboardTaskFocusIndex(
|
||||
@@ -560,7 +573,11 @@ constructor(
|
||||
|
||||
private fun updateRecentsViewFocus(command: CommandInfo) {
|
||||
val recentsView: RecentsView<*, *> = getVisibleRecentsView(command.displayId) ?: return
|
||||
if (command.type != KEYBOARD_INPUT && command.type != HIDE && command.type != SHOW) {
|
||||
if (
|
||||
command.type != SHOW_ALT_TAB &&
|
||||
command.type != HIDE_ALT_TAB &&
|
||||
command.type != SHOW_WITH_FOCUS
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -581,7 +598,7 @@ constructor(
|
||||
|
||||
private fun onRecentsViewFocusUpdated(command: CommandInfo) {
|
||||
val recentsView: RecentsView<*, *> = getVisibleRecentsView(command.displayId) ?: return
|
||||
if (command.type != HIDE || keyboardTaskFocusIndex == PagedView.INVALID_PAGE) {
|
||||
if (command.type != HIDE_ALT_TAB || keyboardTaskFocusIndex == PagedView.INVALID_PAGE) {
|
||||
return
|
||||
}
|
||||
recentsView.setKeyboardTaskFocusIndex(PagedView.INVALID_PAGE)
|
||||
@@ -603,8 +620,8 @@ constructor(
|
||||
val container = containerInterface.getCreatedContainer() ?: return
|
||||
val event =
|
||||
when (command.type) {
|
||||
SHOW -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT
|
||||
HIDE -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH
|
||||
SHOW_WITH_FOCUS -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_SHORTCUT
|
||||
HIDE_ALT_TAB -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_KEYBOARD_QUICK_SWITCH
|
||||
TOGGLE -> LAUNCHER_OVERVIEW_SHOW_OVERVIEW_FROM_3_BUTTON
|
||||
else -> return
|
||||
}
|
||||
@@ -659,11 +676,17 @@ constructor(
|
||||
}
|
||||
|
||||
enum class CommandType {
|
||||
SHOW,
|
||||
KEYBOARD_INPUT,
|
||||
HIDE,
|
||||
SHOW_WITH_FOCUS,
|
||||
SHOW_ALT_TAB,
|
||||
HIDE_ALT_TAB,
|
||||
/** Toggle between overview and the next task */
|
||||
TOGGLE, // Navigate to Overview
|
||||
HOME, // Navigate to Home
|
||||
/**
|
||||
* Toggle between Overview and the previous screen before launching Overview, which can
|
||||
* either be a task or the home screen.
|
||||
*/
|
||||
TOGGLE_OVERVIEW_PREVIOUS,
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -94,6 +94,7 @@ import com.android.launcher3.util.ScreenOnTracker;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType;
|
||||
import com.android.quickstep.OverviewComponentObserver.OverviewChangeListener;
|
||||
import com.android.quickstep.actioncorner.ActionCornerHandler;
|
||||
import com.android.quickstep.fallback.window.RecentsWindowFlags;
|
||||
import com.android.quickstep.fallback.window.RecentsWindowManager;
|
||||
import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler;
|
||||
@@ -238,9 +239,9 @@ public class TouchInteractionService extends Service {
|
||||
int displayId = enableAltTabKqsOnConnectedDisplays.isTrue()
|
||||
? SystemUiProxy.INSTANCE.get(tis).getFocusState().getFocusedDisplayId()
|
||||
: DEFAULT_DISPLAY;
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.KEYBOARD_INPUT, displayId);
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW_ALT_TAB, displayId);
|
||||
} else {
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW);
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.SHOW_WITH_FOCUS);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -254,7 +255,7 @@ public class TouchInteractionService extends Service {
|
||||
int displayId = enableAltTabKqsOnConnectedDisplays.isTrue()
|
||||
? SystemUiProxy.INSTANCE.get(tis).getFocusState().getFocusedDisplayId()
|
||||
: DEFAULT_DISPLAY;
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.HIDE, displayId);
|
||||
tis.mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, displayId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -451,7 +452,13 @@ public class TouchInteractionService extends Service {
|
||||
|
||||
@Override
|
||||
public void onActionCornerActivated(int action, int displayId) {
|
||||
//TODO: b/409036363 - Handle Home and Overview action corner
|
||||
MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
|
||||
ActionCornerHandler actionCornerHandler = tis.mActionCornerHandler;
|
||||
if (actionCornerHandler == null) {
|
||||
return;
|
||||
}
|
||||
actionCornerHandler.handleAction(action, displayId);
|
||||
}));
|
||||
}
|
||||
|
||||
private void executeForTouchInteractionService(
|
||||
@@ -595,9 +602,9 @@ public class TouchInteractionService extends Service {
|
||||
@Override
|
||||
public void onHideOverview(int displayId) {
|
||||
if (enableOverviewOnConnectedDisplays()) {
|
||||
mOverviewCommandHelper.addCommand(CommandType.HIDE, displayId);
|
||||
mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, displayId);
|
||||
} else {
|
||||
mOverviewCommandHelper.addCommand(CommandType.HIDE, DEFAULT_DISPLAY);
|
||||
mOverviewCommandHelper.addCommand(CommandType.HIDE_ALT_TAB, DEFAULT_DISPLAY);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -620,6 +627,7 @@ public class TouchInteractionService extends Service {
|
||||
private InputEventReceiver mInputEventReceiver;
|
||||
|
||||
private TaskbarManager mTaskbarManager;
|
||||
private ActionCornerHandler mActionCornerHandler;
|
||||
private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
|
||||
private AllAppsActionManager mAllAppsActionManager;
|
||||
private ActiveTrackpadList mTrackpadsConnected;
|
||||
@@ -755,6 +763,7 @@ public class TouchInteractionService extends Service {
|
||||
mOverviewCommandHelper = new OverviewCommandHelper(this,
|
||||
mOverviewComponentObserver, mDisplayRepository, mTaskbarManager,
|
||||
mTaskAnimationManagerRepository);
|
||||
mActionCornerHandler = new ActionCornerHandler(mOverviewCommandHelper);
|
||||
mUserUnlocked = true;
|
||||
mInputConsumer.registerInputConsumer();
|
||||
mDeviceStateRepository.forEach(/* createIfAbsent= */ true, deviceState ->
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 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.quickstep.actioncorner
|
||||
|
||||
import com.android.quickstep.OverviewCommandHelper
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType.TOGGLE_OVERVIEW_PREVIOUS
|
||||
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.Action
|
||||
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.HOME
|
||||
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants.OVERVIEW
|
||||
|
||||
/**
|
||||
* Handles actions triggered from action corners that are mapped to specific functionalities.
|
||||
* Launcher supports both overview and home actions.
|
||||
*/
|
||||
class ActionCornerHandler(private val overviewCommandHelper: OverviewCommandHelper) {
|
||||
|
||||
fun handleAction(@Action action: Int, displayId: Int) {
|
||||
when (action) {
|
||||
// TODO(b/410798748): handle projected mode when launching overview
|
||||
OVERVIEW -> overviewCommandHelper.addCommandsForAllDisplays(TOGGLE_OVERVIEW_PREVIOUS)
|
||||
HOME -> {} // TODO(b/409036363): handle HOME action
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-7
@@ -21,12 +21,18 @@ import android.view.Display.DEFAULT_DISPLAY
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.app.displaylib.DisplayRepository
|
||||
import com.android.launcher3.Flags
|
||||
import com.android.launcher3.LauncherState
|
||||
import com.android.launcher3.statemanager.StateManager
|
||||
import com.android.launcher3.statemanager.StatefulActivity
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher
|
||||
import com.android.launcher3.util.LauncherMultivalentJUnit
|
||||
import com.android.launcher3.util.TestDispatcherProvider
|
||||
import com.android.launcher3.util.rule.setFlags
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandInfo
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandInfo.CommandStatus
|
||||
import com.android.quickstep.OverviewCommandHelper.CommandType
|
||||
import com.android.quickstep.views.RecentsView
|
||||
import com.android.quickstep.views.TaskView
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -46,6 +52,7 @@ import org.mockito.Mockito.doAnswer
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@SmallTest
|
||||
@@ -63,6 +70,10 @@ class OverviewCommandHelperTest {
|
||||
private val displayRepository: DisplayRepository = mock()
|
||||
private val executeCommandDisplayIds = mutableListOf<Int>()
|
||||
|
||||
private val recentView: RecentsView<*, *> = mock()
|
||||
private val stateManager: StateManager<LauncherState, StatefulActivity<LauncherState>> = mock()
|
||||
private val containerInterface: BaseActivityInterface<LauncherState, QuickstepLauncher> = mock()
|
||||
|
||||
private fun setupDefaultDisplay() {
|
||||
whenever(displayRepository.displayIds).thenReturn(MutableStateFlow(setOf(DEFAULT_DISPLAY)))
|
||||
}
|
||||
@@ -79,18 +90,30 @@ class OverviewCommandHelperTest {
|
||||
|
||||
setupDefaultDisplay()
|
||||
|
||||
val overviewComponentObserver = mock<OverviewComponentObserver>()
|
||||
whenever(overviewComponentObserver.getContainerInterface(any()))
|
||||
.thenReturn(containerInterface)
|
||||
whenever(recentView.getStateManager()).thenReturn(stateManager)
|
||||
whenever(containerInterface.switchToRecentsIfVisible(any())).thenReturn(true)
|
||||
|
||||
sut =
|
||||
spy(
|
||||
OverviewCommandHelper(
|
||||
touchInteractionService = mock(),
|
||||
overviewComponentObserver = mock(),
|
||||
overviewComponentObserver = overviewComponentObserver,
|
||||
dispatcherProvider = TestDispatcherProvider(dispatcher),
|
||||
displayRepository = displayRepository,
|
||||
taskbarManager = mock(),
|
||||
taskAnimationManagerRepository = mock(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun addCallbackDelay(delayInMillis: Long = 0) {
|
||||
pendingCallbacksWithDelays.add(delayInMillis)
|
||||
}
|
||||
|
||||
private fun mockExecuteCommand() {
|
||||
doAnswer { invocation ->
|
||||
val pendingCallback = invocation.arguments[1] as () -> Unit
|
||||
|
||||
@@ -111,13 +134,10 @@ class OverviewCommandHelperTest {
|
||||
.executeCommand(any<CommandInfo>(), any())
|
||||
}
|
||||
|
||||
private fun addCallbackDelay(delayInMillis: Long = 0) {
|
||||
pendingCallbacksWithDelays.add(delayInMillis)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenFirstCommandIsAdded_executeCommandImmediately() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
// Add command to queue
|
||||
val commandInfo: CommandInfo = sut.addCommand(CommandType.HOME)!!
|
||||
assertThat(commandInfo.status).isEqualTo(CommandStatus.IDLE)
|
||||
@@ -128,6 +148,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenFirstCommandIsAdded_executeCommandImmediately_WithCallbackDelay() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
addCallbackDelay(100)
|
||||
|
||||
// Add command to queue
|
||||
@@ -145,6 +166,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenFirstCommandIsPendingCallback_NextCommandWillWait() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
// Add command to queue
|
||||
addCallbackDelay(100)
|
||||
val commandType1 = CommandType.HOME
|
||||
@@ -152,7 +174,7 @@ class OverviewCommandHelperTest {
|
||||
assertThat(commandInfo1.status).isEqualTo(CommandStatus.IDLE)
|
||||
|
||||
addCallbackDelay(100)
|
||||
val commandType2 = CommandType.SHOW
|
||||
val commandType2 = CommandType.SHOW_ALT_TAB
|
||||
val commandInfo2: CommandInfo = sut.addCommand(commandType2)!!
|
||||
assertThat(commandInfo2.status).isEqualTo(CommandStatus.IDLE)
|
||||
|
||||
@@ -171,6 +193,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenCommandTakesTooLong_TriggerTimeout_AndExecuteNextCommand() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
// Add command to queue
|
||||
addCallbackDelay(QUEUE_TIMEOUT)
|
||||
val commandType1 = CommandType.HOME
|
||||
@@ -178,7 +201,7 @@ class OverviewCommandHelperTest {
|
||||
assertThat(commandInfo1.status).isEqualTo(CommandStatus.IDLE)
|
||||
|
||||
addCallbackDelay(100)
|
||||
val commandType2 = CommandType.SHOW
|
||||
val commandType2 = CommandType.SHOW_ALT_TAB
|
||||
val commandInfo2: CommandInfo = sut.addCommand(commandType2)!!
|
||||
assertThat(commandInfo2.status).isEqualTo(CommandStatus.IDLE)
|
||||
|
||||
@@ -197,6 +220,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenAllDisplaysCommandIsAdded_singleCommandProcessedForDefaultDisplay() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
executeCommandDisplayIds.clear()
|
||||
// Add command to queue
|
||||
val commandInfo: CommandInfo = sut.addCommandsForAllDisplays(CommandType.HOME)!!
|
||||
@@ -209,6 +233,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenAllDisplaysCommandIsAdded_multipleCommandsProcessedForMultipleDisplays() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
setupMultipleDisplays()
|
||||
executeCommandDisplayIds.clear()
|
||||
// Add command to queue
|
||||
@@ -223,6 +248,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenAllExceptDisplayCommandIsAdded_otherDisplayProcessed() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
setupMultipleDisplays()
|
||||
executeCommandDisplayIds.clear()
|
||||
// Add command to queue
|
||||
@@ -237,6 +263,7 @@ class OverviewCommandHelperTest {
|
||||
@Test
|
||||
fun whenSingleDisplayCommandIsAdded_thatDisplayIsProcessed() =
|
||||
testScope.runTest {
|
||||
mockExecuteCommand()
|
||||
executeCommandDisplayIds.clear()
|
||||
val displayId = 5
|
||||
// Add command to queue
|
||||
@@ -247,6 +274,39 @@ class OverviewCommandHelperTest {
|
||||
assertThat(executeCommandDisplayIds).containsExactly(displayId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun recentViewNotVisible_toggleOverviewPrev_goToOverview() =
|
||||
testScope.runTest {
|
||||
whenever(containerInterface.getVisibleRecentsView<RecentsView<*, *>>()).thenReturn(null)
|
||||
sut.addCommand(CommandType.TOGGLE_OVERVIEW_PREVIOUS)!!
|
||||
runCurrent()
|
||||
verify(containerInterface).switchToRecentsIfVisible(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun recentViewVisible_toggleOverviewPrev_goToHome() =
|
||||
testScope.runTest {
|
||||
whenever(containerInterface.getVisibleRecentsView<RecentsView<*, *>>())
|
||||
.thenReturn(recentView)
|
||||
sut.addCommand(CommandType.TOGGLE_OVERVIEW_PREVIOUS)!!
|
||||
runCurrent()
|
||||
verify(recentView).startHome()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun recentViewVisible_hasRunningTask_toggleOverviewPrev_goToPrevTask() =
|
||||
testScope.runTest {
|
||||
whenever(containerInterface.getVisibleRecentsView<RecentsView<*, *>>())
|
||||
.thenReturn(recentView)
|
||||
val mockTask = mock<TaskView>()
|
||||
whenever(recentView.runningTaskView).thenReturn(mockTask)
|
||||
|
||||
sut.addCommand(CommandType.TOGGLE_OVERVIEW_PREVIOUS)!!
|
||||
runCurrent()
|
||||
|
||||
verify(mockTask).launchWithAnimation()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val QUEUE_TIMEOUT = 5001L
|
||||
const val EXTERNAL_DISPLAY_ID = 1
|
||||
|
||||
Reference in New Issue
Block a user