Merge "Printing TouchInteractionService state on test failures" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/res/values/dimens.xml b/quickstep/recents_ui_overrides/res/values/dimens.xml
index b316edd..c80e531 100644
--- a/quickstep/recents_ui_overrides/res/values/dimens.xml
+++ b/quickstep/recents_ui_overrides/res/values/dimens.xml
@@ -27,4 +27,5 @@
<!-- Swipe up to home related -->
<dimen name="swipe_up_fling_min_visible_change">18dp</dimen>
<dimen name="swipe_up_y_overshoot">10dp</dimen>
+ <dimen name="swipe_up_max_workspace_trans_y">-80dp</dimen>
</resources>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
index 00e4a9d..5af09f7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -57,6 +57,7 @@
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -151,8 +152,21 @@
@NonNull
@Override
public AnimatorPlaybackController createActivityAnimationToHome() {
+ // Return an empty APC here since we have an non-user controlled animation to home.
long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
- return activity.getStateManager().createAnimationToNewWorkspace(NORMAL, accuracy);
+ AnimatorSet as = new AnimatorSet();
+ as.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ activity.getStateManager().goToState(NORMAL, false);
+ }
+ });
+ return AnimatorPlaybackController.wrap(as, accuracy);
+ }
+
+ @Override
+ public void playAtomicAnimation(float velocity) {
+ new StaggeredWorkspaceAnim(activity, workspaceView, velocity).start();
}
};
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
index ca966c8..0d0478a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -1057,6 +1057,7 @@
setStateOnUiThread(target.endState);
}
});
+ homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
windowAnim.start(velocityPxPerMs);
mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim);
mLauncherTransitionController = null;
@@ -1134,12 +1135,10 @@
// FolderIconView can be seen morphing into the icon shape.
final float windowAlphaThreshold = isFloatingIconView ? 1f - SHAPE_PROGRESS_DURATION : 1f;
anim.addOnUpdateListener((currentRect, progress) -> {
- float interpolatedProgress = Interpolators.ACCEL_1_5.getInterpolation(progress);
-
homeAnim.setPlayFraction(progress);
- float windowAlpha = Utilities.mapToRange(interpolatedProgress, 0,
- windowAlphaThreshold, 1f, 0f, Interpolators.LINEAR);
+ float windowAlpha = Math.max(0, Utilities.mapToRange(progress, 0,
+ windowAlphaThreshold, 1f, 0f, Interpolators.LINEAR));
mTransformParams.setProgress(progress)
.setCurrentRectAndTargetAlpha(currentRect, windowAlpha);
mClipAnimationHelper.applyTransform(targetSet, mTransformParams,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
new file mode 100644
index 0000000..93b6e4b
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+import androidx.dynamicanimation.animation.SpringForce;
+
+import com.android.launcher3.CellLayout;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils.ViewProgressProperty;
+import com.android.launcher3.R;
+import com.android.launcher3.ShortcutAndWidgetContainer;
+import com.android.launcher3.anim.SpringObjectAnimator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+/**
+ * Creates an animation where all the workspace items are moved into their final location,
+ * staggered row by row from the bottom up.
+ * This is used in conjunction with the swipe up to home animation.
+ */
+public class StaggeredWorkspaceAnim {
+
+ private static final int APP_CLOSE_ROW_START_DELAY_MS = 16;
+ private static final int ALPHA_DURATION_MS = 200;
+
+ private static final float MAX_VELOCITY_PX_PER_S = 22f;
+
+ private static final float DAMPING_RATIO =
+ (SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY + SpringForce.DAMPING_RATIO_LOW_BOUNCY) / 2f;
+ private static final float STIFFNESS = SpringForce.STIFFNESS_LOW;
+
+ private final float mVelocity;
+ private final float mSpringTransY;
+ private final View mViewToIgnore;
+
+ private final List<ValueAnimator> mAnimators = new ArrayList<>();
+
+ /**
+ * @param floatingViewOriginalView The FloatingIconView's original view.
+ */
+ public StaggeredWorkspaceAnim(Launcher launcher, @Nullable View floatingViewOriginalView,
+ float velocity) {
+ mVelocity = velocity;
+ // We ignore this view since it's visibility and position is controlled by
+ // the FloatingIconView.
+ mViewToIgnore = floatingViewOriginalView;
+
+ // Scale the translationY based on the initial velocity to better sync the workspace items
+ // with the floating view.
+ float transFactor = 0.1f + 0.9f * Math.abs(velocity) / MAX_VELOCITY_PX_PER_S;
+ mSpringTransY = transFactor * launcher.getResources()
+ .getDimensionPixelSize(R.dimen.swipe_up_max_workspace_trans_y);;
+
+ DeviceProfile grid = launcher.getDeviceProfile();
+ ShortcutAndWidgetContainer currentPage = ((CellLayout) launcher.getWorkspace()
+ .getChildAt(launcher.getWorkspace().getCurrentPage()))
+ .getShortcutsAndWidgets();
+
+ // Hotseat and QSB takes up two additional rows.
+ int totalRows = grid.inv.numRows + (grid.isVerticalBarLayout() ? 0 : 2);
+
+ // Set up springs on workspace items.
+ for (int i = currentPage.getChildCount() - 1; i >= 0; i--) {
+ View child = currentPage.getChildAt(i);
+ CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
+ addStaggeredAnimationForView(child, lp.cellY + lp.cellVSpan, totalRows);
+ }
+
+ // Set up springs for the hotseat and qsb.
+ if (grid.isVerticalBarLayout()) {
+ ViewGroup hotseat = (ViewGroup) launcher.getHotseat().getChildAt(0);
+ for (int i = hotseat.getChildCount() - 1; i >= 0; i--) {
+ View child = hotseat.getChildAt(i);
+ CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
+ addStaggeredAnimationForView(child, lp.cellY + 1, totalRows);
+ }
+ } else {
+ View hotseat = launcher.getHotseat().getChildAt(0);
+ addStaggeredAnimationForView(hotseat, grid.inv.numRows + 1, totalRows);
+
+ View qsb = launcher.findViewById(R.id.search_container_all_apps);
+ addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
+ }
+ }
+
+ /**
+ * Starts the animation.
+ */
+ public void start() {
+ for (Animator a : mAnimators) {
+ if (a instanceof SpringObjectAnimator) {
+ ((SpringObjectAnimator) a).startSpring(1f, mVelocity, null);
+ } else {
+ a.start();
+ }
+ }
+ }
+
+ /**
+ * Adds an alpha/trans animator for {@param v}, with a start delay based on the view's row.
+ *
+ * @param v A view on the workspace.
+ * @param row The bottom-most row that contains the view.
+ * @param totalRows Total number of rows.
+ */
+ private void addStaggeredAnimationForView(View v, int row, int totalRows) {
+ if (v == mViewToIgnore) {
+ return;
+ }
+
+ // Invert the rows, because we stagger starting from the bottom of the screen.
+ int invertedRow = totalRows - row;
+ // Add 1 to the inverted row so that the bottom most row has a start delay.
+ long startDelay = (long) ((invertedRow + 1) * APP_CLOSE_ROW_START_DELAY_MS);
+
+ v.setTranslationY(mSpringTransY);
+ SpringObjectAnimator springTransY = new SpringObjectAnimator<>(
+ new ViewProgressProperty(v, View.TRANSLATION_Y), "staggeredSpringTransY", 1f,
+ DAMPING_RATIO, STIFFNESS, mSpringTransY, 0);
+ springTransY.setStartDelay(startDelay);
+ mAnimators.add(springTransY);
+
+ v.setAlpha(0);
+ ObjectAnimator alpha = ObjectAnimator.ofFloat(v, View.ALPHA, 0f, 1f);
+ alpha.setInterpolator(LINEAR);
+ alpha.setDuration(ALPHA_DURATION_MS);
+ alpha.setStartDelay(startDelay);
+ mAnimators.add(alpha);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 3364377..917465f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -145,11 +145,13 @@
};
private final TaskOutlineProvider mOutlineProvider;
+ private final FooterOutlineProvider mFooterOutlineProvider;
private Task mTask;
private TaskThumbnailView mSnapshotView;
private TaskMenuView mMenuView;
private IconView mIconView;
+ private View mTaskFooterContainer;
private DigitalWellBeingToast mDigitalWellBeingToast;
private float mCurveScale;
private float mFullscreenProgress;
@@ -203,6 +205,7 @@
mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
mCurrentFullscreenParams = new FullscreenDrawParams(mCornerRadius);
mOutlineProvider = new TaskOutlineProvider(getResources(), mCurrentFullscreenParams);
+ mFooterOutlineProvider = new FooterOutlineProvider(mCurrentFullscreenParams);
setOutlineProvider(mOutlineProvider);
}
@@ -212,6 +215,9 @@
mSnapshotView = findViewById(R.id.snapshot);
mIconView = findViewById(R.id.icon);
mDigitalWellBeingToast = findViewById(R.id.digital_well_being_toast);
+ mTaskFooterContainer = findViewById(R.id.task_footer_container);
+ mTaskFooterContainer.setOutlineProvider(mFooterOutlineProvider);
+ mTaskFooterContainer.setClipToOutline(true);
}
public TaskMenuView getMenuView() {
@@ -410,6 +416,15 @@
.getInterpolation(progress);
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
+
+ int footerVerticalOffset = (int) (mTaskFooterContainer.getHeight() * (1.0f - scale));
+ mTaskFooterContainer.setTranslationY(
+ mCurrentFullscreenParams.mCurrentDrawnInsets.bottom +
+ mCurrentFullscreenParams.mCurrentDrawnInsets.top +
+ footerVerticalOffset);
+ mFooterOutlineProvider.setFullscreenDrawParams(
+ mCurrentFullscreenParams, footerVerticalOffset);
+ mTaskFooterContainer.invalidateOutline();
}
public void setIconScaleAnimStartProgress(float startProgress) {
@@ -550,6 +565,29 @@
}
}
+ private static final class FooterOutlineProvider extends ViewOutlineProvider {
+
+ private FullscreenDrawParams mFullscreenDrawParams;
+ private int mVerticalOffset;
+ private final Rect mOutlineRect = new Rect();
+
+ FooterOutlineProvider(FullscreenDrawParams params) {
+ mFullscreenDrawParams = params;
+ }
+
+ void setFullscreenDrawParams(FullscreenDrawParams params, int verticalOffset) {
+ mFullscreenDrawParams = params;
+ mVerticalOffset = verticalOffset;
+ }
+
+ @Override
+ public void getOutline(View view, Outline outline) {
+ mOutlineRect.set(0, 0, view.getWidth(), view.getHeight());
+ mOutlineRect.offset(0, -mVerticalOffset);
+ outline.setRoundRect(mOutlineRect, mFullscreenDrawParams.mCurrentDrawnCornerRadius);
+ }
+ }
+
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
@@ -639,7 +677,6 @@
}
mFullscreenProgress = progress;
boolean isFullscreen = mFullscreenProgress > 0;
- setIconScaleAndDim(progress, true /* invert */);
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
setClipChildren(!isFullscreen);
setClipToPadding(!isFullscreen);
@@ -663,6 +700,9 @@
/ (getWidth() + currentInsetsLeft + currentInsetsRight));
}
+ // Some of the items in here are dependent on the current fullscreen params
+ setIconScaleAndDim(progress, true /* invert */);
+
thumbnail.setFullscreenParams(mCurrentFullscreenParams);
mOutlineProvider.setFullscreenParams(mCurrentFullscreenParams);
invalidateOutline();
diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
index 95ae312..79540c1 100644
--- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java
@@ -278,7 +278,7 @@
if (launcherClosing) {
Pair<AnimatorSet, Runnable> launcherContentAnimator =
getLauncherContentAnimator(true /* isAppOpening */,
- new float[] {0, mContentTransY});
+ new float[] {0, -mContentTransY});
anim.play(launcherContentAnimator.first);
anim.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index b0acd9b..279a946 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -143,5 +143,9 @@
@NonNull RectF getWindowTargetRect();
@NonNull AnimatorPlaybackController createActivityAnimationToHome();
+
+ default void playAtomicAnimation(float velocity) {
+ // No-op
+ }
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
index e552f56..c3e46ea 100644
--- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
+++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java
@@ -133,7 +133,7 @@
for (int i = 0; i != 100; ++i) {
if (mLauncher.getNavigationModel() == expectedMode) {
- Thread.sleep(1000);
+ Thread.sleep(5000);
return;
}
Thread.sleep(100);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 8a8a2fb..bde87cb 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -288,7 +288,9 @@
InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
// Re-init grid
- initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
+ // TODO(b/131867841): We pass in null here so that we can calculate the closest profile
+ // without the bias of the grid name.
+ initGrid(context, null);
int changeFlags = 0;
if (numRows != oldProfile.numRows ||
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 434918d..2ad92e1 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -23,6 +23,7 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LabelComparator;
@@ -300,6 +301,11 @@
}
private void refreshRecyclerView() {
+ if (TestProtocol.sDebugTracing) {
+ android.util.Log.d(TestProtocol.NO_START_TAG,
+ "refreshRecyclerView @ " + android.util.Log.getStackTraceString(
+ new Throwable()));
+ }
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
diff --git a/src/com/android/launcher3/anim/SpringObjectAnimator.java b/src/com/android/launcher3/anim/SpringObjectAnimator.java
index f74590b..b1395af 100644
--- a/src/com/android/launcher3/anim/SpringObjectAnimator.java
+++ b/src/com/android/launcher3/anim/SpringObjectAnimator.java
@@ -22,6 +22,8 @@
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
import android.util.Property;
@@ -139,7 +141,7 @@
/**
* Initializes and sets up the spring to take over controlling the object.
*/
- void startSpring(float end, float velocity, OnAnimationEndListener endListener) {
+ public void startSpring(float end, float velocity, OnAnimationEndListener endListener) {
// Cancel the spring so we can set new start velocity and final position. We need to remove
// the listener since the spring is not actually ending.
mSpring.removeEndListener(endListener);
@@ -149,7 +151,13 @@
mProperty.switchToSpring();
mSpring.setStartVelocity(velocity);
- mSpring.animateToFinalPosition(end == 0 ? mValues[0] : mValues[1]);
+
+ float startValue = end == 0 ? mValues[1] : mValues[0];
+ float endValue = end == 0 ? mValues[0] : mValues[1];
+ mSpring.setStartValue(startValue);
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ mSpring.animateToFinalPosition(endValue);
+ }, getStartDelay());
}
@Override
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 03cbb21..cf0ee62 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -229,7 +229,7 @@
mTaskCornerRadius = cornerRadius / scale;
if (mIsAdaptiveIcon) {
- if (!isOpening && shapeRevealProgress >= 0) {
+ if (!isOpening && progress >= shapeProgressStart) {
if (mRevealAnimator == null) {
mRevealAnimator = (ValueAnimator) IconShape.getShape().createRevealAnimator(
this, mStartRevealRect, mOutline, mTaskCornerRadius, !isOpening);
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 4261988..5190f00 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -53,7 +53,7 @@
private Background launch(BySelector selector) {
LauncherInstrumentation.log("Launchable.launch before click " +
- mObject.getVisibleCenter());
+ mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
mLauncher.getTestInfo(TestProtocol.REQUEST_ENABLE_DEBUG_TRACING);
mLauncher.assertTrue(
"Launching an app didn't open a new window: " + mObject.getText(),