Merge "Update the enforce_system_radius_for_app_widgets flag's type" into main
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 53f37ba..b221b22 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -362,11 +362,6 @@
<dimen name="taskbar_running_app_indicator_width">12dp</dimen>
<dimen name="taskbar_running_app_indicator_top_margin">4dp</dimen>
<dimen name="taskbar_minimized_app_indicator_width">6dp</dimen>
- <dimen name="taskbar_overflow_item_icon_size_default">22dp</dimen>
- <dimen name="taskbar_overflow_item_icon_size_scaled_down">15dp</dimen>
- <dimen name="taskbar_overflow_item_icon_stroke_width_default">2dp</dimen>
- <dimen name="taskbar_overflow_leave_behind_size_default">18dp</dimen>
- <dimen name="taskbar_overflow_leave_behind_size_scaled_down">15dp</dimen>
<!-- Transient taskbar -->
<dimen name="transient_taskbar_padding">12dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarOverflowView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarOverflowView.java
index 712478e..8775766 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarOverflowView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarOverflowView.java
@@ -41,6 +41,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Reorderable;
import com.android.launcher3.Utilities;
+import com.android.launcher3.icons.IconNormalizer;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.util.Themes;
import com.android.systemui.shared.recents.model.Task;
@@ -68,8 +69,15 @@
private static final long LEAVE_BEHIND_ANIMATIONS_DELAY = 500L;
private static final long LEAVE_BEHIND_OPACITY_ANIMATION_DURATION = 100L;
private static final long LEAVE_BEHIND_SIZE_ANIMATION_DURATION = 500L;
+ private static final float LEAVE_BEHIND_SIZE_SCALE_DOWN_MULTIPLIER = 0.83f;
private static final int MAX_ITEMS_IN_PREVIEW = 4;
+ // The height divided by the width of the horizontal box containing two overlapping app icons.
+ // According to the spec, this ratio is constant for different sizes of taskbar app icons.
+ // Assuming the width of this box = taskbar app icon size - 2 paddings - 2 stroke widths, and
+ // the height = width * 0.61, which is also equal to the height of a single item in the preview.
+ private static final float TWO_ITEM_ICONS_BOX_ASPECT_RATIO = 0.61f;
+
private static final FloatProperty<TaskbarOverflowView> ITEM_ICON_CENTER_OFFSET =
new FloatProperty<>("itemIconCenterOffset") {
@Override
@@ -208,9 +216,24 @@
icon.mIconSize = iconSize;
icon.mPadding = padding;
- final float radius = iconSize / 2f - padding;
- final float size = radius + icon.mItemIconStrokeWidth;
- icon.mItemIconCenterOffsetDefault = radius - size / 2 - icon.mItemIconStrokeWidth;
+ final float taskbarIconRadius =
+ iconSize * IconNormalizer.ICON_VISIBLE_AREA_FACTOR / 2f - padding;
+
+ icon.mLeaveBehindSizeDefault = taskbarIconRadius; // 1/2 of taskbar app icon size
+ icon.mLeaveBehindSizeScaledDown =
+ icon.mLeaveBehindSizeDefault * LEAVE_BEHIND_SIZE_SCALE_DOWN_MULTIPLIER;
+ icon.mLeaveBehindSize = icon.mLeaveBehindSizeScaledDown;
+
+ icon.mItemIconStrokeWidthDefault = taskbarIconRadius / 5f; // 1/10 of taskbar app icon size
+ icon.mItemIconStrokeWidth = icon.mItemIconStrokeWidthDefault;
+
+ icon.mItemIconSizeDefault = 2 * (taskbarIconRadius - icon.mItemIconStrokeWidthDefault)
+ * TWO_ITEM_ICONS_BOX_ASPECT_RATIO;
+ icon.mItemIconSizeScaledDown = icon.mLeaveBehindSizeScaledDown;
+ icon.mItemIconSize = icon.mItemIconSizeDefault;
+
+ icon.mItemIconCenterOffsetDefault = taskbarIconRadius - icon.mItemIconSizeDefault / 2f
+ - icon.mItemIconStrokeWidthDefault;
icon.mItemIconCenterOffset = icon.mItemIconCenterOffsetDefault;
return icon;
@@ -222,22 +245,6 @@
mItemBackgroundColor = getContext().getColor(R.color.taskbar_background);
mLeaveBehindColor = Themes.getAttrColor(getContext(), android.R.attr.textColorTertiary);
- mItemIconSizeDefault = getResources().getDimension(
- R.dimen.taskbar_overflow_item_icon_size_default);
- mItemIconSizeScaledDown = getResources().getDimension(
- R.dimen.taskbar_overflow_item_icon_size_scaled_down);
- mItemIconSize = mItemIconSizeDefault;
-
- mItemIconStrokeWidthDefault = getResources().getDimension(
- R.dimen.taskbar_overflow_item_icon_stroke_width_default);
- mItemIconStrokeWidth = mItemIconStrokeWidthDefault;
-
- mLeaveBehindSizeDefault = getResources().getDimension(
- R.dimen.taskbar_overflow_leave_behind_size_default);
- mLeaveBehindSizeScaledDown = getResources().getDimension(
- R.dimen.taskbar_overflow_leave_behind_size_scaled_down);
- mLeaveBehindSize = mLeaveBehindSizeScaledDown;
-
setWillNotDraw(false);
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 5190ec8..cfbcf0a 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -274,7 +274,7 @@
* @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;
}
diff --git a/quickstep/src/com/android/quickstep/InputConsumerUtils.kt b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
new file mode 100644
index 0000000..bea3150
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/InputConsumerUtils.kt
@@ -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()
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 0242fb6..d38eaf3 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -24,7 +24,6 @@
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.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.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.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 @@
+ "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 @@
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 @@
// 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 @@
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 @@
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 @@
? 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
diff --git a/res/layout/add_item_confirmation_activity.xml b/res/layout/add_item_confirmation_activity.xml
index d113a38..2bb2eb3 100644
--- a/res/layout/add_item_confirmation_activity.xml
+++ b/res/layout/add_item_confirmation_activity.xml
@@ -71,7 +71,8 @@
android:id="@+id/widget_preview_scroll_view"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_marginVertical="16dp"
+ android:layout_margin="16dp"
+ android:background="@drawable/widgets_surface_background"
android:layout_weight="1">
<include
diff --git a/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
index ce00b28..9b4bd71 100644
--- a/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/icons/IconCacheTest.java
@@ -71,6 +71,7 @@
import com.google.common.truth.Truth;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,6 +100,11 @@
new LauncherIconProvider(mContext));
}
+ @After
+ public void tearDown() {
+ mIconCache.close();
+ }
+
@Test
public void getShortcutInfoBadge_nullComponent_overrideAllowed() throws Exception {
String overridePackage = "com.android.settings";
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
index c9ea421..09752b8 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/DatabaseHelperTest.kt
@@ -1,5 +1,6 @@
package com.android.launcher3.model
+import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -11,8 +12,10 @@
import com.android.launcher3.pm.UserCache
import com.android.launcher3.provider.LauncherDbUtils
import java.util.function.ToLongFunction
+import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -24,6 +27,19 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class DatabaseHelperTest {
+ val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
+ // v30 - 21 columns
+ lateinit var db: SQLiteDatabase
+
+ @Before
+ fun setUp() {
+ db = FactitiousDbController(context, INSERTION_SQL).inMemoryDb
+ }
+
+ @After
+ fun tearDown() {
+ db.close()
+ }
/**
* b/304687723 occurred when a return was accidentally added to a case statement in
@@ -33,13 +49,11 @@
*/
@Test
fun onUpgrade_to_version_32_from_30() {
- val context = InstrumentationRegistry.getInstrumentation().targetContext
val userSerialProvider =
ToLongFunction<UserHandle> {
UserCache.INSTANCE.get(context).getSerialNumberForUser(it)
}
val dbHelper = DatabaseHelper(context, null, userSerialProvider) {}
- val db = FactitiousDbController(context, INSERTION_SQL).inMemoryDb
dbHelper.onUpgrade(db, 30, 32)
@@ -54,9 +68,6 @@
*/
@Test
fun after_migrating_from_db_v30_to_v32_copy_table() {
- val context = InstrumentationRegistry.getInstrumentation().targetContext
- val db = FactitiousDbController(context, INSERTION_SQL).inMemoryDb // v30 - 21 columns
-
addTableToDb(db, 1, true, TMP_TABLE)
LauncherDbUtils.copyTable(db, TABLE_NAME, db, TMP_TABLE, context)
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
index 7933331..eee6191 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
@@ -82,6 +82,7 @@
@After
fun tearDown() {
+ db.close()
modelHelper.destroy()
}
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java
index b4945d7..63359ec 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -109,6 +109,7 @@
@After
public void tearDown() {
+ mCursor.close();
mModelHelper.destroy();
}
diff --git a/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index d0c168a..c30b730 100644
--- a/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -92,6 +92,7 @@
private Cursor mMockCursor;
private LauncherPrefs mPrefs;
private LauncherRestoreEventLogger mMockRestoreEventLogger;
+ private SQLiteDatabase mDb;
@Before
public void setup() {
@@ -107,57 +108,60 @@
@After
public void teardown() {
+ if (mDb != null) {
+ mDb.close();
+ }
mModelHelper.destroy();
LauncherPrefs.get(mContext).removeSync(RESTORE_DEVICE);
}
@Test
public void testGetProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(23).getDb();
- assertEquals(23, new RestoreDbTask().getDefaultProfileId(db));
+ mDb = new MyModelDbController(23).getDb();
+ assertEquals(23, new RestoreDbTask().getDefaultProfileId(mDb));
}
@Test
public void testMigrateProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ mDb = new MyModelDbController(42).getDb();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
values.put(Favorites.TITLE, "item " + i);
- db.insert(Favorites.TABLE_NAME, null, values);
+ mDb.insert(Favorites.TABLE_NAME, null, values);
}
// Verify item add
- assertEquals(5, getCount(db, "select * from favorites where profileId = 42"));
+ assertEquals(5, getCount(mDb, "select * from favorites where profileId = 42"));
- new RestoreDbTask().migrateProfileId(db, 42, 33);
+ new RestoreDbTask().migrateProfileId(mDb, 42, 33);
// verify data migrated
- assertEquals(0, getCount(db, "select * from favorites where profileId = 42"));
- assertEquals(5, getCount(db, "select * from favorites where profileId = 33"));
+ assertEquals(0, getCount(mDb, "select * from favorites where profileId = 42"));
+ assertEquals(5, getCount(mDb, "select * from favorites where profileId = 33"));
}
@Test
public void testChangeDefaultColumn() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ mDb = new MyModelDbController(42).getDb();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
values.put(Favorites.TITLE, "item " + i);
- db.insert(Favorites.TABLE_NAME, null, values);
+ mDb.insert(Favorites.TABLE_NAME, null, values);
}
// Verify default column is 42
- assertEquals(5, getCount(db, "select * from favorites where profileId = 42"));
+ assertEquals(5, getCount(mDb, "select * from favorites where profileId = 42"));
- new RestoreDbTask().changeDefaultColumn(db, 33);
+ new RestoreDbTask().changeDefaultColumn(mDb, 33);
// Verify default value changed
ContentValues values = new ContentValues();
values.put(Favorites._ID, 100);
values.put(Favorites.TITLE, "item 100");
- db.insert(Favorites.TABLE_NAME, null, values);
- assertEquals(1, getCount(db, "select * from favorites where profileId = 33"));
+ mDb.insert(Favorites.TABLE_NAME, null, values);
+ assertEquals(1, getCount(mDb, "select * from favorites where profileId = 33"));
}
@Test
@@ -170,7 +174,7 @@
long workProfileId_old = myProfileId + 3;
MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ mDb = controller.getDb();
BackupManager bm = spy(new BackupManager(mContext));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
@@ -178,16 +182,16 @@
addIconsBulk(controller, 10, 1, myProfileId_old);
addIconsBulk(controller, 6, 2, workProfileId_old);
- assertEquals(10, getItemCountForProfile(db, myProfileId_old));
- assertEquals(6, getItemCountForProfile(db, workProfileId_old));
+ assertEquals(10, getItemCountForProfile(mDb, myProfileId_old));
+ assertEquals(6, getItemCountForProfile(mDb, workProfileId_old));
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm, mMockRestoreEventLogger);
// All the data has been migrated to the new user ids
- assertEquals(0, getItemCountForProfile(db, myProfileId_old));
- assertEquals(0, getItemCountForProfile(db, workProfileId_old));
- assertEquals(10, getItemCountForProfile(db, myProfileId));
- assertEquals(6, getItemCountForProfile(db, workProfileId));
+ assertEquals(0, getItemCountForProfile(mDb, myProfileId_old));
+ assertEquals(0, getItemCountForProfile(mDb, workProfileId_old));
+ assertEquals(10, getItemCountForProfile(mDb, myProfileId));
+ assertEquals(6, getItemCountForProfile(mDb, workProfileId));
}
@Test
@@ -199,7 +203,7 @@
long workProfileId_old = myProfileId + 3;
MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ mDb = controller.getDb();
BackupManager bm = spy(new BackupManager(mContext));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
// Work profile is not migrated
@@ -207,16 +211,16 @@
addIconsBulk(controller, 10, 1, myProfileId_old);
addIconsBulk(controller, 6, 2, workProfileId_old);
- assertEquals(10, getItemCountForProfile(db, myProfileId_old));
- assertEquals(6, getItemCountForProfile(db, workProfileId_old));
+ assertEquals(10, getItemCountForProfile(mDb, myProfileId_old));
+ assertEquals(6, getItemCountForProfile(mDb, workProfileId_old));
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm, mMockRestoreEventLogger);
// All the data has been migrated to the new user ids
- assertEquals(0, getItemCountForProfile(db, myProfileId_old));
- assertEquals(0, getItemCountForProfile(db, workProfileId_old));
- assertEquals(10, getItemCountForProfile(db, myProfileId));
- assertEquals(10, getCount(db, "select * from favorites"));
+ assertEquals(0, getItemCountForProfile(mDb, myProfileId_old));
+ assertEquals(0, getItemCountForProfile(mDb, workProfileId_old));
+ assertEquals(10, getItemCountForProfile(mDb, myProfileId));
+ assertEquals(10, getCount(mDb, "select * from favorites"));
}
@Test
@@ -342,24 +346,24 @@
}
private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ mDb = new MyModelDbController(42).getDb();
// Add some mock data
for (int i = 0; i < screenIds.length; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
values.put(Favorites.SCREEN, screenIds[i]);
values.put(Favorites.CONTAINER, CONTAINER_DESKTOP);
- db.insert(Favorites.TABLE_NAME, null, values);
+ mDb.insert(Favorites.TABLE_NAME, null, values);
}
// Verify items are added
assertEquals(screenIds.length,
- getCount(db, "select * from favorites where container = -100"));
+ getCount(mDb, "select * from favorites where container = -100"));
- new RestoreDbTask().removeScreenIdGaps(db);
+ new RestoreDbTask().removeScreenIdGaps(mDb);
// verify screenId gaps removed
int[] resultScreenIds = new int[screenIds.length];
- try (Cursor c = db.rawQuery(
+ try (Cursor c = mDb.rawQuery(
"select screen from favorites where container = -100 order by screen", null)) {
int i = 0;
while (c.moveToNext()) {
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt b/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
index 7484bce..ac5fda2 100644
--- a/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
@@ -26,6 +26,7 @@
import com.android.launcher3.util.ActivityContextWrapper
import com.android.launcher3.util.Executors
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -38,7 +39,7 @@
@get:Rule val checkFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
private val providerName =
ComponentName(
- getInstrumentation().getContext().getPackageName(),
+ getInstrumentation().context.packageName,
"com.android.launcher3.testcomponent.AppWidgetNoConfig",
)
private val generatedPreviewLayout =
@@ -51,6 +52,7 @@
private lateinit var helper: WidgetManagerHelper
private lateinit var appWidgetProviderInfo: LauncherAppWidgetProviderInfo
private lateinit var widgetItem: WidgetItem
+ private lateinit var iconCache: IconCache
@Before
fun setup() {
@@ -88,17 +90,17 @@
createWidgetItem()
}
+ @After
+ fun tearDown() {
+ iconCache.close()
+ }
+
private fun createWidgetItem() {
Executors.MODEL_EXECUTOR.submit {
val idp = InvariantDeviceProfile()
- widgetItem =
- WidgetItem(
- appWidgetProviderInfo,
- idp,
- IconCache(context, idp, null, IconProvider(context)),
- context,
- helper,
- )
+ if (::iconCache.isInitialized) iconCache.close()
+ iconCache = IconCache(context, idp, null, IconProvider(context))
+ widgetItem = WidgetItem(appWidgetProviderInfo, idp, iconCache, context, helper)
}
.get()
}
diff --git a/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt b/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt
index 6446592..61fa7d5 100644
--- a/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt
+++ b/tests/src/com/android/launcher3/util/BaseLauncherActivityTest.kt
@@ -124,9 +124,10 @@
@JvmOverloads
protected fun injectKeyEvent(keyCode: Int, actionDown: Boolean, metaState: Int = 0) {
+ uiDevice.waitForIdle()
val eventTime = SystemClock.uptimeMillis()
val event =
- KeyEvent.obtain(
+ KeyEvent(
eventTime,
eventTime,
if (actionDown) KeyEvent.ACTION_DOWN else MotionEvent.ACTION_UP,
@@ -137,10 +138,8 @@
/* scancode= */ 0,
/* flags= */ 0,
InputDevice.SOURCE_KEYBOARD,
- /* characters =*/ null,
)
executeOnLauncher { it.dispatchKeyEvent(event) }
- event.recycle()
}
@JvmOverloads