Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6dedc222 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Handling swipe up on a third-party launcher

Bug: 78125098
Change-Id: Iba4247987825bf9ce16d3494200bfea889c931e2
parent d39b8755
Loading
Loading
Loading
Loading
+76 −70
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.view.View;
@@ -40,15 +39,16 @@ import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;

import java.util.function.BiPredicate;
import java.util.function.Consumer;

/**
 * Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
@@ -67,19 +67,14 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {

    void executeOnWindowAvailable(T activity, Runnable action);

    void executeOnNextDraw(T activity, TaskView targetView, Runnable action);

    void onTransitionCancelled(T activity, boolean activityVisible);

    int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);

    void onSwipeUpComplete(T activity);

    void prepareRecentsUI(T activity, boolean activityVisible);

    AnimatorPlaybackController createControllerForVisibleActivity(T activity);

    AnimatorPlaybackController createControllerForHiddenActivity(T activity, int transitionLength);
    AnimationFactory prepareRecentsUI(T activity, boolean activityVisible,
            Consumer<AnimatorPlaybackController> callback);

    ActivityInitListener createActivityInitListener(BiPredicate<T, Boolean> onInitListener);

@@ -130,20 +125,6 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
            }
        }

        @Override
        public void executeOnNextDraw(Launcher activity, TaskView targetView, Runnable action) {
            ViewOnDrawExecutor executor = new ViewOnDrawExecutor() {
                @Override
                public void onViewDetachedFromWindow(View v) {
                    if (!isCompleted()) {
                        runAllTasks();
                    }
                }
            };
            executor.attachTo(activity, targetView, false /* waitForLoadAnimation */);
            executor.execute(action);
        }

        @Override
        public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
            LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
@@ -169,7 +150,8 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
        }

        @Override
        public void prepareRecentsUI(Launcher activity, boolean activityVisible) {
        public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible,
                Consumer<AnimatorPlaybackController> callback) {
            LauncherState startState = activity.getStateManager().getState();
            if (startState.disableRestore) {
                startState = activity.getStateManager().getRestState();
@@ -185,23 +167,28 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
                // Optimization, hide the all apps view to prevent layout while initializing
                activity.getAppsView().getContentView().setVisibility(View.GONE);
            }

            return (transitionLength) ->
                    createActivityController(activity, activityVisible, transitionLength, callback);
        }

        @Override
        public AnimatorPlaybackController createControllerForVisibleActivity(Launcher activity) {
        private void createActivityController(Launcher activity, boolean wasVisible,
                long transitionLength, Consumer<AnimatorPlaybackController> callback) {
            if (wasVisible) {
                DeviceProfile dp = activity.getDeviceProfile();
                long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx);
            return activity.getStateManager().createAnimationToNewWorkspace(OVERVIEW, accuracy);
                callback.accept(activity.getStateManager()
                        .createAnimationToNewWorkspace(OVERVIEW, accuracy));
                return;
            }

            if (activity.getDeviceProfile().isVerticalBarLayout()) {
                return;
            }

        @Override
        public AnimatorPlaybackController createControllerForHiddenActivity(
                Launcher activity, int transitionLength) {
            AllAppsTransitionController controller = activity.getAllAppsController();
            AnimatorSet anim = new AnimatorSet();
            if (activity.getDeviceProfile().isVerticalBarLayout()) {
                // TODO:
            } else {

            float scrollRange = Math.max(controller.getShiftRange(), 1);
            float progressDelta = (transitionLength / scrollRange);

@@ -211,11 +198,10 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
                    controller, ALL_APPS_PROGRESS, startProgress, endProgress);
            shiftAnim.setInterpolator(LINEAR);
            anim.play(shiftAnim);
            }

            anim.setDuration(transitionLength * 2);
            activity.getStateManager().setCurrentAnimation(anim);
            return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
            callback.accept(AnimatorPlaybackController.wrap(anim, transitionLength * 2));
        }

        @Override
