Refactor InputConsumer selection logic into a util class

This will allow us to test the logic in isolation

Flag: EXEMPT refactor
Bug: 371020209
Test: NONE refactor
Change-Id: I5e1e9cc79e69db261ea28a2f7d43a983339f178b
This commit is contained in:
Schneider Victor-Tulias
2024-11-14 13:29:19 -05:00
parent e7b134f6ce
commit cfce474121
3 changed files with 770 additions and 422 deletions
@@ -274,7 +274,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
* @return the interface to the activity handing the UI updates for this gesture.
*/
public <S extends BaseState<S>, T extends RecentsViewContainer & StatefulContainer<S>>
BaseContainerInterface getContainerInterface() {
BaseContainerInterface<S, T> getContainerInterface() {
return mContainerInterface;
}
@@ -0,0 +1,746 @@
/*
* Copyright (C) 2024 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
import android.content.Context
import android.view.MotionEvent
import androidx.annotation.VisibleForTesting
import com.android.launcher3.anim.AnimatedFloat
import com.android.launcher3.statemanager.BaseState
import com.android.launcher3.statemanager.StatefulContainer
import com.android.launcher3.taskbar.TaskbarManager
import com.android.launcher3.util.LockedUserState.Companion.get
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer
import com.android.quickstep.inputconsumers.AssistantInputConsumer
import com.android.quickstep.inputconsumers.BubbleBarInputConsumer
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer
import com.android.quickstep.inputconsumers.NavHandleLongPressInputConsumer
import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer
import com.android.quickstep.inputconsumers.OverviewInputConsumer
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer
import com.android.quickstep.inputconsumers.ProgressDelegateInputConsumer
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer
import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer
import com.android.quickstep.inputconsumers.TrackpadStatusBarInputConsumer
import com.android.quickstep.util.ActiveGestureErrorDetector
import com.android.quickstep.util.ActiveGestureLog
import com.android.quickstep.util.ActiveGestureLog.CompoundString
import com.android.quickstep.util.ActiveGestureProtoLogProxy
import com.android.quickstep.views.RecentsViewContainer
import com.android.systemui.shared.system.InputChannelCompat
import com.android.systemui.shared.system.InputMonitorCompat
import com.android.wm.shell.Flags
import java.util.function.Consumer
import java.util.function.Function
/** Utility class for creating input consumers. */
object InputConsumerUtils {
private const val SUBSTRING_PREFIX = "; "
private const val NEWLINE_PREFIX = "\n\t\t\t-> "
@JvmStatic
fun <S : BaseState<S>, T> newConsumer(
baseContext: Context,
tisContext: Context,
resetGestureInputConsumer: ResetGestureInputConsumer?,
overviewComponentObserver: OverviewComponentObserver,
deviceState: RecentsAnimationDeviceState,
previousGestureState: GestureState,
gestureState: GestureState,
taskAnimationManager: TaskAnimationManager,
inputMonitorCompat: InputMonitorCompat,
swipeUpHandlerFactory: AbsSwipeUpHandler.Factory,
onCompleteCallback: Consumer<OtherActivityInputConsumer>,
inputEventReceiver: InputChannelCompat.InputEventReceiver,
taskbarManager: TaskbarManager,
swipeUpProxyProvider: Function<GestureState?, AnimatedFloat?>,
overviewCommandHelper: OverviewCommandHelper,
event: MotionEvent,
): InputConsumer where T : RecentsViewContainer, T : StatefulContainer<S> {
val tac = taskbarManager.currentActivityContext
val bubbleControllers = tac?.bubbleControllers
if (bubbleControllers != null && BubbleBarInputConsumer.isEventOnBubbles(tac, event)) {
val consumer: InputConsumer =
BubbleBarInputConsumer(tisContext, bubbleControllers, inputMonitorCompat)
logInputConsumerSelectionReason(
consumer,
newCompoundString("event is on bubbles, creating new input consumer"),
)
return consumer
}
val progressProxy = swipeUpProxyProvider.apply(gestureState)
if (progressProxy != null) {
val consumer: InputConsumer =
ProgressDelegateInputConsumer(
tisContext,
taskAnimationManager,
gestureState,
inputMonitorCompat,
progressProxy,
)
logInputConsumerSelectionReason(
consumer,
newCompoundString(
"mSwipeUpProxyProvider has been set, using ProgressDelegateInputConsumer"
),
)
return consumer
}
val canStartSystemGesture =
if (gestureState.isTrackpadGesture) deviceState.canStartTrackpadGesture()
else deviceState.canStartSystemGesture()
if (!get(tisContext).isUserUnlocked) {
val reasonString = newCompoundString("device locked")
val consumer =
if (canStartSystemGesture) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g.
// camera).
createDeviceLockedInputConsumer(
tisContext,
resetGestureInputConsumer,
deviceState,
gestureState,
taskAnimationManager,
inputMonitorCompat,
reasonString.append("%scan start system gesture", SUBSTRING_PREFIX),
)
} else {
getDefaultInputConsumer(
resetGestureInputConsumer,
reasonString.append("%scannot start system gesture", SUBSTRING_PREFIX),
)
}
logInputConsumerSelectionReason(consumer, reasonString)
return consumer
}
var reasonString: CompoundString
var base: InputConsumer
// When there is an existing recents animation running, bypass systemState check as this is
// a followup gesture and the first gesture started in a valid system state.
if (canStartSystemGesture || previousGestureState.isRecentsAnimationRunning) {
reasonString =
newCompoundString(
if (canStartSystemGesture)
"can start system gesture, trying to use base consumer"
else "recents animation was running, trying to use base consumer"
)
base =
newBaseConsumer<S, T>(
tisContext,
resetGestureInputConsumer,
overviewComponentObserver,
deviceState,
previousGestureState,
gestureState,
taskAnimationManager,
inputMonitorCompat,
swipeUpHandlerFactory,
onCompleteCallback,
inputEventReceiver,
event,
reasonString,
)
} else {
reasonString =
newCompoundString(
"cannot start system gesture and recents " +
"animation was not running, trying to use default input consumer"
)
base = getDefaultInputConsumer(resetGestureInputConsumer, reasonString)
}
if (deviceState.isGesturalNavMode || gestureState.isTrackpadGesture) {
handleOrientationSetup(base)
}
if (deviceState.isFullyGesturalNavMode || gestureState.isTrackpadGesture) {
val reasonPrefix =
"device is in gesture navigation mode or 3-button mode with a trackpad gesture"
if (deviceState.canTriggerAssistantAction(event)) {
reasonString.append(
"%s%s%sgesture can trigger the assistant, " +
"trying to use assistant input consumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
base =
tryCreateAssistantInputConsumer(
tisContext,
deviceState,
inputMonitorCompat,
base,
gestureState,
event,
reasonString,
)
}
// If Taskbar is present, we listen for swipe or cursor hover events to unstash it.
if (tac != null && base !is AssistantInputConsumer) {
// Present always on large screen or on small screen w/ flag
val useTaskbarConsumer =
(tac.deviceProfile.isTaskbarPresent &&
!tac.isPhoneMode &&
!tac.isInStashedLauncherState)
if (canStartSystemGesture && useTaskbarConsumer) {
reasonString.append(
"%s%s%sTaskbarActivityContext != null, " +
"using TaskbarUnstashInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
base =
TaskbarUnstashInputConsumer(
tisContext,
base,
inputMonitorCompat,
tac,
overviewCommandHelper,
gestureState,
)
}
}
if (Flags.enableBubblesLongPressNavHandle()) {
// Create bubbles input consumer before NavHandleLongPressInputConsumer.
// This allows for nav handle to fall back to bubbles.
if (deviceState.isBubblesExpanded) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%sbubbles expanded, trying to use default input consumer",
SUBSTRING_PREFIX,
)
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(resetGestureInputConsumer, reasonString)
}
}
val navHandle = tac?.navHandle ?: SystemUiProxy.INSTANCE[tisContext]
if (
canStartSystemGesture &&
!previousGestureState.isRecentsAnimationRunning &&
navHandle.canNavHandleBeLongPressed() &&
!ignoreThreeFingerTrackpadForNavHandleLongPress(gestureState)
) {
reasonString.append(
"%s%s%sNot running recents animation, ",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
if (tac != null && tac.navHandle.canNavHandleBeLongPressed()) {
reasonString.append("stashed handle is long-pressable, ")
}
reasonString.append("using NavHandleLongPressInputConsumer")
base =
NavHandleLongPressInputConsumer(
tisContext,
base,
inputMonitorCompat,
deviceState,
navHandle,
gestureState,
)
}
if (!Flags.enableBubblesLongPressNavHandle()) {
// Continue overriding nav handle input consumer with bubbles
if (deviceState.isBubblesExpanded) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%sbubbles expanded, trying to use default input consumer",
SUBSTRING_PREFIX,
)
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(resetGestureInputConsumer, reasonString)
}
}
if (deviceState.isSystemUiDialogShowing) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%ssystem dialog is showing, using SysUiOverlayInputConsumer",
SUBSTRING_PREFIX,
)
base = SysUiOverlayInputConsumer(baseContext, deviceState, inputMonitorCompat)
}
if (
gestureState.isTrackpadGesture &&
canStartSystemGesture &&
!previousGestureState.isRecentsAnimationRunning
) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%sTrackpad 3-finger gesture, using TrackpadStatusBarInputConsumer",
SUBSTRING_PREFIX,
)
base = TrackpadStatusBarInputConsumer(baseContext, base, inputMonitorCompat)
}
if (deviceState.isScreenPinningActive) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%sscreen pinning is active, using ScreenPinnedInputConsumer",
SUBSTRING_PREFIX,
)
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
base = ScreenPinnedInputConsumer(tisContext, gestureState)
}
if (deviceState.canTriggerOneHandedAction(event)) {
reasonString.append(
"%s%s%sgesture can trigger one handed mode, " +
"using OneHandedModeInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
base = OneHandedModeInputConsumer(tisContext, deviceState, base, inputMonitorCompat)
}
if (deviceState.isAccessibilityMenuAvailable) {
reasonString.append(
"%s%s%saccessibility menu is available, using AccessibilityInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
base =
AccessibilityInputConsumer(
tisContext,
deviceState,
gestureState,
base,
inputMonitorCompat,
)
}
} else {
val reasonPrefix = "device is not in gesture navigation mode"
if (deviceState.isScreenPinningActive) {
reasonString =
newCompoundString(reasonPrefix)
.append(
"%sscreen pinning is active, trying to use default input consumer",
SUBSTRING_PREFIX,
)
base = getDefaultInputConsumer(resetGestureInputConsumer, reasonString)
}
if (deviceState.canTriggerOneHandedAction(event)) {
reasonString.append(
"%s%s%sgesture can trigger one handed mode, " +
"using OneHandedModeInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX,
)
base = OneHandedModeInputConsumer(tisContext, deviceState, base, inputMonitorCompat)
}
}
logInputConsumerSelectionReason(base, reasonString)
return base
}
@JvmStatic
fun tryCreateAssistantInputConsumer(
context: Context,
deviceState: RecentsAnimationDeviceState,
inputMonitorCompat: InputMonitorCompat,
gestureState: GestureState,
motionEvent: MotionEvent,
): InputConsumer {
return tryCreateAssistantInputConsumer(
context,
deviceState,
inputMonitorCompat,
InputConsumer.NO_OP,
gestureState,
motionEvent,
CompoundString.NO_OP,
)
}
private fun tryCreateAssistantInputConsumer(
context: Context,
deviceState: RecentsAnimationDeviceState,
inputMonitorCompat: InputMonitorCompat,
base: InputConsumer,
gestureState: GestureState,
motionEvent: MotionEvent,
reasonString: CompoundString,
): InputConsumer {
return if (deviceState.isGestureBlockedTask(gestureState.runningTask)) {
reasonString.append(
"%sis gesture-blocked task, using base input consumer",
SUBSTRING_PREFIX,
)
base
} else {
reasonString.append("%susing AssistantInputConsumer", SUBSTRING_PREFIX)
AssistantInputConsumer(
context,
gestureState,
base,
inputMonitorCompat,
deviceState,
motionEvent,
)
}
}
@VisibleForTesting
@JvmStatic
fun <S : BaseState<S>, T> newBaseConsumer(
context: Context,
resetGestureInputConsumer: ResetGestureInputConsumer?,
overviewComponentObserver: OverviewComponentObserver,
deviceState: RecentsAnimationDeviceState,
previousGestureState: GestureState,
gestureState: GestureState,
taskAnimationManager: TaskAnimationManager,
inputMonitorCompat: InputMonitorCompat,
swipeUpHandlerFactory: AbsSwipeUpHandler.Factory,
onCompleteCallback: Consumer<OtherActivityInputConsumer>,
inputEventReceiver: InputChannelCompat.InputEventReceiver,
event: MotionEvent,
reasonString: CompoundString,
): InputConsumer where T : RecentsViewContainer, T : StatefulContainer<S> {
if (deviceState.isKeyguardShowingOccluded) {
// This handles apps showing over the lockscreen (e.g. camera)
return createDeviceLockedInputConsumer(
context,
resetGestureInputConsumer,
deviceState,
gestureState,
taskAnimationManager,
inputMonitorCompat,
reasonString.append(
"%skeyguard is showing occluded, " +
"trying to use device locked input consumer",
SUBSTRING_PREFIX,
),
)
}
reasonString.append("%skeyguard is not showing occluded", SUBSTRING_PREFIX)
val runningTask = gestureState.runningTask
// Use overview input consumer for sharesheets on top of home.
val forceOverviewInputConsumer =
gestureState.getContainerInterface<S, T>().isStarted() &&
runningTask != null &&
runningTask.isRootChooseActivity
if (!Flags.enableShellTopTaskTracking()) {
// In the case where we are in an excluded, translucent overlay, ignore it and treat the
// running activity as the task behind the overlay.
val otherVisibleTask = runningTask?.visibleNonExcludedTask
if (otherVisibleTask != null) {
ActiveGestureProtoLogProxy.logUpdateGestureStateRunningTask(
otherVisibleTask.packageName ?: "MISSING",
runningTask.packageName ?: "MISSING",
)
gestureState.updateRunningTask(otherVisibleTask)
}
}
val previousGestureAnimatedToLauncher =
(previousGestureState.isRunningAnimationToLauncher ||
deviceState.isPredictiveBackToHomeInProgress)
// with shell-transitions, home is resumed during recents animation, so
// explicitly check against recents animation too.
val launcherResumedThroughShellTransition =
(gestureState.getContainerInterface<S, T>().isResumed() &&
!previousGestureState.isRecentsAnimationRunning)
// If a task fragment within Launcher is resumed
val launcherChildActivityResumed =
(com.android.launcher3.Flags.useActivityOverlay() &&
runningTask != null &&
runningTask.isHomeTask &&
overviewComponentObserver.isHomeAndOverviewSame &&
!launcherResumedThroughShellTransition &&
!previousGestureState.isRecentsAnimationRunning)
return if (gestureState.getContainerInterface<S, T>().isInLiveTileMode()) {
createOverviewInputConsumer<S, T>(
resetGestureInputConsumer,
deviceState,
inputMonitorCompat,
previousGestureState,
gestureState,
event,
reasonString.append(
"%sis in live tile mode, trying to use overview input consumer",
SUBSTRING_PREFIX,
),
)
} else if (runningTask == null) {
getDefaultInputConsumer(
resetGestureInputConsumer,
reasonString.append("%srunning task == null", SUBSTRING_PREFIX),
)
} else if (
previousGestureAnimatedToLauncher ||
launcherResumedThroughShellTransition ||
forceOverviewInputConsumer
) {
createOverviewInputConsumer<S, T>(
resetGestureInputConsumer,
deviceState,
inputMonitorCompat,
previousGestureState,
gestureState,
event,
reasonString.append(
if (previousGestureAnimatedToLauncher)
("%sprevious gesture animated to launcher, " +
"trying to use overview input consumer")
else
(if (launcherResumedThroughShellTransition)
("%slauncher resumed through a shell transition, " +
"trying to use overview input consumer")
else
("%sforceOverviewInputConsumer == true, " +
"trying to use overview input consumer")),
SUBSTRING_PREFIX,
),
)
} else if (deviceState.isGestureBlockedTask(runningTask) || launcherChildActivityResumed) {
getDefaultInputConsumer(
resetGestureInputConsumer,
reasonString.append(
if (launcherChildActivityResumed)
"%sis launcher child-task, trying to use default input consumer"
else "%sis gesture-blocked task, trying to use default input consumer",
SUBSTRING_PREFIX,
),
)
} else {
reasonString.append("%susing OtherActivityInputConsumer", SUBSTRING_PREFIX)
createOtherActivityInputConsumer<S, T>(
context,
swipeUpHandlerFactory,
overviewComponentObserver,
deviceState,
taskAnimationManager,
inputMonitorCompat,
onCompleteCallback,
inputEventReceiver,
gestureState,
event,
)
}
}
private fun createDeviceLockedInputConsumer(
context: Context,
resetGestureInputConsumer: ResetGestureInputConsumer?,
deviceState: RecentsAnimationDeviceState,
gestureState: GestureState,
taskAnimationManager: TaskAnimationManager,
inputMonitorCompat: InputMonitorCompat,
reasonString: CompoundString,
): InputConsumer {
return if (
(deviceState.isFullyGesturalNavMode || gestureState.isTrackpadGesture) &&
gestureState.runningTask != null
) {
reasonString.append(
"%sdevice is in gesture nav mode or 3-button mode with a trackpad " +
"gesture and running task != null, using DeviceLockedInputConsumer",
SUBSTRING_PREFIX,
)
DeviceLockedInputConsumer(
context,
deviceState,
taskAnimationManager,
gestureState,
inputMonitorCompat,
)
} else {
getDefaultInputConsumer(
resetGestureInputConsumer,
reasonString.append(
if (deviceState.isFullyGesturalNavMode || gestureState.isTrackpadGesture)
"%srunning task == null, trying to use default input consumer"
else
("%sdevice is not in gesture nav mode and it's not a trackpad gesture," +
" trying to use default input consumer"),
SUBSTRING_PREFIX,
),
)
}
}
private fun <S : BaseState<S>, T> createOverviewInputConsumer(
resetGestureInputConsumer: ResetGestureInputConsumer?,
deviceState: RecentsAnimationDeviceState,
inputMonitorCompat: InputMonitorCompat,
previousGestureState: GestureState,
gestureState: GestureState,
event: MotionEvent,
reasonString: CompoundString,
): InputConsumer where T : RecentsViewContainer, T : StatefulContainer<S> {
val container: T =
gestureState.getContainerInterface<S, T>().getCreatedContainer()
?: return getDefaultInputConsumer(
resetGestureInputConsumer,
reasonString.append(
"%sactivity == null, trying to use default input consumer",
SUBSTRING_PREFIX,
),
)
val rootView = container.rootView
val hasWindowFocus = rootView?.hasWindowFocus() ?: false
val isPreviousGestureAnimatingToLauncher =
(previousGestureState.isRunningAnimationToLauncher ||
deviceState.isPredictiveBackToHomeInProgress)
val isInLiveTileMode: Boolean =
gestureState.getContainerInterface<S, T>().isInLiveTileMode()
reasonString.append(
if (hasWindowFocus) "%sactivity has window focus"
else
(if (isPreviousGestureAnimatingToLauncher)
"%sprevious gesture is still animating to launcher"
else if (isInLiveTileMode) "%sdevice is in live mode"
else "%sall overview focus conditions failed"),
SUBSTRING_PREFIX,
)
return if (hasWindowFocus || isPreviousGestureAnimatingToLauncher || isInLiveTileMode) {
reasonString.append(
"%soverview should have focus, using OverviewInputConsumer",
SUBSTRING_PREFIX,
)
OverviewInputConsumer(
gestureState,
container,
inputMonitorCompat,
/* startingInActivityBounds= */ false,
)
} else {
reasonString.append(
"%soverview shouldn't have focus, using OverviewWithoutFocusInputConsumer",
SUBSTRING_PREFIX,
)
val disableHorizontalSwipe = deviceState.isInExclusionRegion(event)
OverviewWithoutFocusInputConsumer(
container.asContext(),
deviceState,
gestureState,
inputMonitorCompat,
disableHorizontalSwipe,
)
}
}
/** Returns the [ResetGestureInputConsumer] if user is unlocked, else NO_OP. */
private fun getDefaultInputConsumer(
resetGestureInputConsumer: ResetGestureInputConsumer?,
reasonString: CompoundString,
): InputConsumer {
return if (resetGestureInputConsumer != null) {
reasonString.append(
"%smResetGestureInputConsumer initialized, using ResetGestureInputConsumer",
SUBSTRING_PREFIX,
)
resetGestureInputConsumer
} else {
reasonString.append(
"%smResetGestureInputConsumer not initialized, using no-op input consumer",
SUBSTRING_PREFIX,
)
// mResetGestureInputConsumer isn't initialized until onUserUnlocked(), so reset to
// NO_OP until then (we never want these to be null).
InputConsumer.NO_OP
}
}
private fun <S : BaseState<S>, T> createOtherActivityInputConsumer(
context: Context,
swipeUpHandlerFactory: AbsSwipeUpHandler.Factory,
overviewComponentObserver: OverviewComponentObserver,
deviceState: RecentsAnimationDeviceState,
taskAnimationManager: TaskAnimationManager,
inputMonitorCompat: InputMonitorCompat,
onCompleteCallback: Consumer<OtherActivityInputConsumer>,
inputEventReceiver: InputChannelCompat.InputEventReceiver,
gestureState: GestureState,
event: MotionEvent,
): InputConsumer where T : RecentsViewContainer, T : StatefulContainer<S> {
val shouldDefer =
(!overviewComponentObserver.isHomeAndOverviewSame ||
gestureState
.getContainerInterface<S, T>()
.deferStartingActivity(deviceState, event))
val disableHorizontalSwipe = deviceState.isInExclusionRegion(event)
return OtherActivityInputConsumer(
/* base= */ context,
deviceState,
taskAnimationManager,
gestureState,
/* isDeferredDownTarget= */ shouldDefer,
onCompleteCallback,
inputMonitorCompat,
inputEventReceiver,
disableHorizontalSwipe,
swipeUpHandlerFactory,
)
}
private fun newCompoundString(substring: String): CompoundString {
return CompoundString("%s%s", NEWLINE_PREFIX, substring)
}
private fun logInputConsumerSelectionReason(
consumer: InputConsumer,
reasonString: CompoundString,
) {
ActiveGestureProtoLogProxy.logSetInputConsumer(consumer.name, reasonString.toString())
if ((consumer.type and InputConsumer.TYPE_OTHER_ACTIVITY) != 0) {
ActiveGestureLog.INSTANCE.trackEvent(
ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER
)
}
}
private fun ignoreThreeFingerTrackpadForNavHandleLongPress(
gestureState: GestureState
): Boolean {
return (com.android.launcher3.Flags.ignoreThreeFingerTrackpadForNavHandleLongPress() &&
gestureState.isThreeFingerTrackpadGesture)
}
private fun handleOrientationSetup(baseInputConsumer: InputConsumer) {
baseInputConsumer.notifyOrientationSetup()
}
}
@@ -24,7 +24,6 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Flags.enableCursorHoverStates;
import static com.android.launcher3.Flags.enableHandleDelayedGestureCallbacks;
import static com.android.launcher3.Flags.useActivityOverlay;
import static com.android.launcher3.LauncherPrefs.backedUpItem;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
@@ -35,12 +34,12 @@ import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WI
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.quickstep.GestureState.TrackpadGestureType.getTrackpadGestureType;
import static com.android.quickstep.InputConsumer.TYPE_CURSOR_HOVER;
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER;
import static com.android.quickstep.InputConsumerUtils.newConsumer;
import static com.android.quickstep.InputConsumerUtils.tryCreateAssistantInputConsumer;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
import static com.android.wm.shell.Flags.enableBubblesLongPressNavHandle;
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
@@ -71,7 +70,6 @@ import android.view.Choreographer;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.BinderThread;
import androidx.annotation.MainThread;
@@ -106,21 +104,9 @@ import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.OverviewCommandHelper.CommandType;
import com.android.quickstep.fallback.window.RecentsWindowManager;
import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
import com.android.quickstep.inputconsumers.BubbleBarInputConsumer;
import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
import com.android.quickstep.inputconsumers.NavHandleLongPressInputConsumer;
import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
import com.android.quickstep.inputconsumers.ProgressDelegateInputConsumer;
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer;
import com.android.quickstep.inputconsumers.TrackpadStatusBarInputConsumer;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActiveGestureLog.CompoundString;
import com.android.quickstep.util.ActiveGestureProtoLogProxy;
@@ -959,7 +945,8 @@ public class TouchInteractionService extends Service {
+ "consuming gesture for assistant action");
mGestureState =
createGestureState(mGestureState, getTrackpadGestureType(event));
mUncheckedConsumer = tryCreateAssistantInputConsumer(mGestureState, event);
mUncheckedConsumer = tryCreateAssistantInputConsumer(
this, mDeviceState, mInputMonitorCompat, mGestureState, event);
} else {
reasonString.append(" but event cannot trigger Assistant, "
+ "consuming gesture as no-op");
@@ -978,7 +965,23 @@ public class TouchInteractionService extends Service {
getTrackpadGestureType(event));
mConsumer.onConsumerAboutToBeSwitched();
mGestureState = newGestureState;
mConsumer = newConsumer(prevGestureState, mGestureState, event);
mConsumer = newConsumer(
getBaseContext(),
this,
mResetGestureInputConsumer,
mOverviewComponentObserver,
mDeviceState,
prevGestureState,
mGestureState,
mTaskAnimationManager,
mInputMonitorCompat,
getSwipeUpHandlerFactory(),
this::onConsumerInactive,
mInputEventReceiver,
mTaskbarManager,
mSwipeUpProxyProvider,
mOverviewCommandHelper,
event);
mUncheckedConsumer = mConsumer;
} else if ((mDeviceState.isFullyGesturalNavMode() || isTrackpadMultiFingerSwipe(event))
&& mDeviceState.canTriggerAssistantAction(event)) {
@@ -991,7 +994,8 @@ public class TouchInteractionService extends Service {
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
mUncheckedConsumer = tryCreateAssistantInputConsumer(mGestureState, event);
mUncheckedConsumer = tryCreateAssistantInputConsumer(
this, mDeviceState, mInputMonitorCompat, mGestureState, event);
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
reasonString.append("event can trigger one-handed action, "
+ "consuming gesture for one-handed action");
@@ -1073,28 +1077,6 @@ public class TouchInteractionService extends Service {
return event.isHoverEvent() && event.getSource() == InputDevice.SOURCE_MOUSE;
}
private InputConsumer tryCreateAssistantInputConsumer(
GestureState gestureState, MotionEvent motionEvent) {
return tryCreateAssistantInputConsumer(
InputConsumer.NO_OP, gestureState, motionEvent, CompoundString.NO_OP);
}
private InputConsumer tryCreateAssistantInputConsumer(
InputConsumer base,
GestureState gestureState,
MotionEvent motionEvent,
CompoundString reasonString) {
if (mDeviceState.isGestureBlockedTask(gestureState.getRunningTask())) {
reasonString.append(
"%sis gesture-blocked task, using base input consumer", SUBSTRING_PREFIX);
return base;
} else {
reasonString.append("%susing AssistantInputConsumer", SUBSTRING_PREFIX);
return new AssistantInputConsumer(
this, gestureState, base, mInputMonitorCompat, mDeviceState, motionEvent);
}
}
public GestureState createGestureState(GestureState previousGestureState,
GestureState.TrackpadGestureType trackpadGestureType) {
final GestureState gestureState;
@@ -1125,312 +1107,6 @@ public class TouchInteractionService extends Service {
return gestureState;
}
private InputConsumer newConsumer(
GestureState previousGestureState, GestureState newGestureState, MotionEvent event) {
TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
BubbleControllers bubbleControllers = tac != null ? tac.getBubbleControllers() : null;
if (bubbleControllers != null && BubbleBarInputConsumer.isEventOnBubbles(tac, event)) {
InputConsumer consumer = new BubbleBarInputConsumer(this, bubbleControllers,
mInputMonitorCompat);
logInputConsumerSelectionReason(consumer, newCompoundString(
"event is on bubbles, creating new input consumer"));
return consumer;
}
AnimatedFloat progressProxy = mSwipeUpProxyProvider.apply(mGestureState);
if (progressProxy != null) {
InputConsumer consumer = new ProgressDelegateInputConsumer(
this, mTaskAnimationManager, mGestureState, mInputMonitorCompat, progressProxy);
logInputConsumerSelectionReason(consumer, newCompoundString(
"mSwipeUpProxyProvider has been set, using ProgressDelegateInputConsumer"));
return consumer;
}
boolean canStartSystemGesture =
mGestureState.isTrackpadGesture() ? mDeviceState.canStartTrackpadGesture()
: mDeviceState.canStartSystemGesture();
if (!LockedUserState.get(this).isUserUnlocked()) {
CompoundString reasonString = newCompoundString("device locked");
InputConsumer consumer;
if (canStartSystemGesture) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
consumer = createDeviceLockedInputConsumer(
newGestureState,
reasonString.append("%scan start system gesture", SUBSTRING_PREFIX));
} else {
consumer = getDefaultInputConsumer(
reasonString.append("%scannot start system gesture", SUBSTRING_PREFIX));
}
logInputConsumerSelectionReason(consumer, reasonString);
return consumer;
}
CompoundString reasonString;
InputConsumer base;
// When there is an existing recents animation running, bypass systemState check as this is
// a followup gesture and the first gesture started in a valid system state.
if (canStartSystemGesture || previousGestureState.isRecentsAnimationRunning()) {
reasonString = newCompoundString(canStartSystemGesture
? "can start system gesture, trying to use base consumer"
: "recents animation was running, trying to use base consumer");
base = newBaseConsumer(previousGestureState, newGestureState, event, reasonString);
} else {
reasonString = newCompoundString("cannot start system gesture and recents "
+ "animation was not running, trying to use default input consumer");
base = getDefaultInputConsumer(reasonString);
}
if (mDeviceState.isGesturalNavMode() || newGestureState.isTrackpadGesture()) {
handleOrientationSetup(base);
}
if (mDeviceState.isFullyGesturalNavMode() || newGestureState.isTrackpadGesture()) {
String reasonPrefix =
"device is in gesture navigation mode or 3-button mode with a trackpad gesture";
if (mDeviceState.canTriggerAssistantAction(event)) {
reasonString.append("%s%s%sgesture can trigger the assistant, "
+ "trying to use assistant input consumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
base = tryCreateAssistantInputConsumer(base, newGestureState, event, reasonString);
}
// If Taskbar is present, we listen for swipe or cursor hover events to unstash it.
if (tac != null && !(base instanceof AssistantInputConsumer)) {
// Present always on large screen or on small screen w/ flag
boolean useTaskbarConsumer = tac.getDeviceProfile().isTaskbarPresent
&& !tac.isPhoneMode()
&& !tac.isInStashedLauncherState();
if (canStartSystemGesture && useTaskbarConsumer) {
reasonString.append("%s%s%sTaskbarActivityContext != null, "
+ "using TaskbarUnstashInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac,
mOverviewCommandHelper, mGestureState);
}
}
if (enableBubblesLongPressNavHandle()) {
// Create bubbles input consumer before NavHandleLongPressInputConsumer.
// This allows for nav handle to fall back to bubbles.
if (mDeviceState.isBubblesExpanded()) {
reasonString = newCompoundString(reasonPrefix).append(
"%sbubbles expanded, trying to use default input consumer",
SUBSTRING_PREFIX);
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(reasonString);
}
}
NavHandle navHandle = tac != null ? tac.getNavHandle()
: SystemUiProxy.INSTANCE.get(this);
if (canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()
&& navHandle.canNavHandleBeLongPressed()
&& !ignoreThreeFingerTrackpadForNavHandleLongPress(mGestureState)) {
reasonString.append("%s%s%sNot running recents animation, ",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
if (tac != null && tac.getNavHandle().canNavHandleBeLongPressed()) {
reasonString.append("stashed handle is long-pressable, ");
}
reasonString.append("using NavHandleLongPressInputConsumer");
base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat,
mDeviceState, navHandle, mGestureState);
}
if (!enableBubblesLongPressNavHandle()) {
// Continue overriding nav handle input consumer with bubbles
if (mDeviceState.isBubblesExpanded()) {
reasonString = newCompoundString(reasonPrefix).append(
"%sbubbles expanded, trying to use default input consumer",
SUBSTRING_PREFIX);
// Bubbles can handle home gesture itself.
base = getDefaultInputConsumer(reasonString);
}
}
if (mDeviceState.isSystemUiDialogShowing()) {
reasonString = newCompoundString(reasonPrefix).append(
"%ssystem dialog is showing, using SysUiOverlayInputConsumer",
SUBSTRING_PREFIX);
base = new SysUiOverlayInputConsumer(
getBaseContext(), mDeviceState, mInputMonitorCompat);
}
if (mGestureState.isTrackpadGesture()
&& canStartSystemGesture && !previousGestureState.isRecentsAnimationRunning()) {
reasonString = newCompoundString(reasonPrefix).append(
"%sTrackpad 3-finger gesture, using TrackpadStatusBarInputConsumer",
SUBSTRING_PREFIX);
base = new TrackpadStatusBarInputConsumer(getBaseContext(), base,
mInputMonitorCompat);
}
if (mDeviceState.isScreenPinningActive()) {
reasonString = newCompoundString(reasonPrefix).append(
"%sscreen pinning is active, using ScreenPinnedInputConsumer",
SUBSTRING_PREFIX);
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
base = new ScreenPinnedInputConsumer(this, newGestureState);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
reasonString.append("%s%s%sgesture can trigger one handed mode, "
+ "using OneHandedModeInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
base = new OneHandedModeInputConsumer(
this, mDeviceState, base, mInputMonitorCompat);
}
if (mDeviceState.isAccessibilityMenuAvailable()) {
reasonString.append(
"%s%s%saccessibility menu is available, using AccessibilityInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
base = new AccessibilityInputConsumer(
this, mDeviceState, mGestureState, base, mInputMonitorCompat);
}
} else {
String reasonPrefix = "device is not in gesture navigation mode";
if (mDeviceState.isScreenPinningActive()) {
reasonString = newCompoundString(reasonPrefix).append(
"%sscreen pinning is active, trying to use default input consumer",
SUBSTRING_PREFIX);
base = getDefaultInputConsumer(reasonString);
}
if (mDeviceState.canTriggerOneHandedAction(event)) {
reasonString.append("%s%s%sgesture can trigger one handed mode, "
+ "using OneHandedModeInputConsumer",
NEWLINE_PREFIX,
reasonPrefix,
SUBSTRING_PREFIX);
base = new OneHandedModeInputConsumer(
this, mDeviceState, base, mInputMonitorCompat);
}
}
logInputConsumerSelectionReason(base, reasonString);
return base;
}
private CompoundString newCompoundString(String substring) {
return new CompoundString("%s%s", NEWLINE_PREFIX, substring);
}
private boolean ignoreThreeFingerTrackpadForNavHandleLongPress(GestureState gestureState) {
return Flags.ignoreThreeFingerTrackpadForNavHandleLongPress()
&& gestureState.isThreeFingerTrackpadGesture();
}
private void logInputConsumerSelectionReason(
InputConsumer consumer, CompoundString reasonString) {
ActiveGestureProtoLogProxy.logSetInputConsumer(consumer.getName(), reasonString.toString());
if ((consumer.getType() & InputConsumer.TYPE_OTHER_ACTIVITY) != 0) {
ActiveGestureLog.INSTANCE.trackEvent(FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER);
}
}
private void handleOrientationSetup(InputConsumer baseInputConsumer) {
baseInputConsumer.notifyOrientationSetup();
}
private InputConsumer newBaseConsumer(
GestureState previousGestureState,
GestureState gestureState,
MotionEvent event,
CompoundString reasonString) {
if (mDeviceState.isKeyguardShowingOccluded()) {
// This handles apps showing over the lockscreen (e.g. camera)
return createDeviceLockedInputConsumer(gestureState, reasonString.append(
"%skeyguard is showing occluded, trying to use device locked input consumer",
SUBSTRING_PREFIX));
}
reasonString.append("%skeyguard is not showing occluded", SUBSTRING_PREFIX);
TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask();
// Use overview input consumer for sharesheets on top of home.
boolean forceOverviewInputConsumer = gestureState.getContainerInterface().isStarted()
&& runningTask != null
&& runningTask.isRootChooseActivity();
if (!com.android.wm.shell.Flags.enableShellTopTaskTracking()) {
// In the case where we are in an excluded, translucent overlay, ignore it and treat the
// running activity as the task behind the overlay.
TopTaskTracker.CachedTaskInfo otherVisibleTask = runningTask == null
? null
: runningTask.getVisibleNonExcludedTask();
if (otherVisibleTask != null) {
ActiveGestureProtoLogProxy.logUpdateGestureStateRunningTask(
otherVisibleTask.getPackageName(), runningTask.getPackageName());
gestureState.updateRunningTask(otherVisibleTask);
}
}
boolean previousGestureAnimatedToLauncher =
previousGestureState.isRunningAnimationToLauncher()
|| mDeviceState.isPredictiveBackToHomeInProgress();
// with shell-transitions, home is resumed during recents animation, so
// explicitly check against recents animation too.
boolean launcherResumedThroughShellTransition =
gestureState.getContainerInterface().isResumed()
&& !previousGestureState.isRecentsAnimationRunning();
// If a task fragment within Launcher is resumed
boolean launcherChildActivityResumed = useActivityOverlay()
&& runningTask != null
&& runningTask.isHomeTask()
&& mOverviewComponentObserver.isHomeAndOverviewSame()
&& !launcherResumedThroughShellTransition
&& !previousGestureState.isRecentsAnimationRunning();
if (gestureState.getContainerInterface().isInLiveTileMode()) {
return createOverviewInputConsumer(
previousGestureState,
gestureState,
event,
forceOverviewInputConsumer,
reasonString.append(
"%sis in live tile mode, trying to use overview input consumer",
SUBSTRING_PREFIX));
} else if (runningTask == null) {
return getDefaultInputConsumer(reasonString.append(
"%srunning task == null", SUBSTRING_PREFIX));
} else if (previousGestureAnimatedToLauncher
|| launcherResumedThroughShellTransition
|| forceOverviewInputConsumer) {
return createOverviewInputConsumer(
previousGestureState,
gestureState,
event,
forceOverviewInputConsumer,
reasonString.append(previousGestureAnimatedToLauncher
? "%sprevious gesture animated to launcher, "
+ "trying to use overview input consumer"
: (launcherResumedThroughShellTransition
? "%slauncher resumed through a shell transition, "
+ "trying to use overview input consumer"
: "%sforceOverviewInputConsumer == true, "
+ "trying to use overview input consumer"),
SUBSTRING_PREFIX));
} else if (mDeviceState.isGestureBlockedTask(runningTask) || launcherChildActivityResumed) {
return getDefaultInputConsumer(reasonString.append(launcherChildActivityResumed
? "%sis launcher child-task, trying to use default input consumer"
: "%sis gesture-blocked task, trying to use default input consumer",
SUBSTRING_PREFIX));
} else {
reasonString.append("%susing OtherActivityInputConsumer", SUBSTRING_PREFIX);
return createOtherActivityInputConsumer(gestureState, event);
}
}
public AbsSwipeUpHandler.Factory getSwipeUpHandlerFactory() {
boolean recentsInWindow =
Flags.enableFallbackOverviewInWindow() || Flags.enableLauncherOverviewInWindow();
@@ -1439,80 +1115,6 @@ public class TouchInteractionService extends Service {
? mRecentsWindowSwipeHandlerFactory : mFallbackSwipeHandlerFactory);
}
private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
MotionEvent event) {
final AbsSwipeUpHandler.Factory factory = getSwipeUpHandlerFactory();
final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame()
|| gestureState.getContainerInterface().deferStartingActivity(mDeviceState, event);
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
gestureState, shouldDefer, this::onConsumerInactive,
mInputMonitorCompat, mInputEventReceiver, disableHorizontalSwipe, factory);
}
private InputConsumer createDeviceLockedInputConsumer(
GestureState gestureState, CompoundString reasonString) {
if ((mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture())
&& gestureState.getRunningTask() != null) {
reasonString.append("%sdevice is in gesture nav mode or 3-button mode with a trackpad "
+ "gesture and running task != null, using DeviceLockedInputConsumer",
SUBSTRING_PREFIX);
return new DeviceLockedInputConsumer(
this, mDeviceState, mTaskAnimationManager, gestureState, mInputMonitorCompat);
} else {
return getDefaultInputConsumer(reasonString.append(
mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture()
? "%srunning task == null, trying to use default input consumer"
: "%sdevice is not in gesture nav mode and it's not a trackpad gesture,"
+ " trying to use default input consumer",
SUBSTRING_PREFIX));
}
}
public InputConsumer createOverviewInputConsumer(
GestureState previousGestureState,
GestureState gestureState,
MotionEvent event,
boolean forceOverviewInputConsumer,
CompoundString reasonString) {
RecentsViewContainer container = gestureState.getContainerInterface().getCreatedContainer();
if (container == null) {
return getDefaultInputConsumer(reasonString.append(
"%sactivity == null, trying to use default input consumer", SUBSTRING_PREFIX));
}
View rootview = container.getRootView();
boolean hasWindowFocus = rootview != null && rootview.hasWindowFocus();
boolean isPreviousGestureAnimatingToLauncher =
previousGestureState.isRunningAnimationToLauncher()
|| mDeviceState.isPredictiveBackToHomeInProgress();
boolean isInLiveTileMode = gestureState.getContainerInterface().isInLiveTileMode();
reasonString.append(hasWindowFocus
? "%sactivity has window focus"
: (isPreviousGestureAnimatingToLauncher
? "%sprevious gesture is still animating to launcher"
: isInLiveTileMode
? "%sdevice is in live mode"
: "%sall overview focus conditions failed"), SUBSTRING_PREFIX);
if (hasWindowFocus
|| isPreviousGestureAnimatingToLauncher
|| isInLiveTileMode) {
reasonString.append(
"%soverview should have focus, using OverviewInputConsumer", SUBSTRING_PREFIX);
return new OverviewInputConsumer(gestureState, container, mInputMonitorCompat,
false /* startingInActivityBounds */);
} else {
reasonString.append(
"%soverview shouldn't have focus, using OverviewWithoutFocusInputConsumer",
SUBSTRING_PREFIX);
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
return new OverviewWithoutFocusInputConsumer(container.asContext(), mDeviceState,
gestureState, mInputMonitorCompat, disableHorizontalSwipe);
}
}
/**
* To be called by the consumer when it's no longer active. This can be called by any consumer
* in the hierarchy at any point during the gesture (ie. if a delegate consumer starts