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

Commit c57b7f6e authored by Matthew Ng's avatar Matthew Ng
Browse files

Fixes quick switch animations for low end devices

Currently using quick switch is fine but sometimes with animation
glitches but very reproducible if tapping recents button very fast. The
problem is that low end device Recents entrance animation also has the
previous tasks animating downward causing more chances of animation
instability.

The problem is that transition is not finished and it is already
starting to do the next toggled animation. When the transition from
app to recents (RecentsImpl.toggleRecents) starts without finishing
RecentsActivity.onStop, the previous frame will be visible for a couple
of frames before the entrance animation starts (having the previous task
animate down). Therefore restrict toggling to after
RecentsActivity.onStop would allow the previous frame to finish and the
transitions run normally.

Bug: 62251652
Fixes: 64401391
Test: manual - using gobo device, launch multiple apps, rapidly tap recents
button
Change-Id: I4e70434bca3c9bec287fa30559b23a1e71b5ef20
parent ed0c5cf4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
+11 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.view.View.MeasureSpec;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.ActivityOptions.OnAnimationFinishedListener;
import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -663,7 +664,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener

        mWaitingForTransitionStart = waitingForTransitionStart;
        if (!waitingForTransitionStart && mToggleFollowingTransitionStart) {
            toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET);
            mHandler.post(() -> toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET));
        }
        mToggleFollowingTransitionStart = false;
    }
@@ -866,6 +867,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
    private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
            getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
                    Rect windowOverrideRect) {
        final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
        if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
            ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
            ArrayList<Task> tasks;
@@ -896,8 +898,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
            AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
            specs.toArray(specsArray);

            // For low end ram devices, wait for transition flag is reset when Recents entrance
            // animation is complete instead of when the transition animation starts
            return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
                    specsArray, mHandler, mResetToggleFlagListener, this), null);
                    specsArray, mHandler, isLowRamDevice ? null : mResetToggleFlagListener, this),
                    null);
        } else {
            // Update the destination rect
            Task toTask = new Task();
@@ -916,9 +921,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                                toTask.key.id, thumbnail, rect));
                    });

            // For low end ram devices, wait for transition flag is reset when Recents entrance
            // animation is complete instead of when the transition animation starts
            return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
                    mHandler, future.getFuture(), mResetToggleFlagListener, false /* scaleUp */),
                    future);
                    mHandler, future.getFuture(), isLowRamDevice ? null : mResetToggleFlagListener,
                    false /* scaleUp */), future);
        }
    }

+8 −4
Original line number Diff line number Diff line
@@ -140,9 +140,11 @@ public class RecentsTransitionHelper {
                        mHandler.postDelayed(mStartScreenPinningRunnable, 350);
                    }

                    if (!Recents.getConfiguration().isLowRamDevice) {
                        // Reset the state where we are waiting for the transition to start
                        EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
                    }
                }
            };
        } else {
            // This is only the case if the task is not on screen (scrolled offscreen for example)
@@ -163,9 +165,11 @@ public class RecentsTransitionHelper {
                    EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
                    stackView.cancelAllTaskViewAnimations();

                    if (!Recents.getConfiguration().isLowRamDevice) {
                        // Reset the state where we are waiting for the transition to start
                        EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
                    }
                }
            };
        }

+11 −1
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -241,6 +243,7 @@ public class TaskStackAnimationHelper {
            return;
        }

        final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
        int taskViewEnterFromAppDuration = res.getInteger(
                R.integer.recents_task_enter_from_app_duration);
        int taskViewEnterFromAffiliatedAppDuration = res.getInteger(
@@ -248,6 +251,13 @@ public class TaskStackAnimationHelper {
        int dockGestureAnimDuration = appRes.getInteger(
                R.integer.long_press_dock_anim_duration);

        // Since low ram devices have an animation when entering app -> recents, do not allow
        // toggle until the animation is complete
        if (launchState.launchedFromApp && !launchState.launchedViaDockGesture && isLowRamDevice) {
            postAnimationTrigger.addLastDecrementRunnable(() -> EventBus.getDefault()
                .send(new SetWaitingForTransitionStartEvent(false)));
        }

        // Create enter animations for each of the views from front to back
        List<TaskView> taskViews = mStackView.getTaskViews();
        int taskViewCount = taskViews.size();
@@ -296,7 +306,7 @@ public class TaskStackAnimationHelper {
                AnimationProps taskAnimation = new AnimationProps()
                        .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
                        .setListener(postAnimationTrigger.decrementOnAnimationEnd());
                if (Recents.getConfiguration().isLowRamDevice) {
                if (isLowRamDevice) {
                    taskAnimation.setInterpolator(AnimationProps.BOUNDS,
                            Interpolators.FAST_OUT_SLOW_IN)
                            .setDuration(AnimationProps.BOUNDS, 150)