@@ -294,13 +280,6 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
            action.run();
        }

        @Override
        public void executeOnNextDraw(RecentsActivity activity, TaskView targetView,
                Runnable action) {
            // TODO:
            new Handler(Looper.getMainLooper()).post(action);
        }

        @Override
        public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) {
            // TODO:
@@ -324,23 +303,43 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
        }

        @Override
        public void prepareRecentsUI(RecentsActivity activity, boolean activityVisible) {
            // TODO:
        public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
                Consumer<AnimatorPlaybackController> callback) {
            if (activityVisible) {
                return (transitionLength) -> { };
            }

            RecentsViewContainer rv = activity.getOverviewPanelContainer();
            rv.setContentAlpha(0);

            return new AnimationFactory() {

                boolean isAnimatingHome = false;

                @Override
        public AnimatorPlaybackController createControllerForVisibleActivity(
                RecentsActivity activity) {
            DeviceProfile dp = activity.getDeviceProfile();
            return createControllerForHiddenActivity(activity, Math.max(dp.widthPx, dp.heightPx));
                public void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) {
                    isAnimatingHome = targets != null && targets.isAnimatingHome();
                    if (!isAnimatingHome) {
                        rv.setContentAlpha(1);
                    }
                    createActivityController(getSwipeUpDestinationAndLength(
                            activity.getDeviceProfile(), activity, new Rect()));
                }

                @Override
        public AnimatorPlaybackController createControllerForHiddenActivity(
                RecentsActivity activity, int transitionLength) {
            // We do not animate anything. Create a empty controller
            AnimatorSet anim = new AnimatorSet();
            return AnimatorPlaybackController.wrap(anim, transitionLength * 2);
                public void createActivityController(long transitionLength) {
                    if (!isAnimatingHome) {
                        return;
                    }

                    ObjectAnimator anim = ObjectAnimator
                            .ofFloat(rv, RecentsViewContainer.CONTENT_ALPHA, 0, 1);
                    anim.setDuration(transitionLength).setInterpolator(LINEAR);
                    AnimatorSet animatorSet = new AnimatorSet();
                    animatorSet.play(anim);
                    callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength));
                }
            };
        }

        @Override
@@ -423,4 +422,11 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
        void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider,
                Context context, Handler handler, long duration);
    }

    interface AnimationFactory {

        default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { }

        void createActivityController(long transitionLength);
    }
}
+30 −9
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static com.android.systemui.shared.system.PackageManagerWrapper
        .ACTION_PREFERRED_ACTIVITY_CHANGED;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;

import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
@@ -36,6 +37,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
import android.os.Build;
import android.os.PatternMatcher;
@@ -49,6 +51,7 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper;
import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -59,6 +62,7 @@ import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;

import java.util.ArrayList;

@@ -254,15 +258,17 @@ public class OverviewCommandHelper {
        private boolean onActivityReady(T activity, Boolean wasVisible) {
            activity.<RecentsView>getOverviewPanel().setCurrentTask(mRunningTaskId);
            AbstractFloatingView.closeAllOpenViews(activity, wasVisible);
            mHelper.prepareRecentsUI(activity, wasVisible);
            if (wasVisible) {
                AnimatorPlaybackController controller =
                        mHelper.createControllerForVisibleActivity(activity);
            AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible,
                    (controller) -> {
                        controller.dispatchOnStart();
                ValueAnimator anim =
                        controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
                        ValueAnimator anim = controller.getAnimationPlayer()
                                .setDuration(RECENTS_LAUNCH_DURATION);
                        anim.setInterpolator(FAST_OUT_SLOW_IN);
                        anim.start();
                });
            factory.onRemoteAnimationReceived(null);
            if (wasVisible) {
                factory.createActivityController(RECENTS_LAUNCH_DURATION);
            }
            mActivity = activity;
            return false;
@@ -283,7 +289,6 @@ public class OverviewCommandHelper {
            RemoteAnimationTargetSet targetSet =
                    new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING);


            // Use the top closing app to determine the insets for the animation
            RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId);
            if (runningTaskTarget == null) {
@@ -313,6 +318,22 @@ public class OverviewCommandHelper {
            valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            valueAnimator.addUpdateListener((v) ->
                clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue()));

            if (targetSet.isAnimatingHome()) {
                // If we are animating home, fade in the opening targets
                RemoteAnimationTargetSet openingSet =
                        new RemoteAnimationTargetSet(targetCompats, MODE_OPENING);

                TransactionCompat transaction = new TransactionCompat();
                valueAnimator.addUpdateListener((v) -> {
                    for (RemoteAnimationTargetCompat app : openingSet.apps) {
                        transaction.setAlpha(app.leash, (float) v.getAnimatedValue());
                        transaction.show(app.leash);
                    }
                    transaction.setEarlyWakeup();
                    transaction.apply();
                });
            }
            anim.play(valueAnimator);
            return anim;
        }
+10 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.fallback.RecentsRootView;
import com.android.quickstep.views.RecentsViewContainer;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
@@ -65,6 +66,7 @@ public class RecentsActivity extends BaseDraggingActivity {
    private Handler mUiHandler = new Handler(Looper.getMainLooper());
    private RecentsRootView mRecentsRootView;
    private FallbackRecentsView mFallbackRecentsView;
    private RecentsViewContainer mOverviewPanelContainer;

    private Configuration mOldConfig;

@@ -78,6 +80,7 @@ public class RecentsActivity extends BaseDraggingActivity {
        setContentView(R.layout.fallback_recents_activity);
        mRecentsRootView = findViewById(R.id.drag_layer);
        mFallbackRecentsView = findViewById(R.id.overview_panel);
        mOverviewPanelContainer = findViewById(R.id.overview_panel_container);

        mRecentsRootView.setup();

@@ -153,6 +156,10 @@ public class RecentsActivity extends BaseDraggingActivity {
        return (T) mFallbackRecentsView;
    }

    public RecentsViewContainer getOverviewPanelContainer() {
        return mOverviewPanelContainer;
    }

    @Override
    public BadgeInfo getBadgeInfoForItem(ItemInfo info) {
        return null;
@@ -210,6 +217,9 @@ public class RecentsActivity extends BaseDraggingActivity {

    @Override
    protected void onStart() {
        // Set the alpha to 1 before calling super, as it may get set back to 0 due to
        // onActivityStart callback.
        mFallbackRecentsView.setContentAlpha(1);
        super.onStart();
        UiFactory.onStart(this);
        mFallbackRecentsView.resetTaskVisuals();
+19 −21
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ 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.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.LayoutListener;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper;
@@ -164,6 +165,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
    private LayoutListener mLayoutListener;
    private RecentsView mRecentsView;
    private QuickScrubController mQuickScrubController;
    private AnimationFactory mAnimationFactory = (t) -> { };

    private Runnable mLauncherDrawnCallback;

@@ -212,11 +214,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
                this::launcherFrameDrawn);
        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
                this::onGestureStartedWithLauncher);
                this::notifyGestureStartedAsync);
        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
                        | STATE_GESTURE_CANCELLED,
                this::resetStateForAnimationCancel);

        mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
                this::sendRemoteAnimationsToAnimationFactory);
        mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
                        | STATE_SCALED_CONTROLLER_APP,
                this::resumeLastTask);
