Merge "Delegate horizontal scrolls from the Hotseat to the Workspace" into ub-launcher3-rvc-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index f1b71e8..f1db144 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -48,12 +48,16 @@
HotseatContainer hotseat = 2;
FolderContainer folder = 3;
AllAppsContainer all_apps_container = 4;
+ WidgetsContainer widgets_container = 5;
}
}
message AllAppsContainer {
}
+message WidgetsContainer {
+}
+
enum Origin {
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
diff --git a/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
index ffe906c..7b3e378 100644
--- a/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
+++ b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
@@ -18,6 +18,7 @@
android:id="@+id/drag_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
android:fitsSystemWindows="true">
<com.android.quickstep.fallback.FallbackRecentsView
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 7a73e50..1fe3643 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -274,6 +274,7 @@
}
if (mAppPredictor != null) {
mAppPredictor.destroy();
+ mAppPredictor = null;
}
WeakReference<HotseatPredictionController> controllerRef = new WeakReference<>(this);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index ad6a10b..95087ba 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -217,7 +217,9 @@
break;
}
case OVERVIEW_STATE_ORDINAL: {
- DiscoveryBounce.showForOverviewIfNeeded(this);
+ RecentsView recentsView = getOverviewPanel();
+ DiscoveryBounce.showForOverviewIfNeeded(this,
+ recentsView.getPagedOrientationHandler());
RecentsView rv = getOverviewPanel();
sendCustomAccessibilityEvent(
rv.getPageAt(rv.getCurrentPage()), TYPE_VIEW_FOCUSED, null);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index a1cc60e..085b9b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -71,7 +71,7 @@
builder.addOnFrameCallback(mRecentsView::loadVisibleTaskData);
mRecentsView.updateEmptyMessage();
} else {
- builder.getAnim().addListener(
+ builder.addListener(
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index fa0d3f3..8ff05f2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -45,8 +45,10 @@
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
return super.getVerticalProgress(launcher);
}
+ RecentsView recentsView = launcher.getOverviewPanel();
int transitionLength = LayoutUtils.getShelfTrackingDistance(launcher,
- launcher.getDeviceProfile());
+ launcher.getDeviceProfile(),
+ recentsView.getPagedOrientationHandler());
AllAppsTransitionController controller = launcher.getAllAppsController();
float scrollRange = Math.max(controller.getShiftRange(), 1);
float progressDelta = (transitionLength / scrollRange);
@@ -73,9 +75,11 @@
public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) {
if ((getVisibleElements(launcher) & HOTSEAT_ICONS) != 0) {
// Translate hotseat offscreen if we show it in overview.
+ RecentsView recentsView = launcher.getOverviewPanel();
ScaleAndTranslation scaleAndTranslation = super.getHotseatScaleAndTranslation(launcher);
scaleAndTranslation.translationY += LayoutUtils.getShelfTrackingDistance(launcher,
- launcher.getDeviceProfile());
+ launcher.getDeviceProfile(),
+ recentsView.getPagedOrientationHandler());
return scaleAndTranslation;
}
return super.getHotseatScaleAndTranslation(launcher);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 9f31608..d174bfd 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
@@ -127,7 +128,9 @@
@Override
public int getVisibleElements(Launcher launcher) {
- if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher)) {
+ RecentsView recentsView = launcher.getOverviewPanel();
+ if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ||
+ hideShelfInTwoButtonLandscape(launcher, recentsView.getPagedOrientationHandler())) {
return OVERVIEW_BUTTONS;
} else if (launcher.getDeviceProfile().isVerticalBarLayout()) {
return VERTICAL_SWIPE_INDICATOR | OVERVIEW_BUTTONS;
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 11593a1..94c7771 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -49,64 +49,62 @@
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
-import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.CellLayout;
import com.android.launcher3.Hotseat;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.anim.SpringAnimationBuilder;
import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.util.RecentsAtomicAnimationFactory;
import com.android.quickstep.views.RecentsView;
/**
* Animation factory for quickstep specific transitions
*/
-public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<LauncherState> {
+public class QuickstepAtomicAnimationFactory extends
+ RecentsAtomicAnimationFactory<Launcher, LauncherState> {
// Scale recents takes before animating in
private static final float RECENTS_PREPARE_SCALE = 1.33f;
- public static final int INDEX_SHELF_ANIM = 0;
- public static final int INDEX_RECENTS_FADE_ANIM = 1;
- public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
- public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
- private static final int ANIM_COUNT = 4;
+ public static final int INDEX_SHELF_ANIM = RecentsAtomicAnimationFactory.NEXT_INDEX + 0;
+ public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM =
+ RecentsAtomicAnimationFactory.NEXT_INDEX + 1;
+
+ private static final int MY_ANIM_COUNT = 2;
+ protected static final int NEXT_INDEX = RecentsAtomicAnimationFactory.NEXT_INDEX
+ + MY_ANIM_COUNT;
public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
- private final QuickstepLauncher mLauncher;
-
- public QuickstepAtomicAnimationFactory(QuickstepLauncher launcher) {
- super(ANIM_COUNT);
- mLauncher = launcher;
+ public QuickstepAtomicAnimationFactory(QuickstepLauncher activity) {
+ super(activity, MY_ANIM_COUNT);
}
@Override
public Animator createStateElementAnimation(int index, float... values) {
switch (index) {
case INDEX_SHELF_ANIM: {
- AllAppsTransitionController aatc = mLauncher.getAllAppsController();
+ AllAppsTransitionController aatc = mActivity.getAllAppsController();
Animator springAnim = aatc.createSpringAnimation(values);
- if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ if ((OVERVIEW.getVisibleElements(mActivity) & HOTSEAT_ICONS) != 0) {
// Translate hotseat with the shelf until reaching overview.
- float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
- ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
+ float overviewProgress = OVERVIEW.getVerticalProgress(mActivity);
+ ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mActivity);
float shiftRange = aatc.getShiftRange();
if (values.length == 1) {
values = new float[] {aatc.getProgress(), values[0]};
@@ -114,9 +112,9 @@
ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
hotseatAnim.addUpdateListener(anim -> {
float progress = (Float) anim.getAnimatedValue();
- if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
+ if (progress >= overviewProgress || mActivity.isInState(BACKGROUND_APP)) {
float hotseatShift = (progress - overviewProgress) * shiftRange;
- mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
+ mActivity.getHotseat().setTranslationY(hotseatShift + sat.translationY);
}
});
hotseatAnim.setInterpolator(LINEAR);
@@ -130,34 +128,21 @@
return springAnim;
}
- case INDEX_RECENTS_FADE_ANIM:
- return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
- RecentsView.CONTENT_ALPHA, values);
- case INDEX_RECENTS_TRANSLATE_X_ANIM: {
- RecentsView rv = mLauncher.getOverviewPanel();
- return new SpringAnimationBuilder(mLauncher)
- .setMinimumVisibleChange(1f / rv.getPageOffsetScale())
- .setDampingRatio(0.8f)
- .setStiffness(250)
- .setValues(values)
- .build(rv, ADJACENT_PAGE_OFFSET);
- }
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
StateAnimationConfig config = new StateAnimationConfig();
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
- if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
+ if ((OVERVIEW.getVisibleElements(mActivity) & HOTSEAT_ICONS) != 0) {
config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
}
- StateManager<LauncherState> stateManager = mLauncher.getStateManager();
+ StateManager<LauncherState> stateManager = mActivity.getStateManager();
return stateManager.createAtomicAnimation(
stateManager.getCurrentStableState(), OVERVIEW, config);
}
-
default:
return super.createStateElementAnimation(index, values);
}
@@ -172,7 +157,7 @@
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
- Workspace workspace = mLauncher.getWorkspace();
+ Workspace workspace = mActivity.getWorkspace();
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
@@ -186,13 +171,13 @@
workspace.setScaleX(0.92f);
workspace.setScaleY(0.92f);
}
- Hotseat hotseat = mLauncher.getHotseat();
+ Hotseat hotseat = mActivity.getHotseat();
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
if (!isHotseatVisible) {
hotseat.setScaleX(0.92f);
hotseat.setScaleY(0.92f);
if (ENABLE_OVERVIEW_ACTIONS.get()) {
- AllAppsContainerView qsbContainer = mLauncher.getAppsView();
+ AllAppsContainerView qsbContainer = mActivity.getAppsView();
View qsb = qsbContainer.getSearchView();
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
if (!qsbVisible) {
@@ -209,7 +194,7 @@
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
} else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) {
- if (SysUINavigationMode.getMode(mLauncher) == NO_BUTTON) {
+ if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
config.setInterpolator(ANIM_WORKSPACE_SCALE,
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
@@ -217,7 +202,7 @@
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
// Scale up the recents, if it is not coming from the side
- RecentsView overview = mLauncher.getOverviewPanel();
+ RecentsView overview = mActivity.getOverviewPanel();
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
}
@@ -225,7 +210,7 @@
config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
- && removeShelfFromOverview(mLauncher)
+ && removeShelfFromOverview(mActivity)
? OVERSHOOT_1_2
: OVERSHOOT_1_7;
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 7385658..c1b68ab 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -116,7 +116,7 @@
mRecentsView = mLauncher.getOverviewPanel();
mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
mYRange = LayoutUtils.getShelfTrackingDistance(
- mLauncher, mLauncher.getDeviceProfile());
+ mLauncher, mLauncher.getDeviceProfile(), mRecentsView.getPagedOrientationHandler());
mMotionPauseDetector = new MotionPauseDetector(mLauncher);
mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
index f38ff10..f4d1629 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
@@ -18,29 +18,26 @@
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
+import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
import android.animation.Animator;
import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.graphics.Rect;
import android.util.Log;
-import android.view.View;
+import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.util.RemoteAnimationProvider;
+import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
-import com.android.systemui.shared.system.TransactionCompat;
/**
* Provider for the atomic (for 3-button mode) remote window animation from the app to the overview.
@@ -80,7 +77,6 @@
controller.dispatchOnStart();
controller.getAnimationPlayer().end();
});
- factory.onRemoteAnimationReceived(null);
factory.createActivityInterface(RECENTS_LAUNCH_DURATION);
factory.setRecentsAttachedToAppWindow(true, false);
mActivity = activity;
@@ -97,32 +93,25 @@
@Override
public AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets) {
- if (mRecentsView != null) {
- mRecentsView.setRunningTaskIconScaledDown(true);
+ PendingAnimation pa = new PendingAnimation(RECENTS_LAUNCH_DURATION);
+ if (mActivity == null) {
+ Log.e(TAG, "Animation created, before activity");
+ return pa.buildAnim();
}
- AnimatorSet anim = new AnimatorSet();
- anim.addListener(new AnimationSuccessListener() {
+ mRecentsView.setRunningTaskIconScaledDown(true);
+ pa.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
mActivityInterface.onSwipeUpToRecentsComplete();
- if (mRecentsView != null) {
- mRecentsView.animateUpRunningTaskIconScale();
- }
+ mRecentsView.animateUpRunningTaskIconScale();
}
});
- if (mActivity == null) {
- Log.e(TAG, "Animation created, before activity");
- anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION));
- return anim;
- }
DepthController depthController = mActivityInterface.getDepthController();
if (depthController != null) {
- anim.play(ObjectAnimator.ofFloat(depthController, DEPTH,
- BACKGROUND_APP.getDepth(mActivity),
- OVERVIEW.getDepth(mActivity))
- .setDuration(RECENTS_LAUNCH_DURATION));
+ pa.addFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(mActivity),
+ OVERVIEW.getDepth(mActivity), TOUCH_RESPONSE_INTERPOLATOR);
}
RemoteAnimationTargets targets = new RemoteAnimationTargets(appTargets,
@@ -132,53 +121,39 @@
RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mTargetTaskId);
if (runningTaskTarget == null) {
Log.e(TAG, "No closing app");
- anim.play(ValueAnimator.ofInt(0, 1).setDuration(RECENTS_LAUNCH_DURATION));
- return anim;
+ return pa.buildAnim();
}
- final AppWindowAnimationHelper clipHelper = new AppWindowAnimationHelper(
- mRecentsView.getPagedViewOrientedState(), mActivity);
-
- // At this point, the activity is already started and laid-out. Get the home-bounds
- // relative to the screen using the rootView of the activity.
- int loc[] = new int[2];
- View rootView = mActivity.getRootView();
- rootView.getLocationOnScreen(loc);
- Rect homeBounds = new Rect(loc[0], loc[1],
- loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
- clipHelper.updateSource(homeBounds, runningTaskTarget);
-
- Rect targetRect = new Rect();
- mActivityInterface.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity,
- targetRect);
- clipHelper.updateTargetRect(targetRect);
- clipHelper.prepareAnimation(mActivity.getDeviceProfile());
+ TaskViewSimulator tsv = new TaskViewSimulator(mActivity, mRecentsView.getSizeStrategy());
+ tsv.setDp(mActivity.getDeviceProfile());
+ tsv.setPreview(runningTaskTarget);
+ tsv.setLayoutRotation(mRecentsView.getPagedViewOrientedState().getTouchRotation(),
+ mRecentsView.getPagedViewOrientedState().getDisplayRotation());
TransformParams params = new TransformParams()
- .setSyncTransactionApplier(new SyncRtSurfaceTransactionApplierCompat(rootView));
- ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
- valueAnimator.setDuration(RECENTS_LAUNCH_DURATION);
- valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
- valueAnimator.addUpdateListener((v) -> {
- params.setProgress((float) v.getAnimatedValue()).setTargetSet(targets);
- clipHelper.applyTransform(params);
- });
+ .setTargetSet(targets)
+ .setSyncTransactionApplier(
+ new SyncRtSurfaceTransactionApplierCompat(mActivity.getRootView()));
+ AnimatedFloat recentsAlpha = new AnimatedFloat(() -> { });
+ params.setBaseAlphaCallback((t, a) -> recentsAlpha.value);
+
+ Interpolator taskInterpolator;
if (targets.isAnimatingHome()) {
- // If we are animating home, fade in the opening targets
- RemoteAnimationTargets openingSet = new RemoteAnimationTargets(appTargets,
- wallpaperTargets, MODE_OPENING);
-
- TransactionCompat transaction = new TransactionCompat();
- valueAnimator.addUpdateListener((v) -> {
- for (RemoteAnimationTargetCompat app : openingSet.apps) {
- transaction.setAlpha(app.leash, (float) v.getAnimatedValue());
- }
- transaction.apply();
- });
+ taskInterpolator = TOUCH_RESPONSE_INTERPOLATOR;
+ pa.addFloat(recentsAlpha, AnimatedFloat.VALUE, 0, 1, TOUCH_RESPONSE_INTERPOLATOR);
+ } else {
+ // When animation from app to recents, the recents layer is drawn on top of the app. To
+ // prevent the overlap, we animate the task first and then quickly fade in the recents.
+ taskInterpolator = clampToProgress(TOUCH_RESPONSE_INTERPOLATOR, 0, 0.8f);
+ pa.addFloat(recentsAlpha, AnimatedFloat.VALUE, 0, 1,
+ clampToProgress(TOUCH_RESPONSE_INTERPOLATOR, 0.8f, 1));
}
- anim.play(valueAnimator);
- return anim;
+
+ pa.addFloat(params, TransformParams.PROGRESS, 0, 1, taskInterpolator);
+ tsv.addAppToOverviewAnim(pa, taskInterpolator);
+ pa.addOnFrameCallback(() -> tsv.apply(params));
+ return pa.buildAnim();
}
/**
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
index bbee67c..d957418 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -25,8 +23,6 @@
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@@ -36,6 +32,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -49,7 +46,9 @@
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.views.FloatingIconView;
@@ -357,12 +356,13 @@
protected void initTransitionEndpoints(DeviceProfile dp) {
mDp = dp;
- mTransitionDragLength = mActivityInterface.getSwipeUpDestinationAndLength(
- dp, mContext, TEMP_RECT);
mTaskViewSimulator.setDp(dp);
mTaskViewSimulator.setLayoutRotation(
mDeviceState.getCurrentActiveRotation(),
mDeviceState.getDisplayRotation());
+ mTransitionDragLength = mActivityInterface.getSwipeUpDestinationAndLength(
+ dp, mContext, TEMP_RECT,
+ mTaskViewSimulator.getOrientationState().getOrientationHandler());
if (mDeviceState.isFullyGesturalNavMode()) {
// We can drag all the way to the top of the screen.
@@ -377,18 +377,9 @@
mDragLengthFactorStartPullback = mDragLengthFactorMaxPullback = 1;
}
- AnimatorSet anim = new AnimatorSet();
- anim.setDuration(mTransitionDragLength * 2);
- anim.setInterpolator(t -> t * mDragLengthFactor);
- anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.recentsViewScale,
- AnimatedFloat.VALUE,
- mTaskViewSimulator.getFullScreenScale(), 1));
- anim.play(ObjectAnimator.ofFloat(mTaskViewSimulator.fullScreenProgress,
- AnimatedFloat.VALUE,
- BACKGROUND_APP.getOverviewFullscreenProgress(),
- OVERVIEW.getOverviewFullscreenProgress()));
- mWindowTransitionController =
- AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2);
+ PendingAnimation pa = new PendingAnimation(mTransitionDragLength * 2);
+ mTaskViewSimulator.addAppToOverviewAnim(pa, t -> t * mDragLengthFactor);
+ mWindowTransitionController = pa.createPlaybackController();
}
/**
@@ -398,7 +389,16 @@
protected boolean onActivityInit(Boolean alreadyOnHome) {
T createdActivity = mActivityInterface.getCreatedActivity();
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.1");
+ }
if (createdActivity != null) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.PAUSE_NOT_DETECTED, "BaseSwipeUpHandler.2");
+ }
+ ((RecentsView) createdActivity.getOverviewPanel())
+ .setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
+ mDeviceState.getDisplayRotation());
initTransitionEndpoints(InvariantDeviceProfile.INSTANCE.get(mContext)
.getDeviceProfile(mContext));
}
@@ -510,8 +510,8 @@
public interface Factory {
- BaseSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs,
- boolean continuingLastGesture, boolean isLikelyToStartNewTask);
+ BaseSwipeUpHandler newHandler(
+ GestureState gestureState, long touchTimeMs, boolean continuingLastGesture);
}
protected interface RunningWindowAnim {
@@ -651,14 +651,11 @@
}
@Override
- public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app, int targetMode,
- TransformParams params) {
- if (app.mode == targetMode
- && app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- builder.withMatrix(mMatrix)
- .withWindowCrop(mCropRect)
- .withCornerRadius(params.getCornerRadius());
- }
+ public void onBuildTargetParams(
+ Builder builder, RemoteAnimationTargetCompat app, TransformParams params) {
+ builder.withMatrix(mMatrix)
+ .withWindowCrop(mCropRect)
+ .withCornerRadius(params.getCornerRadius());
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
similarity index 91%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
rename to quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
index 82a3e79..343f28a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java
@@ -17,7 +17,6 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
-import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
@@ -38,29 +37,24 @@
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import android.animation.Animator;
-import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
-import android.graphics.RectF;
import android.os.Build;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
-import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
@@ -72,7 +66,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.TraceHelper;
-import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
import com.android.quickstep.GestureState.GestureEndTarget;
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
@@ -80,7 +73,6 @@
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
-import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.util.TransformParams.TargetAlphaProvider;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
@@ -92,11 +84,12 @@
/**
* Handles the navigation gestures when Launcher is the default home activity.
+ * TODO: Merge this with BaseSwipeUpHandler
*/
@TargetApi(Build.VERSION_CODES.O)
-public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsView>
- implements OnApplyWindowInsetsListener {
- private static final String TAG = LauncherSwipeHandler.class.getSimpleName();
+public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q extends RecentsView>
+ extends BaseSwipeUpHandler<T, Q> implements OnApplyWindowInsetsListener {
+ private static final String TAG = BaseSwipeUpHandlerV2.class.getSimpleName();
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
@@ -108,9 +101,11 @@
}
// Launcher UI related states
- private static final int STATE_LAUNCHER_PRESENT = getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
- private static final int STATE_LAUNCHER_STARTED = getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
- private static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
+ protected static final int STATE_LAUNCHER_PRESENT =
+ getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
+ protected static final int STATE_LAUNCHER_STARTED =
+ getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
+ protected static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
// Internal initialization states
private static final int STATE_APP_CONTROLLER_RECEIVED =
@@ -122,7 +117,7 @@
private static final int STATE_SCALED_CONTROLLER_RECENTS =
getFlagForIndex(5, "STATE_SCALED_CONTROLLER_RECENTS");
- private static final int STATE_HANDLER_INVALIDATED =
+ protected static final int STATE_HANDLER_INVALIDATED =
getFlagForIndex(6, "STATE_HANDLER_INVALIDATED");
private static final int STATE_GESTURE_STARTED =
getFlagForIndex(7, "STATE_GESTURE_STARTED");
@@ -163,7 +158,7 @@
*/
private static final int LOG_NO_OP_PAGE_INDEX = -1;
- private final TaskAnimationManager mTaskAnimationManager;
+ protected final TaskAnimationManager mTaskAnimationManager;
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
@@ -193,7 +188,7 @@
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
- public LauncherSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
+ public BaseSwipeUpHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
long touchTimeMs, boolean continuingLastGesture,
InputConsumerController inputConsumer) {
@@ -222,9 +217,6 @@
| STATE_GESTURE_CANCELLED,
this::resetStateForAnimationCancel);
- mStateCallback.runOnceAtState(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
- this::sendRemoteAnimationsToAnimationFactory);
-
mStateCallback.runOnceAtState(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
this::resumeLastTask);
mStateCallback.runOnceAtState(STATE_START_NEW_TASK | STATE_SCREENSHOT_CAPTURED,
@@ -272,10 +264,12 @@
@Override
protected boolean onActivityInit(Boolean alreadyOnHome) {
super.onActivityInit(alreadyOnHome);
- final Launcher activity = mActivityInterface.getCreatedActivity();
+ final T activity = mActivityInterface.getCreatedActivity();
if (mActivity == activity) {
return true;
}
+ mTaskViewSimulator.setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
+ mDeviceState.getDisplayRotation());
if (mActivity != null) {
// The launcher may have been recreated as a result of device rotation.
int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES;
@@ -321,7 +315,7 @@
}
private void onLauncherStart() {
- final Launcher activity = mActivityInterface.getCreatedActivity();
+ final T activity = mActivityInterface.getCreatedActivity();
if (mActivity != activity) {
return;
}
@@ -409,6 +403,10 @@
updateSysUiFlags(mCurrentShift.value);
return;
}
+ notifyGestureAnimationStartToRecents();
+ }
+
+ protected void notifyGestureAnimationStartToRecents() {
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
}
@@ -416,10 +414,6 @@
mLauncherFrameDrawnTime = SystemClock.uptimeMillis();
}
- private void sendRemoteAnimationsToAnimationFactory() {
- mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationTargets);
- }
-
private void initializeLauncherAnimationController() {
buildAnimationController();
@@ -631,7 +625,7 @@
*/
@UiThread
private void notifyGestureStartedAsync() {
- final Launcher curActivity = mActivity;
+ final T curActivity = mActivity;
if (curActivity != null) {
// Once the gesture starts, we can no longer transition home through the button, so
// reset the force override of the activity visibility
@@ -679,7 +673,7 @@
endLauncherTransitionController();
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
// Hide the task view, if not already hidden
- setTargetAlphaProvider(LauncherSwipeHandler::getHiddenTargetAlpha);
+ setTargetAlphaProvider(BaseSwipeUpHandlerV2::getHiddenTargetAlpha);
}
StatefulActivity activity = mActivityInterface.getCreatedActivity();
@@ -909,6 +903,8 @@
interpolator, target, velocityPxPerMs));
}
+ protected abstract HomeAnimationFactory createHomeAnimationFactory(long duration);
+
@UiThread
private void animateToProgressInternal(float start, float end, long duration,
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
@@ -917,67 +913,7 @@
maybeUpdateRecentsAttachedState();
if (mGestureState.getEndTarget() == HOME) {
- HomeAnimationFactory homeAnimFactory;
- if (mActivity != null) {
- final TaskView runningTaskView = mRecentsView.getRunningTaskView();
- final View workspaceView;
- if (runningTaskView != null
- && runningTaskView.getTask().key.getComponent() != null) {
- workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
- runningTaskView.getTask().key.getComponent().getPackageName(),
- UserHandle.of(runningTaskView.getTask().key.userId));
- } else {
- workspaceView = null;
- }
- final RectF iconLocation = new RectF();
- boolean canUseWorkspaceView =
- workspaceView != null && workspaceView.isAttachedToWindow();
- FloatingIconView floatingIconView = canUseWorkspaceView
- ? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
- true /* hideOriginal */, iconLocation, false /* isOpening */)
- : null;
-
- mActivity.getRootView().setForceHideBackArrow(true);
- mActivityInterface.setHintUserWillBeActive();
-
- homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
-
- @Override
- public RectF getWindowTargetRect() {
- if (canUseWorkspaceView) {
- return iconLocation;
- } else {
- return super.getWindowTargetRect();
- }
- }
-
- @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(mDp.widthPx, mDp.heightPx);
- return mActivity.getStateManager().createAnimationToNewWorkspace(
- NORMAL, accuracy, 0 /* animComponents */);
- }
-
- @Override
- public void playAtomicAnimation(float velocity) {
- new StaggeredWorkspaceAnim(mActivity, velocity,
- true /* animateOverviewScrim */).start();
- }
- };
-
- } else {
- homeAnimFactory = new HomeAnimationFactory(null) {
- @Override
- public AnimatorPlaybackController createActivityAnimationToHome() {
- return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
- }
- };
- mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
- isPresent -> mRecentsView.startHome());
- }
+ HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
@Override
@@ -1301,14 +1237,15 @@
// If there are no targets or the animation not started, then there is nothing to finish
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
} else {
- mRecentsAnimationController.finish(true /* toRecents */,
- () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED),
- true /* sendUserLeaveHint */);
+ finishRecentsControllerToHome(
+ () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
}
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
doLogGesture(HOME);
}
+ protected abstract void finishRecentsControllerToHome(Runnable callback);
+
private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
endLauncherTransitionController();
mActivityInterface.onSwipeUpToRecentsComplete();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
index 4b3af31..7d08fac 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
@@ -15,26 +15,21 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
-import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
-import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import android.content.Context;
-import android.graphics.PointF;
import android.graphics.Rect;
+import android.view.MotionEvent;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsState;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.views.RecentsView;
@@ -54,12 +49,14 @@
public static final FallbackActivityInterface INSTANCE = new FallbackActivityInterface();
private FallbackActivityInterface() {
- super(false);
+ super(false, DEFAULT, BACKGROUND_APP);
}
+ /** 2 */
@Override
- public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- calculateTaskSize(context, dp, outRect);
+ public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
+ PagedOrientationHandler orientationHandler) {
+ calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout()
&& SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) {
Rect targetInsets = dp.getInsets();
@@ -70,6 +67,13 @@
}
}
+ /** 4 */
+ @Override
+ public void onSwipeUpToHomeComplete() {
+ onSwipeUpToRecentsComplete();
+ }
+
+ /** 5 */
@Override
public void onAssistantVisibilityChanged(float visibility) {
// This class becomes active when the screen is locked.
@@ -77,50 +81,13 @@
// set to zero prior to this class becoming active.
}
+ /** 6 */
@Override
public AnimationFactory prepareRecentsUI(
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
- RecentsActivity activity = getCreatedActivity();
- if (activity == null) {
- return (transitionLength) -> { };
- }
-
- activity.getStateManager().goToState(BACKGROUND_APP);
- FallbackRecentsView rv = activity.getOverviewPanel();
- rv.setContentAlpha(0);
-
- return new AnimationFactory() {
-
- boolean isAnimatingToRecents = false;
-
- @Override
- public void onRemoteAnimationReceived(RemoteAnimationTargets targets) {
- isAnimatingToRecents = targets != null && targets.isAnimatingHome();
- if (!isAnimatingToRecents) {
- rv.setContentAlpha(1);
- }
- createActivityInterface(getSwipeUpDestinationAndLength(
- activity.getDeviceProfile(), activity, new Rect()));
- }
-
- @Override
- public void createActivityInterface(long transitionLength) {
- PendingAnimation pa = new PendingAnimation(transitionLength * 2);
-
- if (isAnimatingToRecents) {
- pa.addFloat(rv, CONTENT_ALPHA, 0, 1, LINEAR);
- }
-
- pa.addFloat(rv, SCALE_PROPERTY, rv.getMaxScaleForFullScreen(), 1, LINEAR);
- pa.addFloat(rv, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
- AnimatorPlaybackController controller = pa.createPlaybackController();
-
- // Since we are changing the start position of the UI, reapply the state, at the end
- controller.setEndAction(() -> activity.getStateManager().goToState(
- controller.getInterpolatedProgress() > 0.5 ? DEFAULT : BACKGROUND_APP));
- callback.accept(controller);
- }
- };
+ DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
+ factory.initUI();
+ return factory;
}
@Override
@@ -164,6 +131,15 @@
}
@Override
+ public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
+ // In non-gesture mode, user might be clicking on the home button which would directly
+ // start the home activity instead of going through recents. In that case, defer starting
+ // recents until we are sure it is a gesture.
+ return !deviceState.isFullyGesturalNavMode()
+ || super.deferStartingActivity(deviceState, ev);
+ }
+
+ @Override
public int getContainerType() {
RecentsActivity activity = getCreatedActivity();
boolean visible = activity != null && activity.isStarted() && activity.hasWindowFocus();
@@ -188,12 +164,8 @@
}
@Override
- public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
- out.set(dp.widthPx, dp.heightPx);
- }
-
- @Override
- protected float getExtraSpace(Context context, DeviceProfile dp) {
+ protected float getExtraSpace(Context context, DeviceProfile dp,
+ PagedOrientationHandler orientationHandler) {
return showOverviewActions(context)
? context.getResources().getDimensionPixelSize(R.dimen.overview_actions_height)
: 0;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
index db41bd6..7b614c2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -15,537 +15,117 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
-import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
-import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
-import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
-import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
-import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
-import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
-import android.graphics.PointF;
-import android.os.Bundle;
-import android.util.ArrayMap;
-import android.view.MotionEvent;
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimationSuccessListener;
+import androidx.annotation.NonNull;
+
import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.util.ObjectWrapper;
-import com.android.quickstep.BaseActivityInterface.AnimationFactory;
-import com.android.quickstep.GestureState.GestureEndTarget;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.quickstep.fallback.FallbackRecentsView;
-import com.android.quickstep.util.RectFSpringAnim;
-import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.quickstep.util.TransformParams;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
/**
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
*/
-public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
+public class FallbackSwipeHandler extends
+ BaseSwipeUpHandlerV2<RecentsActivity, FallbackRecentsView> {
- private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
-
- private static int getFlagForIndex(int index, String name) {
- if (DEBUG_STATES) {
- STATE_NAMES[index] = name;
- }
- return 1 << index;
- }
-
- private static final int STATE_RECENTS_PRESENT =
- getFlagForIndex(0, "STATE_RECENTS_PRESENT");
- private static final int STATE_HANDLER_INVALIDATED =
- getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
-
- private static final int STATE_GESTURE_CANCELLED =
- getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
- private static final int STATE_GESTURE_COMPLETED =
- getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
- private static final int STATE_APP_CONTROLLER_RECEIVED =
- getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
-
- public static class EndTargetAnimationParams {
- private final float mEndProgress;
- private final long mDurationMultiplier;
- private final float mLauncherAlpha;
-
- EndTargetAnimationParams(float endProgress, long durationMultiplier, float launcherAlpha) {
- mEndProgress = endProgress;
- mDurationMultiplier = durationMultiplier;
- mLauncherAlpha = launcherAlpha;
- }
- }
- private final ArrayMap<GestureEndTarget, EndTargetAnimationParams>
- mEndTargetAnimationParams = new ArrayMap();
-
- private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
-
- private boolean mOverviewThresholdPassed = false;
-
- private final boolean mInQuickSwitchMode;
- private final boolean mContinuingLastGesture;
+ private FallbackHomeAnimationFactory mActiveAnimationFactory;
private final boolean mRunningOverHome;
- private final boolean mSwipeUpOverHome;
- private boolean mTouchedHomeDuringTransition;
-
- private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
- private RunningWindowAnim mFinishAnimation;
-
- // Used to control Recents components throughout the swipe gesture.
- private AnimatorPlaybackController mLauncherTransitionController;
- private boolean mHasLauncherTransitionControllerStarted;
-
- private AnimationFactory mAnimationFactory = (t) -> { };
public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
- GestureState gestureState, InputConsumerController inputConsumer,
- boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
- super(context, deviceState, gestureState, inputConsumer);
+ TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
+ boolean continuingLastGesture, InputConsumerController inputConsumer) {
+ super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
+ continuingLastGesture, inputConsumer);
- mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
- mContinuingLastGesture = continuingLastGesture;
mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
- mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
-
- // Keep the home launcher invisible until we decide to land there.
- mLauncherAlpha.value = mRunningOverHome ? 1 : 0;
- if (mSwipeUpOverHome) {
- mTransformParams.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
- } else {
- mTransformParams.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
- }
-
- // Going home has an extra long progress to ensure that it animates into the screen
- mEndTargetAnimationParams.put(HOME, new EndTargetAnimationParams(3, 100, 1));
- mEndTargetAnimationParams.put(RECENTS, new EndTargetAnimationParams(1, 300, 0));
- mEndTargetAnimationParams.put(LAST_TASK, new EndTargetAnimationParams(0, 150, 1));
- mEndTargetAnimationParams.put(NEW_TASK, new EndTargetAnimationParams(0, 150, 1));
-
- initAfterSubclassConstructor();
- initStateCallbacks();
- }
-
- private void initStateCallbacks() {
- mStateCallback = new MultiStateCallback(STATE_NAMES);
-
- mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED,
- this::onHandlerInvalidated);
- mStateCallback.runOnceAtState(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
- this::onHandlerInvalidatedWithRecents);
-
- mStateCallback.runOnceAtState(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
- this::finishAnimationTargetSetAnimationComplete);
-
- if (mInQuickSwitchMode) {
- mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
- | STATE_RECENTS_PRESENT,
- this::finishAnimationTargetSet);
- } else {
- mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
- this::finishAnimationTargetSet);
- }
- }
-
- private void onLauncherAlphaChanged() {
- if (mRecentsAnimationTargets != null && mGestureState.getEndTarget() == null) {
- applyWindowTransform();
- }
}
@Override
- protected boolean onActivityInit(Boolean alreadyOnHome) {
- super.onActivityInit(alreadyOnHome);
- mActivity = mActivityInterface.getCreatedActivity();
- mRecentsView = mActivity.getOverviewPanel();
- mRecentsView.setOnPageTransitionEndCallback(null);
- linkRecentsViewScroll();
- if (!mContinuingLastGesture) {
- if (mRunningOverHome) {
- mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
- } else {
- mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
- }
- }
- mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
- mDeviceState.enableMultipleRegions(false);
-
- mAnimationFactory = mActivityInterface.prepareRecentsUI(alreadyOnHome,
- this::onAnimatorPlaybackControllerCreated);
- mAnimationFactory.createActivityInterface(mTransitionDragLength);
- return true;
- }
-
- @Override
- protected void initTransitionEndpoints(DeviceProfile dp) {
- super.initTransitionEndpoints(dp);
- if (canCreateNewOrUpdateExistingLauncherTransitionController()) {
- mAnimationFactory.createActivityInterface(mTransitionDragLength);
- }
- }
-
- private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
- mLauncherTransitionController = anim;
- mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
- mLauncherTransitionController.dispatchOnStart();
- updateLauncherTransitionProgress();
- }
-
- private void updateLauncherTransitionProgress() {
- if (mLauncherTransitionController == null
- || !canCreateNewOrUpdateExistingLauncherTransitionController()) {
- return;
- }
- // Normalize the progress to 0 to 1, as the animation controller will clamp it to that
- // anyway. The controller mimics the drag length factor by applying it to its interpolators.
- float progress = mCurrentShift.value / mDragLengthFactor;
- mLauncherTransitionController.setPlayFraction(progress);
- }
-
- /**
- * We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
- * (it has its own animation) or if we're already animating the current controller.
- * @return Whether we can create the launcher controller or update its progress.
- */
- private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
- return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
- }
-
- @Override
- protected boolean moveWindowWithRecentsScroll() {
- return mInQuickSwitchMode;
- }
-
- @Override
- public void initWhenReady(Intent intent) {
- if (mInQuickSwitchMode) {
- // Only init if we are in quickswitch mode
- super.initWhenReady(intent);
- }
- }
-
- @Override
- public void updateDisplacement(float displacement) {
- if (!mInQuickSwitchMode) {
- super.updateDisplacement(displacement);
- }
- }
-
- @Override
- protected InputConsumer createNewInputProxyHandler() {
- // Just consume all input on the active task
- return new InputConsumer() {
- @Override
- public int getType() {
- return InputConsumer.TYPE_NO_OP;
- }
-
- @Override
- public void onMotionEvent(MotionEvent ev) {
- mTouchedHomeDuringTransition = true;
- }
- };
- }
-
- @Override
- public void onMotionPauseChanged(boolean isPaused) {
- if (!mInQuickSwitchMode && mDeviceState.isFullyGesturalNavMode()) {
- updateOverviewThresholdPassed(isPaused);
- }
- }
-
- private void updateOverviewThresholdPassed(boolean passed) {
- if (passed != mOverviewThresholdPassed) {
- mOverviewThresholdPassed = passed;
- if (mSwipeUpOverHome) {
- mLauncherAlpha.animateToValue(mLauncherAlpha.value, passed ? 0 : 1)
- .setDuration(150).start();
- }
- performHapticFeedback();
- }
- }
-
- @Override
- public Intent getLaunchIntent() {
- if (mInQuickSwitchMode || mSwipeUpOverHome || !mDeviceState.isFullyGesturalNavMode()) {
- return mGestureState.getOverviewIntent();
- } else {
- return mGestureState.getHomeIntent();
- }
- }
-
- @Override
- public void updateFinalShift() {
- mTransformParams.setProgress(mCurrentShift.value);
- if (mRecentsAnimationController != null) {
- boolean swipeUpThresholdPassed = mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
- mRecentsAnimationController.setUseLauncherSystemBarFlags(mInQuickSwitchMode
- || swipeUpThresholdPassed);
- mRecentsAnimationController.setSplitScreenMinimized(!mInQuickSwitchMode
- && swipeUpThresholdPassed);
- }
-
- if (!mInQuickSwitchMode && !mDeviceState.isFullyGesturalNavMode()) {
- updateOverviewThresholdPassed(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW);
- }
-
- applyWindowTransform();
- updateLauncherTransitionProgress();
- }
-
- @Override
- public void onGestureCancelled() {
- updateDisplacement(0);
- mGestureState.setEndTarget(LAST_TASK);
- mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED);
- }
-
- @Override
- public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
- mEndVelocityPxPerMs.set(0, velocity.y / 1000);
- if (mInQuickSwitchMode) {
- // For now set it to non-null, it will be reset before starting the animation
- mGestureState.setEndTarget(LAST_TASK);
- } else {
- float flingThreshold = mContext.getResources()
- .getDimension(R.dimen.quickstep_fling_threshold_velocity);
- boolean isFling = Math.abs(endVelocity) > flingThreshold;
-
- if (mDeviceState.isFullyGesturalNavMode()) {
- if (isFling) {
- mGestureState.setEndTarget(endVelocity < 0 ? HOME : LAST_TASK);
- } else if (mOverviewThresholdPassed) {
- mGestureState.setEndTarget(RECENTS);
- } else {
- mGestureState.setEndTarget(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW
- ? HOME
- : LAST_TASK);
- }
- } else {
- GestureEndTarget startState = mSwipeUpOverHome ? HOME : LAST_TASK;
- if (isFling) {
- mGestureState.setEndTarget(endVelocity < 0 ? RECENTS : startState);
- } else {
- mGestureState.setEndTarget(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW
- ? RECENTS
- : startState);
- }
- }
- }
- mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
- }
-
- @Override
- public void onConsumerAboutToBeSwitched() {
- if (mInQuickSwitchMode && mGestureState.getEndTarget() != null) {
- mGestureState.setEndTarget(NEW_TASK);
-
- mCanceled = true;
- mCurrentShift.cancelAnimation();
- if (mFinishAnimation != null) {
- mFinishAnimation.cancel();
- }
-
- if (mRecentsView != null) {
- mRecentsView.setOnScrollChangeListener(null);
- }
- } else {
- mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
- }
- }
-
- private void onHandlerInvalidated() {
- mActivityInitListener.unregister();
- if (mGestureEndCallback != null) {
- mGestureEndCallback.run();
- }
- if (mFinishAnimation != null) {
- mFinishAnimation.end();
- }
- }
-
- private void onHandlerInvalidatedWithRecents() {
- mRecentsView.onGestureAnimationEnd();
- mRecentsView.setDisallowScrollToClearAll(false);
- mRecentsView.getClearAllButton().setVisibilityAlpha(1);
- }
-
- private void finishAnimationTargetSetAnimationComplete() {
- switch (mGestureState.getEndTarget()) {
- case HOME: {
- if (mSwipeUpOverHome) {
- mRecentsAnimationController.finish(false, null, false);
- // Send a home intent to clear the task stack
- mContext.startActivity(mGestureState.getHomeIntent());
- } else {
- // Notify swipe-to-home (recents animation) is finished
- SystemUiProxy.INSTANCE.get(mContext).notifySwipeToHomeFinished();
- mRecentsAnimationController.finish(true, () -> {
- if (!mTouchedHomeDuringTransition) {
- // If the user hasn't interacted with the screen during the transition,
- // send a home intent so launcher can go to the default home screen.
- // (If they are trying to touch something, we don't want to interfere.)
- mContext.startActivity(mGestureState.getHomeIntent());
- }
- }, true);
- }
- break;
- }
- case LAST_TASK:
- mRecentsAnimationController.finish(false, null, false);
- break;
- case RECENTS: {
- if (mSwipeUpOverHome || !mDeviceState.isFullyGesturalNavMode()) {
- mRecentsAnimationController.finish(true, null, true);
- break;
- }
-
- final int runningTaskId = mGestureState.getRunningTaskId();
- ThumbnailData thumbnail = mRecentsAnimationController.screenshotTask(runningTaskId);
- mRecentsAnimationController.setDeferCancelUntilNextTransition(true /* defer */,
- false /* screenshot */);
-
- ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
- ActivityOptionsCompat.setFreezeRecentTasksList(options);
-
- Bundle extras = new Bundle();
- extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
- extras.putInt(EXTRA_TASK_ID, runningTaskId);
-
- Intent intent = new Intent(mGestureState.getOverviewIntent())
- .putExtras(extras);
- mContext.startActivity(intent, options.toBundle());
- mRecentsAnimationController.cleanupScreenshot();
- break;
- }
- case NEW_TASK: {
- startNewTask(success -> { });
- break;
- }
- }
-
- mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
- }
-
- private void finishAnimationTargetSet() {
- if (mInQuickSwitchMode) {
- // Recalculate the end target, some views might have been initialized after
- // gesture has ended.
- if (mRecentsView == null || !hasTargets()) {
- mGestureState.setEndTarget(LAST_TASK);
- } else {
- final int runningTaskIndex = getLastAppearedTaskIndex();
- final int taskToLaunch = mRecentsView.getNextPage();
- mGestureState.setEndTarget(
- (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
- ? NEW_TASK
- : LAST_TASK);
- }
- }
-
- EndTargetAnimationParams params = mEndTargetAnimationParams.get(mGestureState.getEndTarget());
- float endProgress = params.mEndProgress;
- long duration = (long) (params.mDurationMultiplier *
- Math.abs(endProgress - mCurrentShift.value));
- if (mRecentsView != null) {
- duration = Math.max(duration, mRecentsView.getScroller().getDuration());
- }
- if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
- AnimationSuccessListener endListener = new AnimationSuccessListener() {
-
- @Override
- public void onAnimationSuccess(Animator animator) {
- if (mRecentsView != null) {
- mRecentsView.setOnPageTransitionEndCallback(FallbackSwipeHandler.this
- ::finishAnimationTargetSetAnimationComplete);
- } else {
- finishAnimationTargetSetAnimationComplete();
- }
- mFinishAnimation = null;
- }
- };
-
- if (mGestureState.getEndTarget() == HOME && !mRunningOverHome) {
- mRecentsAnimationController.enableInputProxy(mInputConsumer,
- this::createNewInputProxyHandler);
- RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
- anim.addAnimatorListener(endListener);
- anim.start(mContext, mEndVelocityPxPerMs);
- mFinishAnimation = RunningWindowAnim.wrap(anim);
- } else {
-
- AnimatorSet anim = new AnimatorSet();
- anim.play(mLauncherAlpha.animateToValue(
- mLauncherAlpha.value, params.mLauncherAlpha));
- anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
-
- anim.setDuration(duration);
- anim.addListener(endListener);
- anim.start();
- mFinishAnimation = RunningWindowAnim.wrap(anim);
- }
-
- } else {
- finishAnimationTargetSetAnimationComplete();
- }
- }
-
- @Override
- public void onRecentsAnimationStart(RecentsAnimationController controller,
- RecentsAnimationTargets targets) {
- super.onRecentsAnimationStart(controller, targets);
- mRecentsAnimationController.enableInputConsumer();
- applyWindowTransform();
-
- mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
- }
-
- @Override
- public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
- mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
-
- // Defer clearing the controller and the targets until after we've updated the state
- super.onRecentsAnimationCanceled(thumbnailData);
+ protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+ mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
+ ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
+ mContext.startActivity(new Intent(mGestureState.getHomeIntent()), options.toBundle());
+ return mActiveAnimationFactory;
}
@Override
protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
- return true;
- }
+ if (mActiveAnimationFactory != null
+ && mActiveAnimationFactory.handleHomeTaskAppeared(appearedTaskTarget)) {
+ mActiveAnimationFactory = null;
+ return false;
+ }
- /**
- * Creates an animation that transforms the current app window into the home app.
- * @param startProgress The progress of {@link #mCurrentShift} to start the window from.
- */
- private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) {
- HomeAnimationFactory factory = new HomeAnimationFactory(null) {
- @Override
- public AnimatorPlaybackController createActivityAnimationToHome() {
- AnimatorSet anim = new AnimatorSet();
- Animator fadeInLauncher = mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1);
- fadeInLauncher.setInterpolator(ACCEL_2);
- anim.play(fadeInLauncher);
- anim.setDuration(duration);
- return AnimatorPlaybackController.wrap(anim, duration);
- }
- };
- return createWindowAnimationToHome(startProgress, factory);
+ return super.handleTaskAppeared(appearedTaskTarget);
}
@Override
- protected float getWindowAlpha(float progress) {
- return 1 - ACCEL_1_5.getInterpolation(progress);
+ protected void finishRecentsControllerToHome(Runnable callback) {
+ mRecentsAnimationController.finish(
+ false /* toRecents */, callback, true /* sendUserLeaveHint */);
+ }
+
+ @Override
+ protected void notifyGestureAnimationStartToRecents() {
+ if (mRunningOverHome) {
+ mRecentsView.onGestureAnimationStartOnHome(mGestureState.getRunningTask());
+ } else {
+ super.notifyGestureAnimationStartToRecents();
+ }
+ }
+
+ private class FallbackHomeAnimationFactory extends HomeAnimationFactory
+ implements TransformParams.BuilderProxy {
+
+ private final TransformParams mHomeAlphaParams = new TransformParams();
+ private final AnimatedFloat mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
+
+ private final long mDuration;
+ FallbackHomeAnimationFactory(long duration) {
+ super(null);
+ mDuration = duration;
+ }
+
+ @NonNull
+ @Override
+ public AnimatorPlaybackController createActivityAnimationToHome() {
+ PendingAnimation pa = new PendingAnimation(mDuration);
+ pa.setFloat(mHomeAlpha, AnimatedFloat.VALUE, 1, LINEAR);
+ return pa.createPlaybackController();
+ }
+
+ private void updateHomeAlpha() {
+ mHomeAlphaParams.setProgress(mHomeAlpha.value);
+ if (mHomeAlphaParams.getTargetSet() != null) {
+ mHomeAlphaParams.applySurfaceParams(mHomeAlphaParams.createSurfaceParams(this));
+ }
+ }
+
+ public boolean handleHomeTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
+ if (appearedTaskTarget.activityType == ACTIVITY_TYPE_HOME) {
+ RemoteAnimationTargets targets = new RemoteAnimationTargets(
+ new RemoteAnimationTargetCompat[] {appearedTaskTarget},
+ new RemoteAnimationTargetCompat[0], appearedTaskTarget.mode);
+ mHomeAlphaParams.setTargetSet(targets);
+ updateHomeAlpha();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app, int targetMode,
+ TransformParams params) { }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
index 4ebfbd6..dae2f41 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
@@ -15,30 +15,18 @@
*/
package com.android.quickstep;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
-import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
-import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.SysUINavigationMode.getMode;
-import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
+import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
import static com.android.quickstep.util.LayoutUtils.getDefaultSwipeHeight;
-import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
-import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
-import android.animation.Animator;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Log;
-import android.view.MotionEvent;
import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
@@ -57,13 +45,12 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DepthController.ClampedDepthProperty;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
-import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -75,23 +62,24 @@
* {@link BaseActivityInterface} for the in-launcher recents.
*/
public final class LauncherActivityInterface extends
- BaseActivityInterface<LauncherState, Launcher> {
+ BaseActivityInterface<LauncherState, BaseQuickstepLauncher> {
public static final LauncherActivityInterface INSTANCE = new LauncherActivityInterface();
private LauncherActivityInterface() {
- super(true);
+ super(true, OVERVIEW, BACKGROUND_APP);
}
@Override
- public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
- calculateTaskSize(context, dp, outRect);
+ public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
+ PagedOrientationHandler orientationHandler) {
+ calculateTaskSize(context, dp, outRect, orientationHandler);
if (dp.isVerticalBarLayout() && SysUINavigationMode.getMode(context) != Mode.NO_BUTTON) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
return dp.hotseatBarSizePx + hotseatInset;
} else {
- return LayoutUtils.getShelfTrackingDistance(context, dp);
+ return LayoutUtils.getShelfTrackingDistance(context, dp, orientationHandler);
}
}
@@ -100,7 +88,9 @@
super.onSwipeUpToRecentsComplete();
Launcher launcher = getCreatedActivity();
if (launcher != null) {
- DiscoveryBounce.showForOverviewIfNeeded(launcher);
+ RecentsView recentsView = launcher.getOverviewPanel();
+ DiscoveryBounce.showForOverviewIfNeeded(launcher,
+ recentsView.getPagedOrientationHandler());
}
}
@@ -128,119 +118,43 @@
@Override
public AnimationFactory prepareRecentsUI(
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
- BaseQuickstepLauncher launcher = getCreatedActivity();
- final LauncherState startState = launcher.getStateManager().getState();
-
- LauncherState resetState = startState;
- if (startState.shouldDisableRestore()) {
- resetState = launcher.getStateManager().getRestState();
- }
- launcher.getStateManager().setRestState(resetState);
-
- launcher.getStateManager().goToState(BACKGROUND_APP, false);
- // Since all apps is not visible, we can safely reset the scroll position.
- // This ensures then the next swipe up to all-apps starts from scroll 0.
- launcher.getAppsView().reset(false /* animate */);
-
- return new AnimationFactory() {
- private final ShelfPeekAnim mShelfAnim = launcher.getShelfPeekAnim();
- private boolean mIsAttachedToWindow;
-
- @Override
- public void createActivityInterface(long transitionLength) {
- callback.accept(createBackgroundToOverviewAnim(launcher, transitionLength));
- // Creating the activity controller animation sometimes reapplies the launcher state
- // (because we set the animation as the current state animation), so we reapply the
- // attached state here as well to ensure recents is shown/hidden appropriately.
- if (SysUINavigationMode.getMode(launcher) == Mode.NO_BUTTON) {
- setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
- }
- }
-
- @Override
- public void onTransitionCancelled() {
- launcher.getStateManager().goToState(startState, false /* animate */);
- }
-
+ DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
@Override
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
long duration) {
- mShelfAnim.setShelfState(shelfState, interpolator, duration);
+ mActivity.getShelfPeekAnim().setShelfState(shelfState, interpolator, duration);
}
@Override
- public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
- if (mIsAttachedToWindow == attached && animate) {
- return;
- }
- mIsAttachedToWindow = attached;
- LauncherRecentsView recentsView = launcher.getOverviewPanel();
- Animator fadeAnim = launcher.getStateManager()
- .createStateElementAnimation(
- INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
+ protected void createBackgroundToOverviewAnim(BaseQuickstepLauncher activity,
+ PendingAnimation pa) {
+ super.createBackgroundToOverviewAnim(activity, pa);
- float fromTranslation = attached ? 1 : 0;
- float toTranslation = attached ? 0 : 1;
- launcher.getStateManager()
- .cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
- if (!recentsView.isShown() && animate) {
- ADJACENT_PAGE_OFFSET.set(recentsView, fromTranslation);
- } else {
- fromTranslation = ADJACENT_PAGE_OFFSET.get(recentsView);
- }
- if (!animate) {
- ADJACENT_PAGE_OFFSET.set(recentsView, toTranslation);
- } else {
- launcher.getStateManager().createStateElementAnimation(
- INDEX_RECENTS_TRANSLATE_X_ANIM,
- fromTranslation, toTranslation).start();
+ if (!activity.getDeviceProfile().isVerticalBarLayout()
+ && SysUINavigationMode.getMode(activity) != Mode.NO_BUTTON) {
+ // Don't animate the shelf when the mode is NO_BUTTON, because we
+ // update it atomically.
+ pa.add(activity.getStateManager().createStateElementAnimation(
+ INDEX_SHELF_ANIM,
+ BACKGROUND_APP.getVerticalProgress(activity),
+ OVERVIEW.getVerticalProgress(activity)));
}
- fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
- fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
+ // Animate the blur and wallpaper zoom
+ float fromDepthRatio = BACKGROUND_APP.getDepth(activity);
+ float toDepthRatio = OVERVIEW.getDepth(activity);
+ pa.addFloat(getDepthController(),
+ new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
+ fromDepthRatio, toDepthRatio, LINEAR);
+
}
};
- }
- private AnimatorPlaybackController createBackgroundToOverviewAnim(
- Launcher activity, long transitionLength) {
-
- PendingAnimation pa = new PendingAnimation(transitionLength * 2);
-
- if (!activity.getDeviceProfile().isVerticalBarLayout()
- && SysUINavigationMode.getMode(activity) != Mode.NO_BUTTON) {
- // Don't animate the shelf when the mode is NO_BUTTON, because we update it atomically.
- pa.add(activity.getStateManager().createStateElementAnimation(
- INDEX_SHELF_ANIM,
- BACKGROUND_APP.getVerticalProgress(activity),
- OVERVIEW.getVerticalProgress(activity)));
- }
-
- // Animate the blur and wallpaper zoom
- float fromDepthRatio = BACKGROUND_APP.getDepth(activity);
- float toDepthRatio = OVERVIEW.getDepth(activity);
- pa.addFloat(getDepthController(), new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
- fromDepthRatio, toDepthRatio, LINEAR);
-
-
- // Scale down recents from being full screen to being in overview.
- RecentsView recentsView = activity.getOverviewPanel();
- pa.addFloat(recentsView, SCALE_PROPERTY,
- BACKGROUND_APP.getOverviewScaleAndOffset(activity)[0],
- OVERVIEW.getOverviewScaleAndOffset(activity)[0],
- LINEAR);
- pa.addFloat(recentsView, FULLSCREEN_PROGRESS,
- BACKGROUND_APP.getOverviewFullscreenProgress(),
- OVERVIEW.getOverviewFullscreenProgress(),
- LINEAR);
-
- AnimatorPlaybackController controller = pa.createPlaybackController();
- activity.getStateManager().setCurrentUserControlledAnimation(controller);
-
- // Since we are changing the start position of the UI, reapply the state, at the end
- controller.setEndAction(() -> activity.getStateManager().goToState(
- controller.getInterpolatedProgress() > 0.5 ? OVERVIEW : BACKGROUND_APP, false));
- return controller;
+ BaseQuickstepLauncher launcher = factory.initUI();
+ // Since all apps is not visible, we can safely reset the scroll position.
+ // This ensures then the next swipe up to all-apps starts from scroll 0.
+ launcher.getAppsView().reset(false /* animate */);
+ return factory;
}
@Override
@@ -249,6 +163,15 @@
onInitListener.test(alreadyOnHome));
}
+ @Override
+ public void setOnDeferredActivityLaunchCallback(Runnable r) {
+ Launcher launcher = getCreatedActivity();
+ if (launcher == null) {
+ return;
+ }
+ launcher.setOnDeferredActivityLaunchCallback(r);
+ }
+
@Nullable
@Override
public BaseQuickstepLauncher getCreatedActivity() {
@@ -256,11 +179,13 @@
}
@Nullable
- @UiThread
- private Launcher getVisibleLauncher() {
- Launcher launcher = getCreatedActivity();
- return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus() ?
- launcher : null;
+ @Override
+ public DepthController getDepthController() {
+ BaseQuickstepLauncher launcher = getCreatedActivity();
+ if (launcher == null) {
+ return null;
+ }
+ return launcher.getDepthController();
}
@Nullable
@@ -271,6 +196,14 @@
? launcher.getOverviewPanel() : null;
}
+ @Nullable
+ @UiThread
+ private Launcher getVisibleLauncher() {
+ Launcher launcher = getCreatedActivity();
+ return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus()
+ ? launcher : null;
+ }
+
@Override
public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
if (TestProtocol.sDebugTracing) {
@@ -290,15 +223,6 @@
return true;
}
- @Override
- public void setHintUserWillBeActive() {
- getCreatedActivity().setHintUserWillBeActive();
- }
-
- @Override
- public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
- return deviceState.isInDeferredGestureRegion(ev);
- }
@Override
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
@@ -311,6 +235,16 @@
}
@Override
+ public void updateOverviewPredictionState() {
+ Launcher launcher = getCreatedActivity();
+ if (launcher == null) {
+ return;
+ }
+ PredictionUiStateManager.INSTANCE.get(launcher).switchClient(
+ PredictionUiStateManager.Client.OVERVIEW);
+ }
+
+ @Override
public int getContainerType() {
final Launcher launcher = getVisibleLauncher();
return launcher != null ? launcher.getStateManager().getState().containerType
@@ -348,54 +282,11 @@
}
@Override
- public void setOnDeferredActivityLaunchCallback(Runnable r) {
- Launcher launcher = getCreatedActivity();
- if (launcher == null) {
- return;
- }
- launcher.setOnDeferredActivityLaunchCallback(r);
- }
-
- @Override
- public void updateOverviewPredictionState() {
- Launcher launcher = getCreatedActivity();
- if (launcher == null) {
- return;
- }
- PredictionUiStateManager.INSTANCE.get(launcher).switchClient(
- PredictionUiStateManager.Client.OVERVIEW);
- }
-
- @Nullable
- @Override
- public DepthController getDepthController() {
- BaseQuickstepLauncher launcher = getCreatedActivity();
- if (launcher == null) {
- return null;
- }
- return launcher.getDepthController();
- }
-
- @Override
- public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
- DeviceProfile fullDp = dp.getFullScreenProfile();
- // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
- // account for system insets
- out.set(fullDp.availableWidthPx, fullDp.availableHeightPx);
- float halfDividerSize = context.getResources()
- .getDimension(R.dimen.multi_window_task_divider_size) / 2;
-
- if (fullDp.isLandscape) {
- out.x = out.x / 2 - halfDividerSize;
- } else {
- out.y = out.y / 2 - halfDividerSize;
- }
- }
-
- @Override
- protected float getExtraSpace(Context context, DeviceProfile dp) {
- if (dp.isVerticalBarLayout()) {
- return 0;
+ protected float getExtraSpace(Context context, DeviceProfile dp,
+ PagedOrientationHandler orientationHandler) {
+ if (dp.isVerticalBarLayout() ||
+ hideShelfInTwoButtonLandscape(context, orientationHandler)) {
+ return 0;
} else {
Resources res = context.getResources();
if (showOverviewActions(context)) {
@@ -421,4 +312,5 @@
}
}
}
+
}
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
new file mode 100644
index 0000000..fa7d268
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 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 static com.android.launcher3.LauncherState.NORMAL;
+
+import android.animation.AnimatorSet;
+import android.content.Context;
+import android.graphics.RectF;
+import android.os.UserHandle;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+
+import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.views.FloatingIconView;
+import com.android.quickstep.util.StaggeredWorkspaceAnim;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.system.InputConsumerController;
+
+/**
+ * Temporary class to allow easier refactoring
+ */
+public class LauncherSwipeHandlerV2 extends
+ BaseSwipeUpHandlerV2<BaseQuickstepLauncher, RecentsView> {
+
+ public LauncherSwipeHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
+ TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
+ boolean continuingLastGesture, InputConsumerController inputConsumer) {
+ super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
+ continuingLastGesture, inputConsumer);
+ }
+
+
+ @Override
+ protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+ HomeAnimationFactory homeAnimFactory;
+ if (mActivity != null) {
+ final TaskView runningTaskView = mRecentsView.getRunningTaskView();
+ final View workspaceView;
+ if (runningTaskView != null
+ && runningTaskView.getTask().key.getComponent() != null) {
+ workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
+ runningTaskView.getTask().key.getComponent().getPackageName(),
+ UserHandle.of(runningTaskView.getTask().key.userId));
+ } else {
+ workspaceView = null;
+ }
+ final RectF iconLocation = new RectF();
+ boolean canUseWorkspaceView =
+ workspaceView != null && workspaceView.isAttachedToWindow();
+ FloatingIconView floatingIconView = canUseWorkspaceView
+ ? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
+ true /* hideOriginal */, iconLocation, false /* isOpening */)
+ : null;
+
+ mActivity.getRootView().setForceHideBackArrow(true);
+ mActivity.setHintUserWillBeActive();
+
+ homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
+
+ @Override
+ public RectF getWindowTargetRect() {
+ if (canUseWorkspaceView) {
+ return iconLocation;
+ } else {
+ return super.getWindowTargetRect();
+ }
+ }
+
+ @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(mDp.widthPx, mDp.heightPx);
+ return mActivity.getStateManager().createAnimationToNewWorkspace(
+ NORMAL, accuracy, 0 /* animComponents */);
+ }
+
+ @Override
+ public void playAtomicAnimation(float velocity) {
+ new StaggeredWorkspaceAnim(mActivity, velocity,
+ true /* animateOverviewScrim */).start();
+ }
+ };
+
+ } else {
+ homeAnimFactory = new HomeAnimationFactory(null) {
+ @Override
+ public AnimatorPlaybackController createActivityAnimationToHome() {
+ return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
+ }
+ };
+ mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
+ isPresent -> mRecentsView.startHome());
+ }
+ return homeAnimFactory;
+ }
+
+ @Override
+ protected void finishRecentsControllerToHome(Runnable callback) {
+ mRecentsAnimationController.finish(
+ true /* toRecents */, callback, true /* sendUserLeaveHint */);
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
index d4c746f..0d49b2b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -7,6 +7,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
import com.android.quickstep.util.LayoutUtils;
import com.android.systemui.shared.recents.model.Task;
@@ -35,7 +36,8 @@
case TestProtocol.REQUEST_BACKGROUND_TO_OVERVIEW_SWIPE_HEIGHT: {
final float swipeHeight =
- LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile);
+ LayoutUtils.getShelfTrackingDistance(mContext, mDeviceProfile,
+ PagedOrientationHandler.HOME_ROTATED);
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, (int) swipeHeight);
return response;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index a4670fd..33b7f12 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -46,6 +46,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.statemanager.StateManager;
+import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.util.ActivityTracker;
@@ -57,6 +58,7 @@
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.fallback.RecentsState;
+import com.android.quickstep.util.RecentsAtomicAnimationFactory;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -345,6 +347,11 @@
dumpMisc(prefix + "\t", writer);
}
+ @Override
+ public AtomicAnimationFactory<RecentsState> createAtomicAnimationFactory() {
+ return new RecentsAtomicAnimationFactory<>(this, 0);
+ }
+
private AnimatorListenerAdapter resetStateListener() {
return new AnimatorListenerAdapter() {
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 82b0097..a0bb631 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -85,7 +85,6 @@
import com.android.quickstep.util.AssistantUtilities;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.SplitScreenBounds;
-import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.OverscrollPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.recents.IOverviewProxy;
@@ -616,21 +615,6 @@
return;
}
mDeviceState.enableMultipleRegions(baseInputConsumer instanceof OtherActivityInputConsumer);
- BaseDraggingActivity activity =
- mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "handleOrientationSetup.2");
- }
- if (activity == null || !(activity.getOverviewPanel() instanceof RecentsView)) {
- return;
- }
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "handleOrientationSetup.3");
- }
- ((RecentsView) activity.getOverviewPanel())
- .setLayoutRotation(mDeviceState.getCurrentActiveRotation(),
- mDeviceState.getDisplayRotation());
- activity.getDragLayer().recreateControllers();
}
private InputConsumer newBaseConsumer(GestureState previousGestureState,
@@ -848,16 +832,16 @@
}
}
- private BaseSwipeUpHandler createLauncherSwipeHandler(GestureState gestureState,
- long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
- return new LauncherSwipeHandler(this, mDeviceState, mTaskAnimationManager,
+ private BaseSwipeUpHandler createLauncherSwipeHandler(
+ GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
+ return new LauncherSwipeHandlerV2(this, mDeviceState, mTaskAnimationManager,
gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
}
- private BaseSwipeUpHandler createFallbackSwipeHandler(GestureState gestureState,
- long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
- return new FallbackSwipeHandler(this, mDeviceState, gestureState,
- mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
+ private BaseSwipeUpHandler createFallbackSwipeHandler(
+ GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
+ return new FallbackSwipeHandler(this, mDeviceState, mTaskAnimationManager,
+ gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
}
protected boolean shouldNotifyBackGesture() {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index f958e6d..9242771 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -24,11 +24,13 @@
import android.os.Build;
import android.util.AttributeSet;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.quickstep.FallbackActivityInterface;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.Task.TaskKey;
@@ -38,7 +40,7 @@
public class FallbackRecentsView extends RecentsView<RecentsActivity>
implements StateListener<RecentsState> {
- private RunningTaskInfo mRunningTaskInfo;
+ private RunningTaskInfo mHomeTaskInfo;
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -67,16 +69,40 @@
return false;
}
- public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
- mRunningTaskInfo = runningTaskInfo;
- onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
+ /**
+ * When starting gesture interaction from home, we add a temporary invisible tile corresponding
+ * to the home task. This allows us to handle quick-switch similarly to a quick-switching
+ * from a foreground task.
+ */
+ public void onGestureAnimationStartOnHome(RunningTaskInfo homeTaskInfo) {
+ mHomeTaskInfo = homeTaskInfo;
+ onGestureAnimationStart(homeTaskInfo == null ? -1 : homeTaskInfo.taskId);
+ }
+
+ /**
+ * When the gesture ends and recents view become interactive, we also remove the temporary
+ * invisible tile added for the home task. This also pushes the remaining tiles back
+ * to the center.
+ */
+ @Override
+ public void onGestureAnimationEnd() {
+ super.onGestureAnimationEnd();
+ if (mHomeTaskInfo != null) {
+ TaskView tv = getTaskView(mHomeTaskInfo.taskId);
+ if (tv != null) {
+ PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150);
+ pa.addEndListener(e -> setCurrentTask(-1));
+ runDismissAnimation(pa);
+ }
+ }
}
@Override
public void setCurrentTask(int runningTaskId) {
super.setCurrentTask(runningTaskId);
- if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
- mRunningTaskInfo = null;
+ if (mHomeTaskInfo != null && mHomeTaskInfo.taskId != runningTaskId) {
+ mHomeTaskInfo = null;
+ setRunningTaskHidden(false);
}
}
@@ -85,7 +111,7 @@
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
// track the index of the next task appropriately, as if we are switching on any other app.
- if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
+ if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId) {
// Check if the task list has running task
boolean found = false;
for (Task t : tasks) {
@@ -97,7 +123,7 @@
if (!found) {
ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
newList.addAll(tasks);
- newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
+ newList.add(Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false));
tasks = newList;
}
}
@@ -105,6 +131,15 @@
}
@Override
+ public void setRunningTaskHidden(boolean isHidden) {
+ if (mHomeTaskInfo != null) {
+ // Always keep the home task hidden
+ isHidden = true;
+ }
+ super.setRunningTaskHidden(isHidden);
+ }
+
+ @Override
public void setModalStateEnabled(boolean isModalState) {
super.setModalStateEnabled(isModalState);
if (isModalState) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 2dc7f5f..3a97216 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -18,29 +18,31 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_UP;
+
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.quickstep.LauncherSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import static com.android.quickstep.BaseSwipeUpHandlerV2.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
-import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
+
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
+import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.GestureState;
import com.android.quickstep.InputConsumer;
import com.android.quickstep.MultiStateCallback;
@@ -49,18 +51,19 @@
import com.android.quickstep.RecentsAnimationDeviceState;
import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.TaskAnimationManager;
-import com.android.quickstep.util.AppWindowAnimationHelper;
import com.android.quickstep.util.TransformParams;
+import com.android.quickstep.util.TransformParams.BuilderProxy;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
/**
* A dummy input consumer used when the device is still locked, e.g. from secure camera.
*/
public class DeviceLockedInputConsumer implements InputConsumer,
- RecentsAnimationCallbacks.RecentsAnimationListener {
+ RecentsAnimationCallbacks.RecentsAnimationListener, BuilderProxy {
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[2] : null;
private static int getFlagForIndex(int index, String name) {
@@ -83,19 +86,20 @@
private final InputMonitorCompat mInputMonitorCompat;
private final PointF mTouchDown = new PointF();
- private final AppWindowAnimationHelper mAppWindowAnimationHelper;
private final TransformParams mTransformParams;
- private final Point mDisplaySize;
private final MultiStateCallback mStateCallback;
+ private final Point mDisplaySize;
+ private final Matrix mMatrix = new Matrix();
+ private final float mMaxTranslationY;
+
private VelocityTracker mVelocityTracker;
- private float mProgress;
+ private final AnimatedFloat mProgress = new AnimatedFloat(this::applyTransform);
private boolean mThresholdCrossed = false;
private boolean mHomeLaunched = false;
private RecentsAnimationController mRecentsAnimationController;
- private RecentsAnimationTargets mRecentsAnimationTargets;
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
TaskAnimationManager taskAnimationManager, GestureState gestureState,
@@ -105,9 +109,10 @@
mTaskAnimationManager = taskAnimationManager;
mGestureState = gestureState;
mTouchSlopSquared = squaredTouchSlop(context);
- mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
mTransformParams = new TransformParams();
mInputMonitorCompat = inputMonitorCompat;
+ mMaxTranslationY = context.getResources().getDimensionPixelSize(
+ R.dimen.device_locked_y_offset);
// Do not use DeviceProfile as the user data might be locked
mDisplaySize = DefaultDisplay.INSTANCE.get(context).getInfo().realSize;
@@ -158,9 +163,7 @@
}
} else {
float dy = Math.max(mTouchDown.y - y, 0);
- mProgress = dy / mDisplaySize.y;
- mTransformParams.setProgress(mProgress);
- mAppWindowAnimationHelper.applyTransform(mTransformParams);
+ mProgress.updateValue(dy / mDisplaySize.y);
}
break;
}
@@ -189,20 +192,13 @@
// Is fling
dismissTask = velocityY < 0;
} else {
- dismissTask = mProgress >= (1 - MIN_PROGRESS_FOR_OVERVIEW);
+ dismissTask = mProgress.value >= (1 - MIN_PROGRESS_FOR_OVERVIEW);
}
// Animate back to fullscreen before finishing
- ValueAnimator animator = ValueAnimator.ofFloat(mTransformParams.getProgress(), 0f);
+ ObjectAnimator animator = mProgress.animateToValue(mProgress.value, 0);
animator.setDuration(100);
animator.setInterpolator(Interpolators.ACCEL);
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator valueAnimator) {
- mTransformParams.setProgress((float) valueAnimator.getAnimatedValue());
- mAppWindowAnimationHelper.applyTransform(mTransformParams);
- }
- });
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -239,29 +235,15 @@
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
mRecentsAnimationController = controller;
- mRecentsAnimationTargets = targets;
-
- Rect displaySize = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
- RemoteAnimationTargetCompat targetCompat = targets.findTask(
- mGestureState.getRunningTaskId());
- if (targetCompat != null) {
- mAppWindowAnimationHelper.updateSource(displaySize, targetCompat);
- }
-
- // Offset the surface slightly
- displaySize.offset(0, mContext.getResources().getDimensionPixelSize(
- R.dimen.device_locked_y_offset));
- mTransformParams.setTargetSet(mRecentsAnimationTargets);
- mAppWindowAnimationHelper.updateTargetRect(displaySize);
- mAppWindowAnimationHelper.applyTransform(mTransformParams);
-
+ mTransformParams.setTargetSet(targets);
+ applyTransform();
mStateCallback.setState(STATE_TARGET_RECEIVED);
}
@Override
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
mRecentsAnimationController = null;
- mRecentsAnimationTargets = null;
+ mTransformParams.setTargetSet(null);
}
private void endRemoteAnimation() {
@@ -273,6 +255,20 @@
}
}
+ private void applyTransform() {
+ mTransformParams.setProgress(mProgress.value);
+ if (mTransformParams.getTargetSet() != null) {
+ mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
+ }
+ }
+
+ @Override
+ public void onBuildTargetParams(
+ Builder builder, RemoteAnimationTargetCompat app, TransformParams params) {
+ mMatrix.setTranslate(0, mProgress.value * mMaxTranslationY);
+ builder.withMatrix(mMatrix);
+ }
+
@Override
public void onConsumerAboutToBeSwitched() {
mStateCallback.setState(STATE_HANDLER_INVALIDATED);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 6b0d7a3..ab9ec21 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -207,7 +207,7 @@
// Start the window animation on down to give more time for launcher to draw if the
// user didn't start the gesture over the back button
if (!mIsDeferredDownTarget) {
- startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
+ startTouchTrackingForWindowAnimation(ev.getEventTime());
}
TraceHelper.INSTANCE.endSection(traceToken);
@@ -275,8 +275,7 @@
if (mIsDeferredDownTarget) {
// Deferred gesture, start the animation and gesture tracking once
// we pass the actual touch slop
- startTouchTrackingForWindowAnimation(
- ev.getEventTime(), isLikelyToStartNewTask);
+ startTouchTrackingForWindowAnimation(ev.getEventTime());
}
if (!mPassedWindowMoveSlop) {
mPassedWindowMoveSlop = true;
@@ -326,12 +325,11 @@
mInteractionHandler.onGestureStarted();
}
- private void startTouchTrackingForWindowAnimation(
- long touchTimeMs, boolean isLikelyToStartNewTask) {
+ private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimation");
mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs,
- mTaskAnimationManager.isRecentsAnimationRunning(), isLikelyToStartNewTask);
+ mTaskAnimationManager.isRecentsAnimationRunning());
mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged);
Intent intent = new Intent(mInteractionHandler.getLaunchIntent());
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
index a7979cc..b743d3f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java
@@ -77,7 +77,6 @@
private final Matrix mTmpMatrix = new Matrix();
private final Rect mTmpRect = new Rect();
private final RectF mTmpRectF = new RectF();
- private final RectF mCurrentRectWithInsets = new RectF();
private RecentsOrientedState mOrientedState;
// Corner radius of windows, in pixels
private final float mWindowCornerRadius;
@@ -88,9 +87,6 @@
// Whether or not to actually use the rounded cornders on windows
private boolean mUseRoundedCornersOnWindows;
- // Corner radius currently applied to transformed window.
- private float mCurrentCornerRadius;
-
public AppWindowAnimationHelper(RecentsOrientedState orientedState, Context context) {
Resources res = context.getResources();
mOrientedState = orientedState;
@@ -100,25 +96,9 @@
mUseRoundedCornersOnWindows = mSupportsRoundedCornersOnWindows;
}
- public AppWindowAnimationHelper(Context context) {
- this(null, context);
- }
-
private void updateSourceStack(RemoteAnimationTargetCompat target) {
mSourceInsets.set(target.contentInsets);
mSourceStackBounds.set(target.screenSpaceBounds);
-
- // TODO: Should sourceContainerBounds already have this offset?
- mSourceStackBounds.offsetTo(target.position.x, target.position.y);
- }
-
- public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) {
- updateSourceStack(target);
- updateHomeBounds(homeStackBounds);
- }
-
- public void updateHomeBounds(Rect homeStackBounds) {
- mHomeStackBounds.set(homeStackBounds);
}
public void updateTargetRect(Rect targetRect) {
@@ -186,14 +166,14 @@
crop.offsetTo(0, 0);
float cornerRadius = 0f;
float scale = Math.max(mCurrentRect.width(), mTargetRect.width()) / crop.width();
+ mTmpMatrix.setTranslate(0, 0);
+ if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
+ mTmpMatrix.setTranslate(app.localBounds.left, app.localBounds.top);
+ }
if (app.mode == targetMode
&& app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, mCurrentRect, ScaleToFit.FILL);
- if (app.localBounds != null) {
- mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
- } else {
- mTmpMatrix.postTranslate(app.position.x, app.position.y);
- }
+ mTmpMatrix.postTranslate(app.localBounds.left, app.localBounds.top);
mCurrentClipRectF.roundOut(crop);
if (mSupportsRoundedCornersOnWindows) {
if (params.getCornerRadius() > -1) {
@@ -205,7 +185,6 @@
cornerRadius = mapRange(boundToRange(params.getProgress(), 0, 1),
windowCornerRadius, mTaskCornerRadius);
}
- mCurrentCornerRadius = cornerRadius;
}
builder.withMatrix(mTmpMatrix)
@@ -241,11 +220,6 @@
mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress);
}
- public RectF getCurrentRectWithInsets() {
- mTmpMatrix.mapRect(mCurrentRectWithInsets, mCurrentClipRectF);
- return mCurrentRectWithInsets;
- }
-
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv,
@Nullable RemoteAnimationTargetCompat target) {
BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
@@ -317,8 +291,4 @@
return mTargetRect;
}
- public float getCurrentCornerRadius() {
- return mCurrentCornerRadius;
- }
-
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
new file mode 100644
index 0000000..5b0d503
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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 static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
+import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.quickstep.views.RecentsView;
+
+public class RecentsAtomicAnimationFactory<ACTIVITY_TYPE extends StatefulActivity, STATE_TYPE>
+ extends AtomicAnimationFactory<STATE_TYPE> {
+
+ public static final int INDEX_RECENTS_FADE_ANIM = AtomicAnimationFactory.NEXT_INDEX + 0;
+ public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = AtomicAnimationFactory.NEXT_INDEX + 1;
+
+ private static final int MY_ANIM_COUNT = 2;
+ protected static final int NEXT_INDEX = AtomicAnimationFactory.NEXT_INDEX + MY_ANIM_COUNT;
+
+ protected final ACTIVITY_TYPE mActivity;
+
+ /**
+ * @param extraAnims number of animations supported by the subclass. This should not include
+ * the 2 animations supported by this class.
+ */
+ public RecentsAtomicAnimationFactory(ACTIVITY_TYPE activity, int extraAnims) {
+ super(MY_ANIM_COUNT + extraAnims);
+ mActivity = activity;
+ }
+
+ @Override
+ public Animator createStateElementAnimation(int index, float... values) {
+ switch (index) {
+ case INDEX_RECENTS_FADE_ANIM:
+ return ObjectAnimator.ofFloat(mActivity.getOverviewPanel(),
+ RecentsView.CONTENT_ALPHA, values);
+ case INDEX_RECENTS_TRANSLATE_X_ANIM: {
+ RecentsView rv = mActivity.getOverviewPanel();
+ return new SpringAnimationBuilder(mActivity)
+ .setMinimumVisibleChange(1f / rv.getPageOffsetScale())
+ .setDampingRatio(0.8f)
+ .setStiffness(250)
+ .setValues(values)
+ .build(rv, ADJACENT_PAGE_OFFSET);
+ }
+ default:
+ return super.createStateElementAnimation(index, values);
+ }
+ }
+}
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
index 32fc0de..3e0daaf 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -212,12 +212,13 @@
}
private void addScrimAnimationForState(Launcher launcher, LauncherState state, long duration) {
- PendingAnimation builder = new PendingAnimation(duration, mAnimators);
+ PendingAnimation builder = new PendingAnimation(duration);
launcher.getWorkspace().getStateTransitionAnimation().setScrim(builder, state);
builder.setFloat(
launcher.getDragLayer().getOverviewScrim(),
OverviewScrim.SCRIM_PROGRESS,
state.getOverviewScrimAlpha(launcher),
ACCEL_DEACCEL);
+ mAnimators.play(builder.buildAnim());
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
index a3db940..348c22d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -20,6 +20,7 @@
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
+import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
@@ -29,6 +30,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseActivityInterface;
@@ -114,7 +116,8 @@
if (mDp == null) {
return 1;
}
- mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
+ mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect,
+ mOrientationState.getOrientationHandler());
return mOrientationState.getFullScreenScaleAndPivot(mTaskRect, mDp, mPivot);
}
@@ -129,8 +132,6 @@
mThumbnailData.windowingMode = WINDOWING_MODE_FULLSCREEN;
mThumbnailPosition.set(runningTarget.screenSpaceBounds);
- // TODO: Should sourceContainerBounds already have this offset?
- mThumbnailPosition.offset(-mRunningTarget.position.x, -mRunningTarget.position.y);
mLayoutValid = false;
}
@@ -145,6 +146,14 @@
}
/**
+ * Adds animation for all the components corresponding to transition from an app to overview
+ */
+ public void addAppToOverviewAnim(PendingAnimation pa, TimeInterpolator interpolator) {
+ pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator);
+ pa.addFloat(recentsViewScale, AnimatedFloat.VALUE, getFullScreenScale(), 1, interpolator);
+ }
+
+ /**
* Returns the current clipped/visible window bounds in the window coordinate space
*/
public RectF getCurrentCropRect() {
@@ -250,14 +259,11 @@
}
@Override
- public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app,
- int targetMode, TransformParams params) {
- if (app.mode == targetMode
- && app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
- builder.withMatrix(mMatrix)
- .withWindowCrop(mTmpCropRect)
- .withCornerRadius(getCurrentCornerRadius());
- }
+ public void onBuildTargetParams(
+ Builder builder, RemoteAnimationTargetCompat app, TransformParams params) {
+ builder.withMatrix(mMatrix)
+ .withWindowCrop(mTmpCropRect)
+ .withCornerRadius(getCurrentCornerRadius());
}
/**
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
index 83b64db..d837e54 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
@@ -16,6 +16,7 @@
package com.android.quickstep.util;
import android.graphics.RectF;
+import android.util.FloatProperty;
import androidx.annotation.Nullable;
@@ -29,6 +30,19 @@
public class TransformParams {
+ public static FloatProperty<TransformParams> PROGRESS =
+ new FloatProperty<TransformParams>("progress") {
+ @Override
+ public void setValue(TransformParams params, float v) {
+ params.setProgress(v);
+ }
+
+ @Override
+ public Float get(TransformParams params) {
+ return params.getProgress();
+ }
+ };
+
private float mProgress;
private @Nullable RectF mCurrentRect;
private float mTargetAlpha;
@@ -176,10 +190,6 @@
return mTargetSet;
}
- public SyncRtSurfaceTransactionApplierCompat getSyncTransactionApplier() {
- return mSyncTransactionApplier;
- }
-
public void applySurfaceParams(SurfaceParams[] params) {
if (mSyncTransactionApplier != null) {
mSyncTransactionApplier.scheduleApply(params);
@@ -199,7 +209,15 @@
public interface BuilderProxy {
- void onBuildParams(SurfaceParams.Builder builder,
- RemoteAnimationTargetCompat app, int targetMode, TransformParams params);
+ default void onBuildParams(SurfaceParams.Builder builder,
+ RemoteAnimationTargetCompat app, int targetMode, TransformParams params) {
+ if (app.mode == targetMode
+ && app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
+ onBuildTargetParams(builder, app, params);
+ }
+ }
+
+ default void onBuildTargetParams(SurfaceParams.Builder builder,
+ RemoteAnimationTargetCompat app, TransformParams params) { }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
index 2c85618..fd74357 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
@@ -47,24 +47,21 @@
private boolean mIsRtl;
private int mScrollOffset;
- private RecentsView mParent;
public ClearAllButton(Context context, AttributeSet attrs) {
super(context, attrs);
+ mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- PagedOrientationHandler orientationHandler = mParent.getPagedOrientationHandler();
- mScrollOffset = orientationHandler.getClearAllScrollOffset(mParent, mIsRtl);
+ PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
+ mScrollOffset = orientationHandler.getClearAllScrollOffset(getRecentsView(), mIsRtl);
}
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- mParent = (RecentsView) getParent();
- mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+ private RecentsView getRecentsView() {
+ return (RecentsView) getParent();
}
@Override
@@ -94,7 +91,7 @@
@Override
public void onPageScroll(ScrollState scrollState) {
- PagedOrientationHandler orientationHandler = mParent.getPagedOrientationHandler();
+ PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
float orientationSize = orientationHandler.getPrimaryValue(getWidth(), getHeight());
if (orientationSize == 0) {
return;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 253e83c..3273e85 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -17,6 +17,8 @@
package com.android.quickstep.views;
import static android.view.Surface.ROTATION_0;
+import static android.view.View.MeasureSpec.EXACTLY;
+import static android.view.View.MeasureSpec.makeMeasureSpec;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
@@ -827,6 +829,10 @@
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
+ resetPaddingFromTaskSize();
+ }
+
+ private void resetPaddingFromTaskSize() {
DeviceProfile dp = mActivity.getDeviceProfile();
mOrientationState.setMultiWindowMode(dp.isMultiWindowMode);
getTaskSize(mTempRect);
@@ -840,7 +846,8 @@
}
public void getTaskSize(Rect outRect) {
- mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect);
+ mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
+ mOrientationHandler);
}
/** Gets the task size for modal state. */
@@ -1075,9 +1082,9 @@
* Called when a gesture from an app has finished.
*/
public void onGestureAnimationEnd() {
+ setOnScrollChangeListener(null);
setEnableFreeScroll(true);
setEnableDrawingLiveTile(true);
- setOnScrollChangeListener(null);
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
setRunningTaskViewShowScreenshot(true);
}
@@ -1108,6 +1115,12 @@
false, true, false, false, new ActivityManager.TaskDescription(), 0,
new ComponentName("", ""), false);
taskView.bind(mTmpRunningTask, mOrientationState);
+
+ // Measure and layout immediately so that the scroll values is updated instantly
+ // as the user might be quick-switching
+ measure(makeMeasureSpec(getMeasuredWidth(), EXACTLY),
+ makeMeasureSpec(getMeasuredHeight(), EXACTLY));
+ layout(getLeft(), getTop(), getRight(), getBottom());
}
boolean runningTaskTileHidden = mRunningTaskTileHidden;
@@ -1484,7 +1497,7 @@
return true;
}
- private void runDismissAnimation(PendingAnimation pendingAnim) {
+ protected void runDismissAnimation(PendingAnimation pendingAnim) {
AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
controller.dispatchOnStart();
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
@@ -1618,6 +1631,7 @@
mActivity.getDragLayer().recreateControllers();
mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION,
touchRotation != 0 || mOrientationState.getLauncherRotation() != ROTATION_0);
+ resetPaddingFromTaskSize();
requestLayout();
}
}
@@ -2190,6 +2204,10 @@
*/
public void setModalStateEnabled(boolean isModalState) { }
+ public BaseActivityInterface getSizeStrategy() {
+ return mSizeStrategy;
+ }
+
/**
* Used to register callbacks for when our empty message state changes.
*
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
index a3e360f..e3c1b42 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -472,7 +472,6 @@
} else {
setThumbnailRotation(deltaRotate, thumbnailInsets, scale, thumbnailPosition);
}
- mMatrix.postTranslate(-thumbnailPosition.left, -thumbnailPosition.top);
final float widthWithInsets;
final float heightWithInsets;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index e5c9fc9..8745814 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -32,6 +32,7 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -43,6 +44,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
+import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.AbstractStateChangeTouchController;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.uioverrides.states.OverviewState;
@@ -51,6 +53,7 @@
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.views.RecentsView;
/**
* Touch controller for handling various state transitions in portrait UI.
@@ -129,11 +132,22 @@
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "PortraitStatesTouchController.getTargetState");
+ }
if (fromState == ALL_APPS && !isDragTowardPositive) {
// Should swipe down go to OVERVIEW instead?
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
+ "PortraitStatesTouchController.getTargetState 1");
+ }
return TouchInteractionService.isConnected() ?
mLauncher.getStateManager().getLastState() : NORMAL;
} else if (fromState == OVERVIEW) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
+ "PortraitStatesTouchController.getTargetState 2");
+ }
LauncherState positiveDragTarget = ALL_APPS;
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) {
// Don't allow swiping up to all apps.
@@ -141,6 +155,10 @@
}
return isDragTowardPositive ? positiveDragTarget : NORMAL;
} else if (fromState == NORMAL && isDragTowardPositive) {
+ if (TestProtocol.sDebugTracing) {
+ Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
+ "PortraitStatesTouchController.getTargetState 3");
+ }
int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
return mAllowDragToOverview && TouchInteractionService.isConnected()
&& (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0
@@ -244,8 +262,9 @@
mCurrentAnimation = mPendingAnimation.createPlaybackController()
.setOnCancelRunnable(onCancelRunnable);
mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation);
+ RecentsView recentsView = mLauncher.getOverviewPanel();
totalShift = LayoutUtils.getShelfTrackingDistance(mLauncher,
- mLauncher.getDeviceProfile());
+ mLauncher.getDeviceProfile(), recentsView.getPagedOrientationHandler());
} else {
mCurrentAnimation = mLauncher.getStateManager()
.createAnimationToNewWorkspace(mToState, config)
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index f29f0ff..022977b 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -15,14 +15,24 @@
*/
package com.android.quickstep;
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
+import static com.android.quickstep.BaseSwipeUpHandlerV2.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.SysUINavigationMode.getMode;
+import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
+import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
+import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
+import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
+import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
+import android.animation.Animator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.view.MotionEvent;
@@ -34,9 +44,11 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
@@ -56,11 +68,15 @@
public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_TYPE>,
ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>> {
- private final PointF mTempPoint = new PointF();
public final boolean rotationSupportedByActivity;
- protected BaseActivityInterface(boolean rotationSupportedByActivity) {
+ private final STATE_TYPE mOverviewState, mBackgroundState;
+
+ protected BaseActivityInterface(boolean rotationSupportedByActivity,
+ STATE_TYPE overviewState, STATE_TYPE backgroundState) {
this.rotationSupportedByActivity = rotationSupportedByActivity;
+ mOverviewState = overviewState;
+ mBackgroundState = backgroundState;
}
public void onTransitionCancelled(boolean activityVisible) {
@@ -73,7 +89,8 @@
}
public abstract int getSwipeUpDestinationAndLength(
- DeviceProfile dp, Context context, Rect outRect);
+ DeviceProfile dp, Context context, Rect outRect,
+ PagedOrientationHandler orientationHandler);
public void onSwipeUpToRecentsComplete() {
// Re apply state in case we did something funky during the transition.
@@ -84,7 +101,7 @@
activity.getStateManager().reapplyState();
}
- public void onSwipeUpToHomeComplete() { }
+ public abstract void onSwipeUpToHomeComplete();
public abstract void onAssistantVisibilityChanged(float visibility);
@@ -130,7 +147,7 @@
public abstract boolean allowMinimizeSplitScreen();
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
- return true;
+ return deviceState.isInDeferredGestureRegion(ev);
}
/**
@@ -174,26 +191,24 @@
recentsView.switchToScreenshot(thumbnailData, runnable);
}
- public void setHintUserWillBeActive() {}
-
- /**
- * Sets the expected window size in multi-window mode
- */
- public abstract void getMultiWindowSize(Context context, DeviceProfile dp, PointF out);
-
/**
* Calculates the taskView size for the provided device configuration
*/
- public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
- calculateTaskSize(context, dp, getExtraSpace(context, dp), outRect);
+ public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
+ PagedOrientationHandler orientedState) {
+ calculateTaskSize(context, dp, getExtraSpace(context, dp, orientedState),
+ outRect, orientedState);
}
- protected abstract float getExtraSpace(Context context, DeviceProfile dp);
+ protected abstract float getExtraSpace(Context context, DeviceProfile dp,
+ PagedOrientationHandler orientedState);
private void calculateTaskSize(
- Context context, DeviceProfile dp, float extraVerticalSpace, Rect outRect) {
+ Context context, DeviceProfile dp, float extraVerticalSpace, Rect outRect,
+ PagedOrientationHandler orientationHandler) {
Resources res = context.getResources();
- final boolean showLargeTaskSize = showOverviewActions(context);
+ final boolean showLargeTaskSize = showOverviewActions(context) ||
+ hideShelfInTwoButtonLandscape(context, orientationHandler);
final int paddingResId;
if (dp.isMultiWindowMode) {
@@ -251,7 +266,7 @@
/**
* Calculates the modal taskView size for the provided device configuration
*/
- public void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+ public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
float paddingHorz = context.getResources().getDimension(dp.isMultiWindowMode
? R.dimen.multi_window_task_card_horz_space
: dp.isVerticalBarLayout()
@@ -265,7 +280,7 @@
}
/** Gets the space that the overview actions will take, including margins. */
- public float getOverviewActionsHeight(Context context) {
+ public final float getOverviewActionsHeight(Context context) {
Resources res = context.getResources();
float actionsBottomMargin = 0;
if (getMode(context) == Mode.THREE_BUTTONS) {
@@ -282,8 +297,6 @@
public interface AnimationFactory {
- default void onRemoteAnimationReceived(RemoteAnimationTargets targets) { }
-
void createActivityInterface(long transitionLength);
default void onTransitionCancelled() { }
@@ -299,6 +312,97 @@
default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
}
+ class DefaultAnimationFactory implements AnimationFactory {
+
+ protected final ACTIVITY_TYPE mActivity;
+ private final STATE_TYPE mStartState;
+ private final Consumer<AnimatorPlaybackController> mCallback;
+
+ private boolean mIsAttachedToWindow;
+
+ DefaultAnimationFactory(Consumer<AnimatorPlaybackController> callback) {
+ mCallback = callback;
+
+ mActivity = getCreatedActivity();
+ mStartState = mActivity.getStateManager().getState();
+ }
+
+ protected ACTIVITY_TYPE initUI() {
+ STATE_TYPE resetState = mStartState;
+ if (mStartState.shouldDisableRestore()) {
+ resetState = mActivity.getStateManager().getRestState();
+ }
+ mActivity.getStateManager().setRestState(resetState);
+ mActivity.getStateManager().goToState(mBackgroundState, false);
+ return mActivity;
+ }
+
+ @Override
+ public void createActivityInterface(long transitionLength) {
+ PendingAnimation pa = new PendingAnimation(transitionLength * 2);
+ createBackgroundToOverviewAnim(mActivity, pa);
+ AnimatorPlaybackController controller = pa.createPlaybackController();
+ mActivity.getStateManager().setCurrentUserControlledAnimation(controller);
+
+ // Since we are changing the start position of the UI, reapply the state, at the end
+ controller.setEndAction(() -> mActivity.getStateManager().goToState(
+ controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
+ false));
+ mCallback.accept(controller);
+
+ // Creating the activity controller animation sometimes reapplies the launcher state
+ // (because we set the animation as the current state animation), so we reapply the
+ // attached state here as well to ensure recents is shown/hidden appropriately.
+ if (SysUINavigationMode.getMode(mActivity) == Mode.NO_BUTTON) {
+ setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
+ }
+ }
+
+ @Override
+ public void onTransitionCancelled() {
+ mActivity.getStateManager().goToState(mStartState, false /* animate */);
+ }
+
+ @Override
+ public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
+ if (mIsAttachedToWindow == attached && animate) {
+ return;
+ }
+ mIsAttachedToWindow = attached;
+ RecentsView recentsView = mActivity.getOverviewPanel();
+ Animator fadeAnim = mActivity.getStateManager()
+ .createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
+
+ float fromTranslation = attached ? 1 : 0;
+ float toTranslation = attached ? 0 : 1;
+ mActivity.getStateManager()
+ .cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
+ if (!recentsView.isShown() && animate) {
+ ADJACENT_PAGE_OFFSET.set(recentsView, fromTranslation);
+ } else {
+ fromTranslation = ADJACENT_PAGE_OFFSET.get(recentsView);
+ }
+ if (!animate) {
+ ADJACENT_PAGE_OFFSET.set(recentsView, toTranslation);
+ } else {
+ mActivity.getStateManager().createStateElementAnimation(
+ INDEX_RECENTS_TRANSLATE_X_ANIM,
+ fromTranslation, toTranslation).start();
+ }
+
+ fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
+ fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
+ }
+
+ protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
+ // Scale down recents from being full screen to being in overview.
+ RecentsView recentsView = activity.getOverviewPanel();
+ pa.addFloat(recentsView, SCALE_PROPERTY,
+ recentsView.getMaxScaleForFullScreen(), 1, LINEAR);
+ pa.addFloat(recentsView, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
+ }
+ }
+
protected static boolean showOverviewActions(Context context) {
return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
}
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 8e14bbb..016ffea 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -322,7 +322,7 @@
pw.println(" gestureID=" + mGestureId);
pw.println(" runningTask=" + mRunningTask);
pw.println(" endTarget=" + mEndTarget);
- pw.println(" lastAppearedTaskTarget=" + mLastAppearedTaskTarget);
+ pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId());
pw.println(" lastStartedTaskId=" + mLastStartedTaskId);
pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning());
}
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 879fd1d..4cf7aab 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -317,13 +317,6 @@
private class OrientationRectF extends RectF {
- /**
- * Delta to subtract width and height by because if we report the translated touch
- * bounds as the width and height, calling {@link RectF#contains(float, float)} will
- * be false
- */
- private float maxDelta = 0.001f;
-
private int mRotation;
private float mHeight;
private float mWidth;
@@ -331,8 +324,8 @@
OrientationRectF(float left, float top, float right, float bottom, int rotation) {
super(left, top, right, bottom);
this.mRotation = rotation;
- mHeight = bottom - maxDelta;
- mWidth = right - maxDelta;
+ mHeight = bottom;
+ mWidth = right;
}
@Override
@@ -342,6 +335,13 @@
return s;
}
+ @Override
+ public boolean contains(float x, float y) {
+ // Mark bottom right as included in the Rect (copied from Rect src, added "=" in "<=")
+ return left < right && top < bottom // check for empty first
+ && x >= left && x <= right && y >= top && y <= bottom;
+ }
+
boolean applyTransform(MotionEvent event, boolean forceTransform) {
mTmpMatrix.reset();
postDisplayRotation(deltaRotation(mCurrentDisplayRotation, mRotation),
diff --git a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
index 5fa6bc7..f90df45 100644
--- a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
@@ -68,7 +68,7 @@
}
public boolean isAnimatingHome() {
- for (RemoteAnimationTargetCompat target : apps) {
+ for (RemoteAnimationTargetCompat target : unfilteredApps) {
if (target.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
return true;
}
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
index c715c93..05ce2a2 100644
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.util.Log;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.MainThreadInitializedObject;
import java.io.PrintWriter;
@@ -134,6 +135,12 @@
return getMode(context) != Mode.TWO_BUTTONS;
}
+ public static boolean hideShelfInTwoButtonLandscape(Context context,
+ PagedOrientationHandler pagedOrientationHandler) {
+ return getMode(context) == Mode.TWO_BUTTONS &&
+ !pagedOrientationHandler.isLayoutNaturalToLauncher();
+ }
+
public void dump(PrintWriter pw) {
pw.println("SysUINavigationMode:");
pw.println(" mode=" + mMode.name());
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index c1b276a..3f58e01 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -25,6 +25,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
@@ -41,11 +42,13 @@
return swipeHeight;
}
- public static int getShelfTrackingDistance(Context context, DeviceProfile dp) {
+ public static int getShelfTrackingDistance(Context context, DeviceProfile dp,
+ PagedOrientationHandler orientationHandler) {
// Track the bottom of the window.
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
Rect taskSize = new Rect();
- LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize);
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize,
+ orientationHandler);
return (dp.heightPx - taskSize.height()) / 2;
}
int shelfHeight = dp.hotseatBarSizePx + dp.getInsets().bottom;
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index e03f4b8..4c47d7f 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -27,6 +27,7 @@
import static com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.content.ContentResolver;
@@ -53,6 +54,7 @@
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.SysUINavigationMode;
import java.lang.annotation.Retention;
import java.util.function.IntConsumer;
@@ -118,6 +120,9 @@
MASK_MULTIPLE_ORIENTATION_SUPPORTED_BY_DEVICE | FLAG_SYSTEM_ROTATION_ALLOWED
| FLAG_ROTATION_WATCHER_SUPPORTED | FLAG_ROTATION_WATCHER_ENABLED;
+ private SysUINavigationMode.NavigationModeChangeListener mNavModeChangeListener =
+ newMode -> setFlag(FLAG_ROTATION_WATCHER_SUPPORTED, newMode != TWO_BUTTONS);
+
private final Context mContext;
private final ContentResolver mContentResolver;
private final SharedPreferences mSharedPrefs;
@@ -163,13 +168,7 @@
if (isFixedRotationTransformEnabled(context)) {
mFlags |= FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_FLAG;
}
- if (mOrientationListener.canDetectOrientation()) {
- mFlags |= FLAG_ROTATION_WATCHER_SUPPORTED;
- }
-
- // initialize external flags
- updateAutoRotateSetting();
- updateHomeRotationSetting();
+ initFlags();
}
/**
@@ -273,6 +272,18 @@
mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY, false));
}
+ private void initFlags() {
+ SysUINavigationMode.Mode currentMode = SysUINavigationMode.getMode(mContext);
+ if (mOrientationListener.canDetectOrientation() &&
+ currentMode != TWO_BUTTONS) {
+ mFlags |= FLAG_ROTATION_WATCHER_SUPPORTED;
+ }
+
+ // initialize external flags
+ updateAutoRotateSetting();
+ updateHomeRotationSetting();
+ }
+
/**
* Initializes any system values and registers corresponding change listeners. It must be
* paired with {@link #destroyListeners()} call
@@ -283,9 +294,11 @@
mContentResolver.registerContentObserver(
Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION),
false, mSystemAutoRotateObserver);
+ SysUINavigationMode.Mode currentMode =
+ SysUINavigationMode.INSTANCE.get(mContext)
+ .addModeChangeListener(mNavModeChangeListener);
}
- updateAutoRotateSetting();
- updateHomeRotationSetting();
+ initFlags();
}
/**
@@ -295,6 +308,8 @@
if (isMultipleOrientationSupportedByDevice()) {
mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
mContentResolver.unregisterContentObserver(mSystemAutoRotateObserver);
+ SysUINavigationMode.INSTANCE.get(mContext)
+ .removeModeChangeListener(mNavModeChangeListener);
}
setRotationWatcherEnabled(false);
}
diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java
index faa18b8..9a66d32 100644
--- a/src/com/android/launcher3/InsettableFrameLayout.java
+++ b/src/com/android/launcher3/InsettableFrameLayout.java
@@ -91,6 +91,9 @@
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
+ if (!isAttachedToWindow()) {
+ return;
+ }
setFrameLayoutChildInsets(child, mInsets, new Rect());
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 87ead9e..535c9e6 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -153,12 +153,16 @@
public static final int CONTAINER_PREDICTION = -102;
public static final int CONTAINER_HOTSEAT_PREDICTION = -103;
public static final int CONTAINER_ALL_APPS = -104;
+ public static final int CONTAINER_WIDGETS_TRAY = -105;
+
public static final String containerToString(int container) {
switch (container) {
case CONTAINER_DESKTOP: return "desktop";
case CONTAINER_HOTSEAT: return "hotseat";
case CONTAINER_PREDICTION: return "prediction";
+ case CONTAINER_ALL_APPS: return "all_apps";
+ case CONTAINER_WIDGETS_TRAY: return "widgets_tray";
default: return String.valueOf(container);
}
}
diff --git a/src/com/android/launcher3/PendingAddItemInfo.java b/src/com/android/launcher3/PendingAddItemInfo.java
index 29c9d93..be994ee 100644
--- a/src/com/android/launcher3/PendingAddItemInfo.java
+++ b/src/com/android/launcher3/PendingAddItemInfo.java
@@ -18,12 +18,15 @@
import android.content.ComponentName;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.model.data.ItemInfo;
+import java.util.Optional;
+
/**
- * Meta data that is used for deferred binding.
- * e.g., this object is used to pass information on draggable targets when they are dropped onto
- * the workspace from another container.
+ * Meta data that is used for deferred binding. e.g., this object is used to pass information on
+ * draggable targets when they are dropped onto the workspace from another container.
*/
public class PendingAddItemInfo extends ItemInfo {
@@ -36,4 +39,22 @@
protected String dumpProperties() {
return super.dumpProperties() + " componentName=" + componentName;
}
+
+ /**
+ * Returns shallow copy of the object.
+ */
+ @Override
+ public ItemInfo makeShallowCopy() {
+ PendingAddItemInfo itemInfo = new PendingAddItemInfo();
+ itemInfo.copyFrom(this);
+ itemInfo.componentName = this.componentName;
+ return itemInfo;
+ }
+
+ @Nullable
+ @Override
+ public ComponentName getTargetComponent() {
+ return Optional.ofNullable(super.getTargetComponent()).orElse(componentName);
+ }
+
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 286b522..6b660c1 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2438,6 +2438,10 @@
// widgets/shortcuts/folders in a slightly different way
mLauncher.addPendingItem(pendingInfo, container, screenId, mTargetCell,
item.spanX, item.spanY);
+ mStatsLogManager.log(
+ LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
+ d.logInstanceId,
+ d.dragInfo.buildProto(null));
}
};
boolean isWidget = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
@@ -2526,11 +2530,12 @@
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view, this);
resetTransitionTransform();
}
+ mStatsLogManager.log(
+ LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
+ d.logInstanceId,
+ d.dragInfo.buildProto(null));
}
- mStatsLogManager.log(
- LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
- d.logInstanceId,
- d.dragInfo.buildProto(null));
+
}
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 5397942..b4ff5ea 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -34,6 +34,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.statemanager.StateManager.StateListener;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.OnboardingPrefs;
/**
@@ -153,16 +154,19 @@
new DiscoveryBounce(launcher, 0).show(HOTSEAT);
}
- public static void showForOverviewIfNeeded(Launcher launcher) {
- showForOverviewIfNeeded(launcher, true);
+ public static void showForOverviewIfNeeded(Launcher launcher,
+ PagedOrientationHandler orientationHandler) {
+ showForOverviewIfNeeded(launcher, true, orientationHandler);
}
- private static void showForOverviewIfNeeded(Launcher launcher, boolean withDelay) {
+ private static void showForOverviewIfNeeded(Launcher launcher, boolean withDelay,
+ PagedOrientationHandler orientationHandler) {
OnboardingPrefs onboardingPrefs = launcher.getOnboardingPrefs();
if (!launcher.isInState(OVERVIEW)
|| !launcher.hasBeenResumed()
|| launcher.isForceInvisible()
|| launcher.getDeviceProfile().isVerticalBarLayout()
+ || !orientationHandler.isLayoutNaturalToLauncher()
|| onboardingPrefs.getBoolean(OnboardingPrefs.SHELF_BOUNCE_SEEN)
|| launcher.getSystemService(UserManager.class).isDemoUser()
|| Utilities.IS_RUNNING_IN_TEST_HARNESS) {
@@ -170,7 +174,8 @@
}
if (withDelay) {
- new Handler().postDelayed(() -> showForOverviewIfNeeded(launcher, false), DELAY_MS);
+ new Handler().postDelayed(() -> showForOverviewIfNeeded(launcher, false,
+ orientationHandler), DELAY_MS);
return;
} else if (AbstractFloatingView.getTopOpenView(launcher) != null) {
// TODO: Move these checks to the top and call this method after invalidate handler.
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 740f7f2..0f04104 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.anim.AnimatorPlaybackController.addAnimationHoldersRecur;
import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
@@ -51,12 +52,8 @@
private ValueAnimator mProgressAnimator;
public PendingAnimation(long duration) {
- this(duration, new AnimatorSet());
- }
-
- public PendingAnimation(long duration, AnimatorSet targetSet) {
mDuration = duration;
- mAnim = targetSet;
+ mAnim = new AnimatorSet();
}
/**
@@ -129,13 +126,32 @@
public void addOnFrameCallback(Runnable runnable) {
if (mProgressAnimator == null) {
mProgressAnimator = ValueAnimator.ofFloat(0, 1).setDuration(mDuration);
- add(mProgressAnimator);
}
mProgressAnimator.addUpdateListener(anim -> runnable.run());
}
- public AnimatorSet getAnim() {
+ /**
+ * @see AnimatorSet#addListener(AnimatorListener)
+ */
+ public void addListener(Animator.AnimatorListener listener) {
+ mAnim.addListener(listener);
+ }
+
+ /**
+ * Creates and returns the underlying AnimatorSet
+ */
+ public AnimatorSet buildAnim() {
+ // Add progress animation to the end, so that frame callback is called after all the other
+ // animation update.
+ if (mProgressAnimator != null) {
+ add(mProgressAnimator);
+ mProgressAnimator = null;
+ }
+ if (mAnimHolders.isEmpty()) {
+ // Add a dummy animation to that the duration is respected
+ add(ValueAnimator.ofFloat(0, 1));
+ }
return mAnim;
}
@@ -143,7 +159,7 @@
* Creates a controller for this animation
*/
public AnimatorPlaybackController createPlaybackController() {
- return new AnimatorPlaybackController(mAnim, mDuration, mAnimHolders);
+ return new AnimatorPlaybackController(buildAnim(), mDuration, mAnimHolders);
}
/**
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index b240f0b..475305f 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -35,50 +35,50 @@
}
public enum LauncherEvent implements EventEnum {
- @LauncherUiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
+ @UiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
LAUNCHER_APP_LAUNCH_TAP(338),
- @LauncherUiEvent(doc = "Task launched from overview using TAP")
+ @UiEvent(doc = "Task launched from overview using TAP")
LAUNCHER_TASK_LAUNCH_TAP(339),
- @LauncherUiEvent(doc = "Task launched from overview using SWIPE DOWN")
+ @UiEvent(doc = "Task launched from overview using SWIPE DOWN")
LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(340),
- @LauncherUiEvent(doc = "TASK dismissed from overview using SWIPE UP")
+ @UiEvent(doc = "TASK dismissed from overview using SWIPE UP")
LAUNCHER_TASK_DISMISS_SWIPE_UP(341),
- @LauncherUiEvent(doc = "User dragged a launcher item")
+ @UiEvent(doc = "User dragged a launcher item")
LAUNCHER_ITEM_DRAG_STARTED(383),
- @LauncherUiEvent(doc = "A dragged launcher item is successfully dropped")
+ @UiEvent(doc = "A dragged launcher item is successfully dropped")
LAUNCHER_ITEM_DROP_COMPLETED(385),
- @LauncherUiEvent(doc = "A dragged launcher item is successfully dropped on another item "
+ @UiEvent(doc = "A dragged launcher item is successfully dropped on another item "
+ "resulting in a new folder creation")
LAUNCHER_ITEM_DROP_FOLDER_CREATED(386),
- @LauncherUiEvent(doc = "User action resulted in or manually updated the folder label to "
+ @UiEvent(doc = "User action resulted in or manually updated the folder label to "
+ "new/same value.")
LAUNCHER_FOLDER_LABEL_UPDATED(460),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Remove' button in the target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Remove' button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_REMOVE(465),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Cancel' button in the target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Cancel' button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_CANCEL(466),
- @LauncherUiEvent(doc = "A predicted item is dragged and dropped on 'Don't suggest app'"
+ @UiEvent(doc = "A predicted item is dragged and dropped on 'Don't suggest app'"
+ " button in the target bar")
LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST(467),
- @LauncherUiEvent(doc = "A dragged item is dropped on 'Uninstall' button in target bar")
+ @UiEvent(doc = "A dragged item is dropped on 'Uninstall' button in target bar")
LAUNCHER_ITEM_DROPPED_ON_UNINSTALL(468),
- @LauncherUiEvent(doc = "User completed uninstalling the package after dropping on "
+ @UiEvent(doc = "User completed uninstalling the package after dropping on "
+ "the icon onto 'Uninstall' button in the target bar")
LAUNCHER_ITEM_UNINSTALL_COMPLETED(469),
- @LauncherUiEvent(doc = "User cancelled uninstalling the package after dropping on "
+ @UiEvent(doc = "User cancelled uninstalling the package after dropping on "
+ "the icon onto 'Uninstall' button in the target bar")
LAUNCHER_ITEM_UNINSTALL_CANCELLED(470);
// ADD MORE
diff --git a/src/com/android/launcher3/logging/LauncherUiEvent.java b/src/com/android/launcher3/logging/UiEvent.java
similarity index 80%
rename from src/com/android/launcher3/logging/LauncherUiEvent.java
rename to src/com/android/launcher3/logging/UiEvent.java
index 4507ff7..20d6c72 100644
--- a/src/com/android/launcher3/logging/LauncherUiEvent.java
+++ b/src/com/android/launcher3/logging/UiEvent.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.launcher3.logging;
import static java.lang.annotation.ElementType.FIELD;
@@ -23,8 +24,11 @@
@Retention(SOURCE)
@Target(FIELD)
-public @interface LauncherUiEvent {
- /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
+// Copy of frameworks/base/core/java/com/android/internal/logging/UiEvent.java
+public @interface UiEvent {
+
+ /**
+ * An explanation, suitable for Android analysts, of the UI event that this log represents.
+ */
String doc();
}
-
diff --git a/src/com/android/launcher3/model/PredictionModel.java b/src/com/android/launcher3/model/PredictionModel.java
index f8140eb..1429843 100644
--- a/src/com/android/launcher3/model/PredictionModel.java
+++ b/src/com/android/launcher3/model/PredictionModel.java
@@ -43,7 +43,6 @@
private static final int MAX_CACHE_ITEMS = 5;
protected Context mContext;
- private ArrayList<ComponentKey> mCachedComponentKeys;
private SharedPreferences mDevicePrefs;
private UserCache mUserCache;
@@ -78,7 +77,6 @@
builder.append("\n");
}
mDevicePrefs.edit().putString(CACHED_ITEMS_KEY, builder.toString()).apply();
- mCachedComponentKeys = null;
});
}
@@ -89,17 +87,16 @@
@WorkerThread
public List<ComponentKey> getPredictionComponentKeys() {
Preconditions.assertWorkerThread();
- if (mCachedComponentKeys == null) {
- mCachedComponentKeys = new ArrayList<>();
- String cachedBlob = mDevicePrefs.getString(CACHED_ITEMS_KEY, "");
- for (String line : cachedBlob.split("\n")) {
- ComponentKey key = getComponentKeyFromSerializedString(line);
- if (key != null) {
- mCachedComponentKeys.add(key);
- }
+ ArrayList<ComponentKey> items = new ArrayList<>();
+ String cachedBlob = mDevicePrefs.getString(CACHED_ITEMS_KEY, "");
+ for (String line : cachedBlob.split("\n")) {
+ ComponentKey key = getComponentKeyFromSerializedString(line);
+ if (key != null) {
+ items.add(key);
}
+
}
- return mCachedComponentKeys;
+ return items;
}
private String serializeComponentKeyToString(ComponentKey componentKey) {
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index f2b7e54..a97d529 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
@@ -342,6 +343,11 @@
.setAllAppsContainer(
AllAppsContainer.getDefaultInstance())
.build();
+ case CONTAINER_WIDGETS_TRAY:
+ return ContainerInfo.newBuilder()
+ .setWidgetsContainer(
+ LauncherAtom.WidgetsContainer.getDefaultInstance())
+ .build();
}
return ContainerInfo.getDefaultInstance();
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 4447166..44f7db9 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -239,7 +239,7 @@
? fromState.getTransitionDuration(mActivity)
: state.getTransitionDuration(mActivity);
prepareForAtomicAnimation(fromState, state, mConfig);
- AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).getAnim();
+ AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim();
if (onCompleteRunnable != null) {
animation.addListener(AnimationSuccessListener.forRunnable(onCompleteRunnable));
}
@@ -267,7 +267,7 @@
for (StateHandler handler : mActivity.getStateManager().getStateHandlers()) {
handler.setStateWithAnimation(toState, config, builder);
}
- return builder.getAnim();
+ return builder.buildAnim();
}
/**
@@ -309,7 +309,7 @@
for (StateHandler handler : getStateHandlers()) {
handler.setStateWithAnimation(state, mConfig, builder);
}
- builder.getAnim().addListener(new AnimationSuccessListener() {
+ builder.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
@@ -325,7 +325,7 @@
onStateTransitionEnd(state);
}
});
- mConfig.setAnimation(builder.getAnim(), state);
+ mConfig.setAnimation(builder.buildAnim(), state);
return builder;
}
@@ -554,6 +554,8 @@
*/
public static class AtomicAnimationFactory<STATE_TYPE> {
+ protected static final int NEXT_INDEX = 0;
+
private final Animator[] mStateElementAnimators;
/**
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 52e2ab8..2e63ccf 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -201,7 +201,7 @@
mToState = newToState;
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS, "reinitCurrentAnimation: "
- + newToState.ordinal);
+ + newToState.ordinal + " " + getClass().getSimpleName());
}
mStartProgress = 0;
diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java
index 1ec0690..91cf835 100644
--- a/src/com/android/launcher3/util/ShortcutUtil.java
+++ b/src/com/android/launcher3/util/ShortcutUtil.java
@@ -34,7 +34,7 @@
* Returns true when we should show depp shortcuts in shortcut menu for the item.
*/
public static boolean supportsDeepShortcuts(ItemInfo info) {
- return isActive(info) && isApp(info);
+ return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_WIDGETS;
}
/**
@@ -64,7 +64,7 @@
private static boolean isActive(ItemInfo info) {
boolean isLoading = info instanceof WorkspaceItemInfo
&& ((WorkspaceItemInfo) info).hasPromiseIconUi();
- return !isLoading && !info.isDisabled() && !WidgetsModel.GO_DISABLE_WIDGETS;
+ return !isLoading && !info.isDisabled();
}
private static boolean isApp(ItemInfo info) {
diff --git a/src/com/android/launcher3/widget/PendingAddShortcutInfo.java b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
index 6e21a41..9601652 100644
--- a/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddShortcutInfo.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
+
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
@@ -32,5 +34,6 @@
componentName = activityInfo.getComponent();
user = activityInfo.getUser();
itemType = activityInfo.getItemType();
+ this.container = CONTAINER_WIDGETS_TRAY;
}
}
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index bc40484..bef9a08 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
+
import android.appwidget.AppWidgetHostView;
import android.os.Bundle;
@@ -50,6 +52,7 @@
spanY = i.spanY;
minSpanX = i.minSpanX;
minSpanY = i.minSpanY;
+ this.container = CONTAINER_WIDGETS_TRAY;
}
public WidgetAddFlowHandler getHandler() {
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index b333100..546ff0b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -362,7 +362,7 @@
public void checkForAnomaly() {
final String systemAnomalyMessage = getSystemAnomalyMessage();
if (systemAnomalyMessage != null) {
- Assert.fail(formatSystemHealthMessage(closeEvents(
+ Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
"http://go/tapl : Tests are broken by a non-Launcher system error: "
+ systemAnomalyMessage, false)));
}
@@ -424,7 +424,7 @@
return message;
}
- private String closeEvents(String message, boolean checkEvents) {
+ private String formatErrorWithEvents(String message, boolean checkEvents) {
if (sCheckingEvents) {
sCheckingEvents = false;
if (checkEvents) {
@@ -454,7 +454,7 @@
private void fail(String message) {
checkForAnomaly();
- Assert.fail(formatSystemHealthMessage(closeEvents(
+ Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
"http://go/tapl : " + getContextDescription() + message
+ " (visible state: " + getVisibleStateMessage() + ")", true)));
}
@@ -632,8 +632,6 @@
* @return the Workspace object.
*/
public Workspace pressHome() {
- mInstrumentation.getUiAutomation().setOnAccessibilityEventListener(
- e -> Log.d("b/155926212", e.toString()));
try (LauncherInstrumentation.Closable e = eventsCheck()) {
waitForLauncherInitialized();
// Click home, then wait for any accessibility event, then wait until accessibility
@@ -642,9 +640,7 @@
// otherwise waitForIdle may return immediately in case when there was a big enough
// pause in accessibility events prior to pressing Home.
final String action;
- Log.d("b/155926212", "Before isLauncherVisible()");
final boolean launcherWasVisible = isLauncherVisible();
- Log.d("b/155926212", "After isLauncherVisible(): " + launcherWasVisible);
if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
checkForAnomaly();
@@ -700,8 +696,6 @@
"performed action to switch to Home - " + action)) {
return getWorkspace();
}
- } finally {
- mInstrumentation.getUiAutomation().setOnAccessibilityEventListener(null);
}
}
@@ -1315,7 +1309,8 @@
if (mOnLauncherCrashed != null) mOnLauncherCrashed.run();
checkForAnomaly();
Assert.fail(
- formatSystemHealthMessage(closeEvents("Launcher crashed", false)));
+ formatSystemHealthMessage(
+ formatErrorWithEvents("Launcher crashed", false)));
}
if (sCheckingEvents) {
@@ -1323,6 +1318,16 @@
if (mCheckEventsForSuccessfulGestures) {
final String message = sEventChecker.verify(WAIT_TIME_MS, true);
if (message != null) {
+ try {
+ Log.e("b/156287114", "Input:");
+ for (String line : mDevice.executeShellCommand("dumpsys input").split(
+ "\\n")) {
+ Log.d("b/156287114", line);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
checkForAnomaly();
Assert.fail(formatSystemHealthMessage(
"http://go/tapl : successful gesture produced " + message));