Merge "Ensure Recents Go layout finishes before remote anim begins" into ub-launcher3-qt-dev
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index 81090c1..3b664b7 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -28,9 +28,13 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
+import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import android.view.MotionEvent;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
@@ -45,8 +49,6 @@
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-import androidx.annotation.Nullable;
-
/**
* Handles quick switching to a recent task from the home screen.
*/
@@ -128,6 +130,10 @@
private void updateFullscreenProgress(float progress) {
if (mTaskToLaunch != null) {
mTaskToLaunch.setFullscreenProgress(progress);
+ int sysuiFlags = progress > UPDATE_SYSUI_FLAGS_THRESHOLD
+ ? mTaskToLaunch.getThumbnail().getSysUiStatusNavFlags()
+ : 0;
+ mLauncher.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, sysuiFlags);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
index 829e478..335e8b1 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AssistantTouchConsumer.java
@@ -21,9 +21,9 @@
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
-
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.FLING;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
@@ -38,11 +38,11 @@
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
-
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher;
+import com.android.launcher3.touch.SwipeDetector;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
@@ -50,12 +50,15 @@
/**
* Touch consumer for handling events to launch assistant from launcher
*/
-public class AssistantTouchConsumer extends DelegateInputConsumer {
+public class AssistantTouchConsumer extends DelegateInputConsumer
+ implements SwipeDetector.Listener {
+
private static final String TAG = "AssistantTouchConsumer";
private static final long RETRACT_ANIMATION_DURATION_MS = 300;
private static final String INVOCATION_TYPE_KEY = "invocation_type";
private static final int INVOCATION_TYPE_GESTURE = 1;
+ private static final int INVOCATION_TYPE_FLING = 6;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
@@ -77,6 +80,7 @@
private final float mSlop;
private final ISystemUiProxy mSysUiProxy;
private final Context mContext;
+ private final SwipeDetector mSwipeDetector;
public AssistantTouchConsumer(Context context, ISystemUiProxy systemUiProxy,
ActivityControlHelper activityControlHelper, InputConsumer delegate,
@@ -90,6 +94,8 @@
mAngleThreshold = res.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
mSlop = QuickStepContract.getQuickStepDragSlopPx();
mActivityControlHelper = activityControlHelper;
+ mSwipeDetector = new SwipeDetector(mContext, this, SwipeDetector.VERTICAL);
+ mSwipeDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
}
@Override
@@ -100,6 +106,7 @@
@Override
public void onMotionEvent(MotionEvent ev) {
// TODO add logging
+ mSwipeDetector.onTouchEvent(ev);
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
@@ -146,7 +153,7 @@
// Determine if angle is larger than threshold for assistant detection
float angle = (float) Math.toDegrees(
- Math.atan2(mDownPos.y - mLastPos.y, mDownPos.x - mLastPos.x));
+ Math.atan2(mDownPos.y - mLastPos.y, mDownPos.x - mLastPos.x));
mDirection = angle > 90 ? UPLEFT : UPRIGHT;
angle = angle > 90 ? 180 - angle : angle;
@@ -159,7 +166,7 @@
} else {
// Movement
mDistance = (float) Math.hypot(mLastPos.x - mStartDragPos.x,
- mLastPos.y - mStartDragPos.y);
+ mLastPos.y - mStartDragPos.y);
if (mDistance >= 0) {
final long diff = SystemClock.uptimeMillis() - mDragTime;
mTimeFraction = Math.min(diff * 1f / mTimeThreshold, 1);
@@ -172,18 +179,18 @@
case ACTION_UP:
if (mState != STATE_DELEGATE_ACTIVE && !mLaunchedAssistant) {
ValueAnimator animator = ValueAnimator.ofFloat(mLastProgress, 0)
- .setDuration(RETRACT_ANIMATION_DURATION_MS);
+ .setDuration(RETRACT_ANIMATION_DURATION_MS);
UserEventDispatcher.newInstance(mContext).logActionOnContainer(
- SWIPE_NOOP, mDirection, NAVBAR);
+ SWIPE_NOOP, mDirection, NAVBAR);
animator.addUpdateListener(valueAnimator -> {
- float progress = (float) valueAnimator.getAnimatedValue();
- try {
+ float progress = (float) valueAnimator.getAnimatedValue();
+ try {
- mSysUiProxy.onAssistantProgress(progress);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send SysUI start/send assistant progress: "
- + progress, e);
- }
+ mSysUiProxy.onAssistantProgress(progress);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send SysUI start/send assistant progress: "
+ + progress, e);
+ }
});
animator.setInterpolator(Interpolators.DEACCEL_2);
animator.start();
@@ -200,30 +207,32 @@
private void updateAssistantProgress() {
if (!mLaunchedAssistant) {
- float progress = Math.min(mDistance * 1f / mDistThreshold, 1) * mTimeFraction;
- mLastProgress = progress;
- try {
- mSysUiProxy.onAssistantProgress(progress);
- if (mDistance >= mDistThreshold && mTimeFraction >= 1) {
- UserEventDispatcher.newInstance(mContext).logActionOnContainer(
- SWIPE, mDirection, NAVBAR);
- Bundle args = new Bundle();
- args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
+ mLastProgress = Math.min(mDistance * 1f / mDistThreshold, 1) * mTimeFraction;
+ updateAssistant(SWIPE);
+ }
+ }
- BaseDraggingActivity launcherActivity =
- mActivityControlHelper.getCreatedActivity();
- if (launcherActivity != null) {
- launcherActivity.getRootView().
- performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
- HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
- }
+ private void updateAssistant(int gestureType) {
+ try {
+ mSysUiProxy.onAssistantProgress(mLastProgress);
+ if (gestureType == FLING || (mDistance >= mDistThreshold && mTimeFraction >= 1)) {
+ UserEventDispatcher.newInstance(mContext)
+ .logActionOnContainer(gestureType, mDirection, NAVBAR);
+ Bundle args = new Bundle();
+ args.putInt(INVOCATION_TYPE_KEY, INVOCATION_TYPE_GESTURE);
- mSysUiProxy.startAssistant(args);
- mLaunchedAssistant = true;
+ BaseDraggingActivity launcherActivity = mActivityControlHelper.getCreatedActivity();
+ if (launcherActivity != null) {
+ launcherActivity.getRootView().performHapticFeedback(
+ 13, // HapticFeedbackConstants.GESTURE_END
+ HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + progress, e);
+
+ mSysUiProxy.startAssistant(args);
+ mLaunchedAssistant = true;
}
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to send SysUI start/send assistant progress: " + mLastProgress, e);
}
}
@@ -234,4 +243,22 @@
final int size = res.getDimensionPixelSize(R.dimen.gestures_assistant_size);
return (ev.getX() > width - size || ev.getX() < size) && ev.getY() > height - size;
}
+
+ @Override
+ public void onDragStart(boolean start) {
+ // do nothing
+ }
+
+ @Override
+ public boolean onDrag(float displacement) {
+ return false;
+ }
+
+ @Override
+ public void onDragEnd(float velocity, boolean fling) {
+ if (fling) {
+ mLastProgress = 1;
+ updateAssistant(FLING);
+ }
+ }
}
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 50f25fb..e932452 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -270,9 +270,9 @@
playScaleDownAnim(anim, activity, endState);
anim.setDuration(transitionLength * 2);
- activity.getStateManager().setCurrentAnimation(anim);
AnimatorPlaybackController controller =
AnimatorPlaybackController.wrap(anim, transitionLength * 2);
+ activity.getStateManager().setCurrentUserControlledAnimation(controller);
// Since we are changing the start position of the UI, reapply the state, at the end
controller.setEndAction(() -> {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
index e3dcadc..e20ef52 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskSystemShortcut.java
@@ -16,6 +16,7 @@
package com.android.quickstep;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import android.app.Activity;
@@ -116,21 +117,22 @@
mHandler = new Handler(Looper.getMainLooper());
}
- protected abstract boolean isAvailable(BaseDraggingActivity activity);
+ protected abstract boolean isAvailable(BaseDraggingActivity activity, int displayId);
protected abstract ActivityOptions makeLaunchOptions(Activity activity);
protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
@Override
public View.OnClickListener getOnClickListener(
BaseDraggingActivity activity, TaskView taskView) {
- if (!isAvailable(activity)) {
- return null;
- }
final Task task = taskView.getTask();
final int taskId = task.key.id;
+ final int displayId = task.key.displayId;
if (!task.isDockable) {
return null;
}
+ if (!isAvailable(activity, displayId)) {
+ return null;
+ }
final RecentsView recentsView = activity.getOverviewPanel();
final TaskThumbnailView thumbnailView = taskView.getThumbnail();
@@ -218,9 +220,13 @@
}
@Override
- protected boolean isAvailable(BaseDraggingActivity activity) {
- // Don't show menu-item if already in multi-window
- return !activity.getDeviceProfile().isMultiWindowMode;
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+ // Don't show menu-item if already in multi-window and the task is from
+ // the secondary display.
+ // TODO(b/118266305): Temporarily disable splitscreen for secondary display while new
+ // implementation is enabled
+ return !activity.getDeviceProfile().isMultiWindowMode
+ && displayId == DEFAULT_DISPLAY;
}
@Override
@@ -256,7 +262,7 @@
}
@Override
- protected boolean isAvailable(BaseDraggingActivity activity) {
+ protected boolean isAvailable(BaseDraggingActivity activity, int displayId) {
return ActivityManagerWrapper.getInstance().supportsFreeformMultiWindow(activity);
}
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 936f0aa..58ae5eb 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT;
+import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
@@ -654,8 +655,7 @@
mTransformParams.setProgress(shift).setOffsetX(offsetX).setOffsetScale(offsetScale);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
- mRecentsAnimationWrapper.setWindowThresholdCrossed(
- shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD);
+ updateSysUiFlags(shift);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@@ -700,6 +700,18 @@
? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart));
}
+ private void updateSysUiFlags(float windowProgress) {
+ if (mRecentsView != null) {
+ // We will handle the sysui flags based on the centermost task view.
+ mRecentsAnimationWrapper.setWindowThresholdCrossed(true);
+ int sysuiFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD
+ ? 0
+ : mRecentsView.getTaskViewAt(mRecentsView.getPageNearestToCenterOfScreen())
+ .getThumbnail().getSysUiStatusNavFlags();
+ mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, sysuiFlags);
+ }
+ }
+
@Override
public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext).getDeviceProfile(mContext);
@@ -1091,6 +1103,7 @@
windowAlphaThreshold, mClipAnimationHelper.getCurrentCornerRadius(), false);
}
+ updateSysUiFlags(Math.max(progress, mCurrentShift.value));
});
anim.addAnimatorListener(new AnimationSuccessListener() {
@Override
diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
index 1817135..ffe3633 100644
--- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
+++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java
@@ -40,7 +40,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -70,6 +69,8 @@
// Disable app tracker
AppLaunchTracker.INSTANCE.initializeForTesting(new AppLaunchTracker());
+ PredictionUiStateManager.INSTANCE.initializeForTesting(null);
+
mCallback = PredictionUiStateManager.INSTANCE.get(mTargetContext).appPredictorCallback(
Client.HOME);
@@ -85,7 +86,6 @@
* Test that prediction UI is updated as soon as we get predictions from the system
*/
@Test
- @Ignore // b/131772711: this really fails (when being run as a part of the whole test suite)!
public void testPredictionExistsInAllApps() {
mActivityMonitor.startLauncher();
mLauncher.pressHome().switchToAllApps();
@@ -118,7 +118,6 @@
}
@Test
- @Ignore // b/131772711 - this was failing in the lab
public void testPredictionsDisabled() {
mActivityMonitor.startLauncher();
sendPredictionUpdate();
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 3b2a7b8..60d2850 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -78,7 +78,8 @@
final long downTime = SystemClock.uptimeMillis();
mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
- mLauncher.movePointer(downTime, ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION, start, end);
+ mLauncher.movePointer(
+ downTime, downTime, ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION, start, end);
LauncherInstrumentation.sleep(ZERO_BUTTON_SWIPE_UP_HOLD_DURATION);
mLauncher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end);
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 87ef044..fd2eabb 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -70,6 +70,7 @@
private static final String TAG = "Tapl";
private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20;
+ private static final int GESTURE_STEP_MS = 16;
// Types for launcher containers that the user is interacting with. "Background" is a
// pseudo-container corresponding to inactive launcher covered by another app.
@@ -359,7 +360,7 @@
? NORMAL_STATE_ORDINAL : BACKGROUND_APP_STATE_ORDINAL;
final Point displaySize = getRealDisplaySize();
- swipe(
+ swipeViaMovePointer(
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, 0,
finalState, ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME);
@@ -543,8 +544,28 @@
}
void swipe(int startX, int startY, int endX, int endY, int expectedState, int steps) {
+ changeStateViaGesture(startX, startY, endX, endY, expectedState,
+ () -> mDevice.swipe(startX, startY, endX, endY, steps));
+ }
+
+ void swipeViaMovePointer(
+ int startX, int startY, int endX, int endY, int expectedState, int steps) {
+ changeStateViaGesture(startX, startY, endX, endY, expectedState, () -> {
+ final long downTime = SystemClock.uptimeMillis();
+ final Point start = new Point(startX, startY);
+ final Point end = new Point(endX, endY);
+ sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
+ final long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start,
+ end);
+ sendPointer(
+ downTime, endTime, MotionEvent.ACTION_UP, end);
+ });
+ }
+
+ private void changeStateViaGesture(int startX, int startY, int endX, int endY,
+ int expectedState, Runnable gesture) {
final Bundle parcel = (Bundle) executeAndWaitForEvent(
- () -> mDevice.swipe(startX, startY, endX, endY, steps),
+ gesture,
event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()),
"Swipe failed to receive an event for the swipe end: " + startX + ", " + startY
+ ", " + endX + ", " + endY);
@@ -589,21 +610,22 @@
event.recycle();
}
- void movePointer(long downTime, long duration, Point from, Point to) {
+ long movePointer(long downTime, long startTime, long duration, Point from, Point to) {
final Point point = new Point();
- final long startTime = SystemClock.uptimeMillis();
- for (; ; ) {
- sleep(16);
+ long steps = duration / GESTURE_STEP_MS;
+ long currentTime = startTime;
+ for (long i = 0; i < steps; ++i) {
+ sleep(GESTURE_STEP_MS);
- final long currentTime = SystemClock.uptimeMillis();
+ currentTime += GESTURE_STEP_MS;
final float progress = (currentTime - startTime) / (float) duration;
- if (progress > 1) return;
point.x = from.x + (int) (progress * (to.x - from.x));
point.y = from.y + (int) (progress * (to.y - from.y));
sendPointer(downTime, currentTime, MotionEvent.ACTION_MOVE, point);
}
+ return currentTime;
}
public static boolean isGesturalMode(Context context) {
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 9a47aef..e8a0b54 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -150,7 +150,8 @@
LauncherInstrumentation.log("dragIconToWorkspace: sent down");
launcher.waitForLauncherObject(longPressIndicator);
LauncherInstrumentation.log("dragIconToWorkspace: indicator");
- launcher.movePointer(downTime, DRAG_DURACTION, launchableCenter, dest);
+ launcher.movePointer(
+ downTime, SystemClock.uptimeMillis(), DRAG_DURACTION, launchableCenter, dest);
LauncherInstrumentation.log("dragIconToWorkspace: moved pointer");
launcher.sendPointer(
downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest);