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

Commit 38157058 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Make recents animation work with fallback activity." into ub-launcher3-master

parents 81839b86 bc5bfc11
Loading
Loading
Loading
Loading
+35 −4
Original line number Diff line number Diff line
@@ -106,6 +106,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
    private DeviceProfile mDeviceProfile;
    private View mFloatingView;

    private RemoteAnimationRunnerCompat mRemoteAnimationOverride;

    private final AnimatorListenerAdapter mReapplyStateListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
@@ -175,6 +177,10 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
        return getDefaultActivityLaunchOptions(launcher, v);
    }

    public void setRemoteAnimationOverride(RemoteAnimationRunnerCompat remoteAnimationOverride) {
        mRemoteAnimationOverride = remoteAnimationOverride;
    }

    /**
     * Try to find a TaskView that corresponds with the component of the launched view.
     *
@@ -635,6 +641,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
     * Registers remote animations used when closing apps to home screen.
     */
    private void registerRemoteAnimations() {
        // Unregister this
        if (hasControlRemoteAppTransitionPermission()) {
            try {
                RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
@@ -669,12 +676,36 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag
    private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
        return new LauncherAnimationRunner(mHandler) {
            @Override
            public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
                if (mLauncher.getStateManager().getState().overviewUi) {
                    // We use a separate transition for Overview mode.
                    return null;
            public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats,
                    Runnable runnable) {
                if (mLauncher.getStateManager().getState().overviewUi
                        && mRemoteAnimationOverride != null) {
                    // This transition is only used for the fallback activity and should not be
                    // managed here (but necessary to implement here since the defined remote
                    // animation currently takes precendence over the one defined in the activity
                    // options).
                    mRemoteAnimationOverride.onAnimationStart(targetCompats, runnable);
                    return;
                }
                super.onAnimationStart(targetCompats, runnable);
            }

            @Override
            public void onAnimationCancelled() {
                if (mLauncher.getStateManager().getState().overviewUi
                        && mRemoteAnimationOverride != null) {
                    // This transition is only used for the fallback activity and should not be
                    // managed here (but necessary to implement here since the defined remote
                    // animation currently takes precendence over the one defined in the activity
                    // options).
                    mRemoteAnimationOverride.onAnimationCancelled();
                    return;
                }
                super.onAnimationCancelled();
            }

            @Override
            public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) {
                AnimatorSet anim = new AnimatorSet();
                anim.play(getClosingWindowAnimators(targetCompats));

+50 −11
Original line number Diff line number Diff line
@@ -36,8 +36,10 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppTransitionManagerImpl;
import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.ViewOnDrawExecutor;
@@ -80,7 +82,10 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {

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

    void startRecents(Context context, Intent intent, AssistDataReceiver assistDataReceiver,
    void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
            final RecentsAnimationListener remoteAnimationListener);

    void startRecentsFromButton(Context context, Intent intent,
            RecentsAnimationListener remoteAnimationListener);

    @UiThread
@@ -203,21 +208,44 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
        }

        @Override
        public void startRecents(Context context, Intent intent,
                AssistDataReceiver assistDataReceiver,
                RecentsAnimationListener remoteAnimationListener) {
        public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
                final RecentsAnimationListener remoteAnimationListener) {
            ActivityManagerWrapper.getInstance().startRecentsActivity(
                    intent, assistDataReceiver, remoteAnimationListener, null, null);
        }

        @Override
        public void startRecentsFromButton(Context context, Intent intent,
                RecentsAnimationListener remoteAnimationListener) {
            // We should use the remove animation for the fallback activity recents button case,
            // it works better with PiP.  In Launcher, we have already registered the remote
            // animation definition, which takes priority over explicitly defined remote
            // animations in the provided activity options when starting the activity, so we
            // just register a remote animation factory to get a callback to handle this.
            LauncherAppTransitionManagerImpl appTransitionManager =
                    (LauncherAppTransitionManagerImpl) getLauncher().getAppTransitionManager();
            appTransitionManager.setRemoteAnimationOverride(new RecentsAnimationActivityOptions(
                    remoteAnimationListener, () -> {
                        // Once the controller is finished, also reset the remote animation override
                        appTransitionManager.setRemoteAnimationOverride(null);
                    }));
            context.startActivity(intent);
        }

        @Nullable
        @UiThread
        private Launcher getVisibleLaucher() {
        private Launcher getLauncher() {
            LauncherAppState app = LauncherAppState.getInstanceNoCreate();
            if (app == null) {
                return null;
            }
            Launcher launcher = (Launcher) app.getModel().getCallback();
            return (Launcher) app.getModel().getCallback();
        }

        @Nullable
        @UiThread
        private Launcher getVisibleLaucher() {
            Launcher launcher = getLauncher();
            return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus() ?
                    launcher : null;
        }
@@ -325,12 +353,23 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
        }

        @Override
        public void startRecents(Context context, Intent intent,
                AssistDataReceiver assistDataReceiver,
        public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver,
                final RecentsAnimationListener remoteAnimationListener) {
            ActivityOptions options =
                    ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat(
                            new FallbackActivityOptions(remoteAnimationListener), 10000, 10000));
            // We can use the normal recents animation for swipe up
            ActivityManagerWrapper.getInstance().startRecentsActivity(
                    intent, assistDataReceiver, remoteAnimationListener, null, null);
        }

        @Override
        public void startRecentsFromButton(Context context, Intent intent,
                RecentsAnimationListener remoteAnimationListener) {
            // We should use the remove animation for the fallback activity recents button case,
            // it works better with PiP. For the fallback activity, we should not have registered
            // the launcher app transition manager, so we should just start the remote animation here.
            ActivityOptions options = ActivityOptionsCompat.makeRemoteAnimation(
                    new RemoteAnimationAdapterCompat(
                            new RecentsAnimationActivityOptions(remoteAnimationListener, null),
                            10000, 10000));
            context.startActivity(intent, options.toBundle());
        }

+1 −1
Original line number Diff line number Diff line
@@ -218,7 +218,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
        handler.initWhenReady();

        TraceHelper.beginSection("RecentsController");
        Runnable startActivity = () -> mActivityControlHelper.startRecents(this, mHomeIntent,
        Runnable startActivity = () -> mActivityControlHelper.startRecentsFromSwipe(mHomeIntent,
                new AssistDataReceiver() {
                    @Override
                    public void onHandleAssistData(Bundle bundle) {
+33 −36
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHel
import com.android.quickstep.util.SysuiEventLogger;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
import com.android.systemui.shared.recents.view.RecentsTransition;
@@ -77,7 +78,7 @@ public class OverviewCommandHelper extends InternalStateHandler {
    private static final int RID_CANCEL_CONTROLLER = 1;
    private static final int RID_CANCEL_ZOOM_OUT_ANIMATION = 2;

    private static final long RECENTS_LAUNCH_DURATION = 150;
    private static final long RECENTS_LAUNCH_DURATION = 200;

    private static final String TAG = "OverviewCommandHelper";
    private static final boolean DEBUG_START_FALLBACK_ACTIVITY = false;
@@ -151,12 +152,13 @@ public class OverviewCommandHelper extends InternalStateHandler {
    private void initSwipeHandler(ActivityControlHelper helper, long time,
            Consumer<WindowTransformSwipeHandler> onAnimationInitCallback) {
        final int commandId = mCurrentCommandId;
        RunningTaskInfo taskInfo = ActivityManagerWrapper.getInstance().getRunningTask();
        final RunningTaskInfo runningTask = ActivityManagerWrapper.getInstance().getRunningTask();
        final int runningTaskId = runningTask.id;
        final WindowTransformSwipeHandler handler =
                new WindowTransformSwipeHandler(taskInfo, mContext, time, helper);
                new WindowTransformSwipeHandler(runningTask, mContext, time, helper);

        // Preload the plan
        mRecentsModel.loadTasks(taskInfo.id, null);
        mRecentsModel.loadTasks(runningTaskId, null);
        mWindowTransformSwipeHandler = handler;

        mTempTaskTargetRect.setEmpty();
@@ -172,13 +174,8 @@ public class OverviewCommandHelper extends InternalStateHandler {
        addFinishCommand(commandId, RID_RESET_SWIPE_HANDLER, handler::reset);

        TraceHelper.beginSection(TAG);
        Runnable startActivity = () -> helper.startRecents(mContext, homeIntent,
                new AssistDataReceiver() {
                    @Override
                    public void onHandleAssistData(Bundle bundle) {
                        mRecentsModel.preloadAssistData(taskInfo.id, bundle);
                    }
                },
        Runnable startActivity = () -> helper.startRecentsFromButton(mContext,
                addToIntent(homeIntent),
                new RecentsAnimationListener() {
                    public void onAnimationStart(
                            RecentsAnimationControllerCompat controller,
@@ -190,11 +187,17 @@ public class OverviewCommandHelper extends InternalStateHandler {
                                    minimizedHomeBounds);
                            mTempTaskTargetRect.set(handler.getTargetRect(mWindowSize));

                            ThumbnailData thumbnail = mAM.getTaskThumbnail(runningTaskId,
                                    true /* reducedResolution */);
                            mMainThreadExecutor.execute(() -> {
                                addFinishCommand(commandId,
                                        RID_CANCEL_CONTROLLER, () -> controller.finish(true));
                                if (commandId == mCurrentCommandId) {
                                    onAnimationInitCallback.accept(handler);

                                    // The animation has started, which means the other activity
                                    // should be paused, lets update the thumbnail
                                    handler.switchToScreenshotImmediate(thumbnail);
                                }
                            });
                        } else {
@@ -230,7 +233,7 @@ public class OverviewCommandHelper extends InternalStateHandler {
        });
        handler.onGestureStarted();
        anim.setDuration(RECENTS_LAUNCH_DURATION);
        anim.setInterpolator(Interpolators.AGGRESSIVE_EASE);
        anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        anim.start();
        addFinishCommand(commandId, RID_CANCEL_ZOOM_OUT_ANIMATION, anim::cancel);
    }
@@ -241,6 +244,7 @@ public class OverviewCommandHelper extends InternalStateHandler {
            return;
        }

        ActivityManagerWrapper.getInstance().closeSystemWindows("recentapps");
        long time = SystemClock.elapsedRealtime();
        mMainThreadExecutor.execute(() -> {
            long elapsedTime = time - mLastToggleTime;
@@ -248,40 +252,37 @@ public class OverviewCommandHelper extends InternalStateHandler {

            mCurrentCommandId++;
            mTempTaskTargetRect.round(mTaskTargetRect);
            boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
            int runnableCount = mCurrentCommandFinishRunnables.size();
            if (runnableCount > 0) {
                for (int i = 0; i < runnableCount; i++) {
                    mCurrentCommandFinishRunnables.valueAt(i).run();
                }
                mCurrentCommandFinishRunnables.clear();
                isQuickTap = true;
            }

            // TODO: We need to fix this case with PIP, when an activity first enters PIP, it shows
            //       the menu activity which takes window focus, prevening the right condition from
            //       being run below
            ActivityControlHelper helper = getActivityControlHelper();
            RecentsView recents = helper.getVisibleRecentsView();
            if (recents != null) {
                int childCount = recents.getChildCount();
                if (childCount != 0) {
                    ((TaskView) recents.getChildAt(childCount >= 2 ? 1 : 0)).launchTask(true);
                }

                // There are not enough tasks. Skip
                // Launch the next task
                recents.showNextTask();
            } else {
                if (elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
                    // The user tried to launch back into overview too quickly, either after
                    // launching an app, or before overview has actually shown, just ignore for now
                    return;
                }

            if (isQuickTap) {
                // Focus last task. Start is on background thread so that all ActivityManager calls
                // are serialized
                BackgroundExecutor.get().submit(this::startLastTask);
                return;
            }
                // Start overview
                if (helper.switchToRecentsIfVisible()) {
                    SysuiEventLogger.writeDummyRecentsTransition(0);
                return;
            }

                    // Do nothing
                } else {
                    initSwipeHandler(helper, time, this::startZoomOutAnim);
                }
            }
        });
    }

@@ -362,10 +363,6 @@ public class OverviewCommandHelper extends InternalStateHandler {
        return false;
    }

    public boolean isUsingFallbackActivity() {
        return DEBUG_START_FALLBACK_ACTIVITY;
    }

    public ActivityControlHelper getActivityControlHelper() {
        if (DEBUG_START_FALLBACK_ACTIVITY) {
            return new FallbackActivityControllerHelper();
+20 −11
Original line number Diff line number Diff line
@@ -24,24 +24,33 @@ import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.function.Consumer;

/**
 * Temporary class to create activity options to emulate recents transition for fallback activtiy.
 * Class to create activity options to emulate recents transition.
 */
public class FallbackActivityOptions implements RemoteAnimationRunnerCompat {
public class RecentsAnimationActivityOptions implements RemoteAnimationRunnerCompat {

    private final RecentsAnimationListener mListener;
    private final Runnable mFinishCallback;

    public FallbackActivityOptions(RecentsAnimationListener listener) {
    public RecentsAnimationActivityOptions(RecentsAnimationListener listener,
            Runnable finishCallback) {
        mListener = listener;
        mFinishCallback = finishCallback;
    }

    @Override
    public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats,
            Runnable runnable) {
        showOpeningTarget(targetCompats);
        DummyRecentsAnimationControllerCompat dummyRecentsAnim =
                new DummyRecentsAnimationControllerCompat(runnable);
        RemoteRecentsAnimationControllerCompat dummyRecentsAnim =
                new RemoteRecentsAnimationControllerCompat(() -> {
                    runnable.run();
                    if (mFinishCallback != null) {
                        mFinishCallback.run();
                    }
                });

        Rect insets = new Rect();
        WindowManagerWrapper.getInstance().getStableInsets(insets);
@@ -54,23 +63,22 @@ public class FallbackActivityOptions implements RemoteAnimationRunnerCompat {
    }

    private void showOpeningTarget(RemoteAnimationTargetCompat[] targetCompats) {
        for (RemoteAnimationTargetCompat target : targetCompats) {
        TransactionCompat t = new TransactionCompat();
        for (RemoteAnimationTargetCompat target : targetCompats) {
            int layer = target.mode == RemoteAnimationTargetCompat.MODE_CLOSING
                    ? Integer.MAX_VALUE
                    : target.prefixOrderIndex;
            t.setLayer(target.leash, layer);
            t.show(target.leash);
            t.apply();
        }
        t.apply();
    }

    private static class DummyRecentsAnimationControllerCompat
            extends RecentsAnimationControllerCompat {
    private class RemoteRecentsAnimationControllerCompat extends RecentsAnimationControllerCompat {

        final Runnable mFinishCallback;

        public DummyRecentsAnimationControllerCompat(Runnable finishCallback) {
        public RemoteRecentsAnimationControllerCompat(Runnable finishCallback) {
            mFinishCallback = finishCallback;
        }

@@ -87,7 +95,8 @@ public class FallbackActivityOptions implements RemoteAnimationRunnerCompat {

        @Override
        public void finish(boolean toHome) {
            if (toHome) {
            // This should never be called with toHome == false
            if (mFinishCallback != null) {
                mFinishCallback.run();
            }
        }
Loading