diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 336ea61c23..d42d9ede6b 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -101,6 +101,7 @@ import com.android.quickstep.fallback.window.RecentsWindowFlags; import com.android.quickstep.fallback.window.RecentsWindowManager; import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler; import com.android.quickstep.input.QuickstepKeyGestureEventsManager; +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler; import com.android.quickstep.inputconsumers.BubbleBarInputConsumer; import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer; import com.android.quickstep.util.ActiveGestureLog; @@ -781,6 +782,8 @@ public class TouchInteractionService extends Service { onOverviewTargetChanged(mOverviewComponentObserver.isHomeAndOverviewSame()); mTaskbarManager.onUserUnlocked(); + mQuickstepKeyGestureEventsHandler.registerOverviewKeyGestureEvent( + createOverviewGestureHandler()); } public OverviewCommandHelper getOverviewCommandHelper() { @@ -857,6 +860,7 @@ public class TouchInteractionService extends Service { + " instance=" + System.identityHashCode(this)); if (LockedUserState.get(this).isUserUnlocked()) { mInputConsumer.unregisterInputConsumer(); + mQuickstepKeyGestureEventsHandler.onDestroy(); mOverviewComponentObserver.setHomeDisabled(false); mOverviewComponentObserver.removeOverviewChangeListener(mOverviewChangeListener); } @@ -1373,6 +1377,22 @@ public class TouchInteractionService extends Service { } + private OverviewGestureHandler createOverviewGestureHandler() { + return new OverviewGestureHandler() { + @Override + public void showOverview(@NonNull OverviewType type) { + mTISBinder.onOverviewShown(/* triggeredFromAltTab= */ type == OverviewType.ALT_TAB); + } + + @Override + public void hideOverview(@NonNull OverviewType type) { + mTISBinder.onOverviewHidden( + /* triggeredFromAltTab= */ type == OverviewType.ALT_TAB, + /* triggeredFromHomeKey= */ type == OverviewType.HOME); + } + }; + } + /** * Helper class that keeps track of external displays and prepares input monitors for each. */ diff --git a/quickstep/src/com/android/quickstep/input/QuickstepKeyGestureEventsManager.kt b/quickstep/src/com/android/quickstep/input/QuickstepKeyGestureEventsManager.kt index d5120985ee..6087cf4af2 100644 --- a/quickstep/src/com/android/quickstep/input/QuickstepKeyGestureEventsManager.kt +++ b/quickstep/src/com/android/quickstep/input/QuickstepKeyGestureEventsManager.kt @@ -21,9 +21,20 @@ import android.content.Context import android.hardware.input.InputManager import android.hardware.input.InputManager.KeyGestureEventHandler import android.hardware.input.KeyGestureEvent +import android.hardware.input.KeyGestureEvent.ACTION_GESTURE_COMPLETE +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER +import android.net.Uri import android.os.IBinder +import android.provider.Settings +import android.provider.Settings.Secure.USER_SETUP_COMPLETE import android.util.Log import androidx.annotation.VisibleForTesting +import com.android.launcher3.util.SettingsCache +import com.android.launcher3.util.SettingsCache.OnChangeListener +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler.OverviewType.ALT_TAB +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler.OverviewType.UNDEFINED import com.android.window.flags.Flags /** @@ -31,8 +42,19 @@ import com.android.window.flags.Flags * recents (incl. alt + tab). */ class QuickstepKeyGestureEventsManager(context: Context) { + private val settingsCache = SettingsCache.INSTANCE[context] + @VisibleForTesting + val onUserSetupCompleteListener = OnChangeListener { isUserSetupCompleted = it } private val inputManager = requireNotNull(context.getSystemService(InputManager::class.java)) private var allAppsPendingIntent: PendingIntent? = null + private var overviewGestureHandler: OverviewGestureHandler? = null + private var isUserSetupCompleted: Boolean = + settingsCache.getValue(USER_SETUP_COMPLETE_URI, /* defaultValue= */ 0) + + init { + settingsCache.register(USER_SETUP_COMPLETE_URI, onUserSetupCompleteListener) + } + @VisibleForTesting val allAppsKeyGestureEventHandler = object : KeyGestureEventHandler { @@ -40,7 +62,11 @@ class QuickstepKeyGestureEventsManager(context: Context) { if (!Flags.enableKeyGestureHandlerForRecents()) { return } - if (event.keyGestureType != KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS) { + if (!isUserSetupCompleted) { + return + } + + if (event.keyGestureType != KEY_GESTURE_TYPE_ALL_APPS) { Log.e(TAG, "Ignore unsupported key gesture event type: ${event.keyGestureType}") return } @@ -50,13 +76,48 @@ class QuickstepKeyGestureEventsManager(context: Context) { allAppsPendingIntent?.send() } } + @VisibleForTesting + val overviewKeyGestureEventHandler = + object : KeyGestureEventHandler { + override fun handleKeyGestureEvent(event: KeyGestureEvent, focusedToken: IBinder?) { + if (!Flags.enableKeyGestureHandlerForRecents()) { + return + } + if (!isUserSetupCompleted) { + return + } + + val handler = overviewGestureHandler ?: return + when (event.keyGestureType) { + KEY_GESTURE_TYPE_RECENT_APPS -> { + if (event.action == ACTION_GESTURE_COMPLETE && !event.isCancelled) { + handler.showOverview(UNDEFINED) + } + } + KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER -> { + if (event.action == KeyGestureEvent.ACTION_GESTURE_START) { + handler.showOverview(ALT_TAB) + } else { + handler.hideOverview(ALT_TAB) + } + } + else -> { + Log.e( + TAG, + "Ignore unsupported overview key gesture event type: " + + event.keyGestureType, + ) + } + } + } + } /** Registers the all apps key gesture events. */ fun registerAllAppsKeyGestureEvent(allAppsPendingIntent: PendingIntent) { if (Flags.enableKeyGestureHandlerForRecents()) { this.allAppsPendingIntent = allAppsPendingIntent inputManager.registerKeyGestureEventHandler( - listOf(KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS), + listOf(KEY_GESTURE_TYPE_ALL_APPS), allAppsKeyGestureEventHandler, ) } @@ -69,7 +130,47 @@ class QuickstepKeyGestureEventsManager(context: Context) { } } + /** Registers the overview key gesture events. */ + fun registerOverviewKeyGestureEvent(overviewGestureHandler: OverviewGestureHandler) { + if (Flags.enableKeyGestureHandlerForRecents()) { + this.overviewGestureHandler = overviewGestureHandler + inputManager.registerKeyGestureEventHandler( + listOf(KEY_GESTURE_TYPE_RECENT_APPS, KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER), + overviewKeyGestureEventHandler, + ) + } + } + + /** Unregisters the overview key gesture events. */ + fun unregisterOverviewKeyGestureEvent() { + if (Flags.enableKeyGestureHandlerForRecents()) { + inputManager.unregisterKeyGestureEventHandler(overviewKeyGestureEventHandler) + } + } + + fun onDestroy() { + settingsCache.unregister(USER_SETUP_COMPLETE_URI, onUserSetupCompleteListener) + unregisterOverviewKeyGestureEvent() + unregisterAllAppsKeyGestureEvent() + } + + /** Callbacks for overview events, including alt + tab. */ + interface OverviewGestureHandler { + enum class OverviewType { + UNDEFINED, + ALT_TAB, + HOME, + } + + /** Shows the overview UI with [type]. */ + fun showOverview(type: OverviewType) + + /** Hides the overview UI with [type]. */ + fun hideOverview(type: OverviewType) + } + private companion object { const val TAG = "KeyGestureEventsHandler" + val USER_SETUP_COMPLETE_URI: Uri = Settings.Secure.getUriFor(USER_SETUP_COMPLETE) } } diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt index a37655186e..b9e52092c6 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt @@ -60,7 +60,8 @@ class AllAppsActionManagerTest { private val settingsCacheSandbox = SettingsCacheSandbox().also { it[USER_SETUP_COMPLETE_URI] = 1 } - private val quickstepKeyGestureEventsManager = spy(QuickstepKeyGestureEventsManager(context)) + private val quickstepKeyGestureEventsManager by + lazy(LazyThreadSafetyMode.NONE) { spy(QuickstepKeyGestureEventsManager(context)) } private val allAppsActionManager by lazy(LazyThreadSafetyMode.NONE) { diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/input/QuickstepKeyGestureEventsHandlerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/input/QuickstepKeyGestureEventsHandlerTest.kt index b7622a0759..a8a9194257 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/input/QuickstepKeyGestureEventsHandlerTest.kt +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/input/QuickstepKeyGestureEventsHandlerTest.kt @@ -19,13 +19,22 @@ package com.android.quickstep.input import android.app.PendingIntent import android.hardware.input.InputManager import android.hardware.input.KeyGestureEvent +import android.hardware.input.KeyGestureEvent.ACTION_GESTURE_COMPLETE +import android.hardware.input.KeyGestureEvent.ACTION_GESTURE_START import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS +import android.hardware.input.KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.SetFlagsRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.launcher3.util.SandboxApplication +import com.android.quickstep.input.QuickstepKeyGestureEventsHandlerTest.FakeOverviewHandler.OverviewEvent +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler.OverviewType +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler.OverviewType.ALT_TAB +import com.android.quickstep.input.QuickstepKeyGestureEventsManager.OverviewGestureHandler.OverviewType.UNDEFINED import com.android.window.flags.Flags import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -50,19 +59,22 @@ class QuickstepKeyGestureEventsHandlerTest { @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT) private val inputManager = context.spyService(InputManager::class.java) - private val keyGestureEventsManager = QuickstepKeyGestureEventsManager(context) private val allAppsPendingIntent: PendingIntent = mock() private val keyGestureEventsCaptor: KArgumentCaptor> = argumentCaptor() + private val fakeOverviewHandler = FakeOverviewHandler() + private lateinit var keyGestureEventsManager: QuickstepKeyGestureEventsManager @Before fun setup() { doNothing().whenever(inputManager).registerKeyGestureEventHandler(any(), any()) doNothing().whenever(inputManager).unregisterKeyGestureEventHandler(any()) + keyGestureEventsManager = QuickstepKeyGestureEventsManager(context) + keyGestureEventsManager.onUserSetupCompleteListener.onSettingsChanged(/* isEnabled= */ true) } @Test @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun registerKeyGestureEventsHandler_flagEnabled_registerWithExpectedKeyGestureEvents() { + fun registerAllAppsHandler_flagEnabled_registerWithExpectedKeyGestureEvents() { keyGestureEventsManager.registerAllAppsKeyGestureEvent(allAppsPendingIntent) verify(inputManager) @@ -75,7 +87,7 @@ class QuickstepKeyGestureEventsHandlerTest { @Test @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun registerKeyGestureEventsHandler_flagDisabled_noRegister() { + fun registerAllAppsHandler_flagDisabled_noRegister() { keyGestureEventsManager.registerAllAppsKeyGestureEvent(allAppsPendingIntent) verifyNoInteractions(inputManager) @@ -83,7 +95,29 @@ class QuickstepKeyGestureEventsHandlerTest { @Test @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun unregisterKeyGestureEventsHandler_flagEnabled_unregisterHandler() { + fun registerOverviewHandler_flagEnabled_registerWithExpectedKeyGestureEvents() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + verify(inputManager) + .registerKeyGestureEventHandler( + keyGestureEventsCaptor.capture(), + eq(keyGestureEventsManager.overviewKeyGestureEventHandler), + ) + assertThat(keyGestureEventsCaptor.firstValue) + .containsExactly(KEY_GESTURE_TYPE_RECENT_APPS, KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun registerOverviewHandler_flagDisabled_noRegister() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + verifyNoInteractions(inputManager) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun unregisterAllAppsHandler_flagEnabled_unregisterHandler() { keyGestureEventsManager.unregisterAllAppsKeyGestureEvent() verify(inputManager) @@ -94,7 +128,7 @@ class QuickstepKeyGestureEventsHandlerTest { @Test @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun unregisterKeyGestureEventsHandler_flagDisabled_noUnregister() { + fun unregisterAllAppsHandler_flagDisabled_noUnregister() { keyGestureEventsManager.unregisterAllAppsKeyGestureEvent() verifyNoInteractions(inputManager) @@ -102,7 +136,26 @@ class QuickstepKeyGestureEventsHandlerTest { @Test @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun handleEvent_flagEnabled_allApps_toggleAllAppsSearch() { + fun unregisterOverviewHandler_flagEnabled_unregisterHandler() { + keyGestureEventsManager.unregisterOverviewKeyGestureEvent() + + verify(inputManager) + .unregisterKeyGestureEventHandler( + eq(keyGestureEventsManager.overviewKeyGestureEventHandler) + ) + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun unregisterOverviewHandler_flagDisabled_noUnregister() { + keyGestureEventsManager.unregisterOverviewKeyGestureEvent() + + verifyNoInteractions(inputManager) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleAllAppsEvent_flagEnabled_toggleAllAppsSearch() { keyGestureEventsManager.registerAllAppsKeyGestureEvent(allAppsPendingIntent) keyGestureEventsManager.allAppsKeyGestureEventHandler.handleKeyGestureEvent( @@ -117,8 +170,11 @@ class QuickstepKeyGestureEventsHandlerTest { } @Test - @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) - fun handleEvent_flagDisabled_allApps_noInteractionWithTaskbar() { + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleAllAppsEvent_flagEnabled_userSetupIncomplete_noInteractionWithTaskbar() { + keyGestureEventsManager.onUserSetupCompleteListener.onSettingsChanged( + /* isEnabled= */ false + ) keyGestureEventsManager.registerAllAppsKeyGestureEvent(allAppsPendingIntent) keyGestureEventsManager.allAppsKeyGestureEventHandler.handleKeyGestureEvent( @@ -132,6 +188,202 @@ class QuickstepKeyGestureEventsHandlerTest { verifyNoInteractions(allAppsPendingIntent) } + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleAllAppsEvent_flagDisabled_noInteractionWithTaskbar() { + keyGestureEventsManager.registerAllAppsKeyGestureEvent(allAppsPendingIntent) + + keyGestureEventsManager.allAppsKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_ALL_APPS) + .build(), + /* focusedToken= */ null, + ) + + verifyNoInteractions(allAppsPendingIntent) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsEvent_flagEnabled_showOverviewWithUndefinedType() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent) + .isEqualTo(OverviewEvent(shouldShowOverview = true, type = UNDEFINED)) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsEvent_userSetupIncomplete_noOverviewEventInFake() { + keyGestureEventsManager.onUserSetupCompleteListener.onSettingsChanged( + /* isEnabled= */ false + ) + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsEvent_flagDisabled_noOverviewEventInFake() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherStartEvent_flagEnabled_showOverviewWithAltTabType() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_START) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent) + .isEqualTo(OverviewEvent(shouldShowOverview = true, type = ALT_TAB)) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherStartEvent_userSetupIncomplete_noOverviewEventInFake() { + keyGestureEventsManager.onUserSetupCompleteListener.onSettingsChanged( + /* isEnabled= */ false + ) + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_START) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherStartEvent_flagDisabled_noOverviewEventInFake() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_START) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherCompleteEvent_flagEnabled_hideOverviewWithAltTabType() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent) + .isEqualTo(OverviewEvent(shouldShowOverview = false, type = ALT_TAB)) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherCompleteEvent_userSetupIncomplete_noOverviewEventInFake() { + keyGestureEventsManager.onUserSetupCompleteListener.onSettingsChanged( + /* isEnabled= */ false + ) + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + @Test + @DisableFlags(Flags.FLAG_ENABLE_KEY_GESTURE_HANDLER_FOR_RECENTS) + fun handleRecentAppsSwitcherCompleteEvent_flagDisabled_noOverviewEventInFake() { + keyGestureEventsManager.registerOverviewKeyGestureEvent(fakeOverviewHandler) + + keyGestureEventsManager.overviewKeyGestureEventHandler.handleKeyGestureEvent( + KeyGestureEvent.Builder() + .setDisplayId(TEST_DISPLAY_ID) + .setKeyGestureType(KEY_GESTURE_TYPE_RECENT_APPS_SWITCHER) + .setAction(ACTION_GESTURE_COMPLETE) + .build(), + /* focusedToken= */ null, + ) + + assertThat(fakeOverviewHandler.overviewEvent).isNull() + } + + private class FakeOverviewHandler : OverviewGestureHandler { + data class OverviewEvent(val shouldShowOverview: Boolean, val type: OverviewType) + + var overviewEvent: OverviewEvent? = null + private set + + override fun showOverview(type: OverviewType) { + overviewEvent = OverviewEvent(shouldShowOverview = true, type) + } + + override fun hideOverview(type: OverviewType) { + overviewEvent = OverviewEvent(shouldShowOverview = false, type) + } + } + private companion object { const val TEST_DISPLAY_ID = 6789 }