Merge "Wait for all springs to finish before running end snapping and relayout." into main

This commit is contained in:
Treehugger Robot
2025-05-19 03:47:48 -07:00
committed by Android (Google) Code Review
5 changed files with 502 additions and 359 deletions
@@ -46,6 +46,7 @@ import com.android.mechanics.spec.MotionSpec
import com.android.mechanics.spring.SpringParameters
import com.android.mechanics.view.DistanceGestureContext
import com.android.mechanics.view.ViewMotionValue
import com.android.quickstep.views.RecentsDismissUtils
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY
import com.android.quickstep.views.RecentsViewContainer
@@ -86,7 +87,7 @@ CONTAINER : StatefulContainer<T> {
private var taskBeingDragged: TaskView? = null
private var taskDragDisplacementValue: ViewMotionValue? = null
private var springAnimation: SpringAnimation? = null
private var springAnimation: RecentsDismissUtils.SpringSet? = null
private var dismissLength: Int = 0
private var verticalFactor: Int = 0
private var hasDismissThresholdHapticRun = false
File diff suppressed because it is too large Load Diff
@@ -4555,7 +4555,7 @@ public abstract class RecentsView<
/** Dismisses the entire [taskView]. */
public void dismissTaskView(TaskView taskView, boolean animateTaskView, boolean removeTask) {
if (enableExpressiveDismissTaskMotion() && (!showAsGrid() || enableGridOnlyOverview())) {
mDismissUtils.createTaskDismissSettlingSpringAnimation(taskView, removeTask,
mDismissUtils.createTaskDismissSpringAnimation(taskView, removeTask,
false /* isSplitSelection */);
} else {
PendingAnimation pa = new PendingAnimation(DISMISS_TASK_DURATION);
@@ -5347,7 +5347,7 @@ public abstract class RecentsView<
mContainer.getDeviceProfile().isTablet);
if (animator.getAnimatedFraction() > splitTimings.getGridSlideStartOffset()
&& !hasRunDismiss.get()) {
mDismissUtils.createTaskDismissSettlingSpringAnimation(
mDismissUtils.createTaskDismissSpringAnimation(
taskView, false /* shouldRemoveTaskView */,
true /* isSplitSelection */);
hasRunDismiss.set(true);
@@ -7014,11 +7014,11 @@ public abstract class RecentsView<
* spring animation. As it passes the threshold of its settling state, its neighbors will
* spring in response to the perceived impact of the settling task.
*/
public SpringAnimation runTaskDismissSettlingSpringAnimation(TaskView draggedTaskView,
float velocity, boolean isDismissing, int dismissLength, int dismissThreshold,
float finalPosition, boolean shouldRemoveTaskView, boolean isSplitSelection,
@NonNull Function0<Unit> onEndRunnable) {
return mDismissUtils.createTaskDismissSettlingSpringAnimation(draggedTaskView, velocity,
public RecentsDismissUtils.SpringSet runTaskDismissSettlingSpringAnimation(
TaskView draggedTaskView, float velocity, boolean isDismissing, int dismissLength,
int dismissThreshold, float finalPosition, boolean shouldRemoveTaskView,
boolean isSplitSelection, @NonNull Function0<Unit> onEndRunnable) {
return mDismissUtils.createTaskDismissSpringAnimation(draggedTaskView, velocity,
isDismissing, dismissLength, dismissThreshold, finalPosition, shouldRemoveTaskView,
isSplitSelection, onEndRunnable);
}
@@ -1763,7 +1763,7 @@ public final class LauncherInstrumentation {
return mDevice;
}
private static String eventListToString(List<Integer> actualEvents) {
static String eventListToString(List<Integer> actualEvents) {
if (actualEvents.isEmpty()) return "no events";
return "["
@@ -1793,7 +1793,7 @@ public final class LauncherInstrumentation {
actionName);
}
private boolean isSwitchToStateEvent(
boolean isSwitchToStateEvent(
AccessibilityEvent event, int expectedState, List<Integer> actualEvents) {
if (!TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName())) return false;
@@ -16,6 +16,7 @@
package com.android.launcher3.tapl;
import static com.android.launcher3.tapl.LauncherInstrumentation.eventListToString;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_MODAL_TASK_STATE_ORDINAL;
import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_SPLIT_SELECT_ORDINAL;
@@ -23,6 +24,11 @@ import androidx.annotation.NonNull;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.testing.shared.TestProtocol;
import java.util.ArrayList;
import java.util.List;
/** Represents the menu of an overview task. */
public class OverviewTaskMenu {
@@ -43,11 +49,43 @@ public class OverviewTaskMenu {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"tap split menu item")) {
mLauncher.runToState(() -> mLauncher.clickLauncherObject(
boolean[] isSplitState = new boolean[]{false};
boolean[] isDismissEnded = new boolean[]{false};
final List<Integer> actualEvents = new ArrayList<>();
mLauncher.executeAndWaitForLauncherEvent(
() -> mLauncher.clickLauncherObject(
mLauncher.findObjectInContainer(mMenu, By.textStartsWith("Split"))),
OVERVIEW_SPLIT_SELECT_ORDINAL,
"tapping split menu item"
);
event -> {
// Wait for state changed to Split Select.
if (!isSplitState[0] && mLauncher.isSwitchToStateEvent(event,
OVERVIEW_SPLIT_SELECT_ORDINAL, actualEvents)) {
isSplitState[0] = true;
}
// Wait for dismiss animation to end.
if (!isDismissEnded[0]
&& TestProtocol.DISMISS_ANIMATION_ENDS_MESSAGE.equals(
event.getClassName())) {
isDismissEnded[0] = true;
}
return isSplitState[0] && isDismissEnded[0];
},
() -> {
StringBuilder failureMessage = new StringBuilder();
if (!isSplitState[0]) {
failureMessage.append(
"Failed to receive event for state change to Split Select. "
+ "Actual events: ").append(
eventListToString(actualEvents));
}
if (!isDismissEnded[0]) {
failureMessage.append(
"Failed to receive dismiss animation ends message.");
}
return failureMessage.toString();
},
"tapping split menu item");
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"tapped split menu item")) {