@@ -321,7 +325,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
            return;
        }

        mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible);
        mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity,
                mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated);
        AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible);

        if (mWasLauncherAlreadyVisible) {
@@ -377,9 +382,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
        mLauncherFrameDrawnTime = SystemClock.uptimeMillis();
    }

    private void sendRemoteAnimationsToAnimationFactory() {
        mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationWrapper.targetSet);
    }

    private void initializeLauncherAnimationController() {
        mLayoutListener.setHandler(this);
        onLauncherLayoutChanged();
        buildAnimationController();

        final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs;
        SysuiEventLogger.writeDummyRecentsTransition(transitionDelay);
@@ -418,16 +427,16 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
    /**
     * Called by {@link #mLayoutListener} when launcher layout changes
     */
    public void onLauncherLayoutChanged() {
    public void buildAnimationController() {
        initTransitionEndpoints(mActivity.getDeviceProfile());
        mAnimationFactory.createActivityController(mTransitionDragLength);
    }

        if (!mWasLauncherAlreadyVisible) {
            mLauncherTransitionController = mActivityControlHelper
                    .createControllerForHiddenActivity(mActivity, mTransitionDragLength);
    private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
        mLauncherTransitionController = anim;
        mLauncherTransitionController.dispatchOnStart();
        mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
    }
    }

    @WorkerThread
    private void updateFinalShift() {
@@ -546,17 +555,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> {
        }
    }

    private void onGestureStartedWithLauncher() {
        notifyGestureStartedAsync();

        if (mWasLauncherAlreadyVisible) {
            mLauncherTransitionController = mActivityControlHelper
                    .createControllerForVisibleActivity(mActivity);
            mLauncherTransitionController.dispatchOnStart();
            mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
        }
    }

    @WorkerThread
    public void onGestureEnded(float endVelocity) {
        Resources res = mContext.getResources();
+9 −7
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
@@ -111,14 +110,17 @@ public class ClipAnimationHelper {
        mClipRect.bottom = (int)
                (mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress));

        mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);

        TransactionCompat transaction = new TransactionCompat();
        for (RemoteAnimationTargetCompat app : targetSet.apps) {
            if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
                mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL);
                mTmpMatrix.postTranslate(app.position.x, app.position.y);
                transaction.setMatrix(app.leash, mTmpMatrix)
                        .setWindowCrop(app.leash, mClipRect);
            if (app.isNotInRecents) {
            }

            if (app.isNotInRecents
                    || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
                transaction.setAlpha(app.leash, 1 - progress);
            }
            transaction.show(app.leash);
Loading