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

Commit 045814a2 authored by Tony Wickham's avatar Tony Wickham Committed by Android Build Coastguard Worker
Browse files

Don't invalidate swipe handler until parallel anim finishes

- When invalidateHandler() is called, it calls endRunningWindowAnim()
  which includes mParallelRunningAnim. This causes a jump if
  mParallelRunningAnim was not already finished, so we now wait to
  invalidate the handler after mParallelRunningAnim ends.

Flag: EXEMPT bugfix
Test: AbsSwipeUpHandlerTestCase (added two tests for this)
Fixes: 370208192
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:ee98cd4bdf739c2f93f7cf0a20764acb2a837b0c)
Merged-In: I37ed281a993b1d2fa3634754378314511f3295f0
Change-Id: I37ed281a993b1d2fa3634754378314511f3295f0
parent 2b71139a
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -238,6 +238,8 @@ public abstract class AbsSwipeUpHandler<
            getNextStateFlag("STATE_SCALED_CONTROLLER_HOME");
    private static final int STATE_SCALED_CONTROLLER_RECENTS =
            getNextStateFlag("STATE_SCALED_CONTROLLER_RECENTS");
    private static final int STATE_PARALLEL_ANIM_FINISHED =
            getNextStateFlag("STATE_PARALLEL_ANIM_FINISHED");

    protected static final int STATE_HANDLER_INVALIDATED =
            getNextStateFlag("STATE_HANDLER_INVALIDATED");
@@ -450,7 +452,8 @@ public abstract class AbsSwipeUpHandler<
        mStateCallback.runOnceAtState(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED
                        | STATE_SCALED_CONTROLLER_HOME,
                this::finishCurrentTransitionToHome);
        mStateCallback.runOnceAtState(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED,
        mStateCallback.runOnceAtState(STATE_SCALED_CONTROLLER_HOME | STATE_CURRENT_TASK_FINISHED
                        | STATE_PARALLEL_ANIM_FINISHED,
                this::reset);

        mStateCallback.runOnceAtState(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
@@ -1548,9 +1551,12 @@ public abstract class AbsSwipeUpHandler<
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mParallelRunningAnim = null;
                        mStateCallback.setStateOnUiThread(STATE_PARALLEL_ANIM_FINISHED);
                    }
                });
                mParallelRunningAnim.start();
            } else {
                mStateCallback.setStateOnUiThread(STATE_PARALLEL_ANIM_FINISHED);
            }
        }

+58 −2
Original line number Diff line number Diff line
@@ -16,15 +16,23 @@

package com.android.quickstep;

import static com.android.quickstep.AbsSwipeUpHandler.STATE_HANDLER_INVALIDATED;

import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -54,6 +62,7 @@ import com.android.systemui.shared.system.InputConsumerController;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@@ -207,7 +216,7 @@ public abstract class AbsSwipeUpHandlerTestCase<

        runOnMainSync(() -> {
            absSwipeUpHandler.startNewTask(unused -> {});
            verify(mRecentsAnimationController).finish(anyBoolean(), any());
            verifyRecentsAnimationFinishedAndCallCallback();
        });
    }

@@ -217,10 +226,57 @@ public abstract class AbsSwipeUpHandlerTestCase<

        runOnMainSync(() -> {
            verify(mRecentsAnimationController).detachNavigationBarFromApp(true);
            verify(mRecentsAnimationController).finish(anyBoolean(), any(), anyBoolean());
            verifyRecentsAnimationFinishedAndCallCallback();
        });
    }

    @Test
    public void testHomeGesture_invalidatesHandlerAfterParallelAnim() {
        ValueAnimator parallelAnim = new ValueAnimator();
        parallelAnim.setRepeatCount(ValueAnimator.INFINITE);
        when(mActivityInterface.getParallelAnimationToLauncher(any(), anyLong(), any()))
                .thenReturn(parallelAnim);
        SWIPE_HANDLER handler = createSwipeUpHandlerForGesture(GestureState.GestureEndTarget.HOME);
        runOnMainSync(() -> {
            parallelAnim.start();
            verifyRecentsAnimationFinishedAndCallCallback();
            assertFalse(handler.mStateCallback.hasStates(STATE_HANDLER_INVALIDATED));
            parallelAnim.end();
            assertTrue(handler.mStateCallback.hasStates(STATE_HANDLER_INVALIDATED));
        });
    }

    @Test
    public void testHomeGesture_invalidatesHandlerIfNoParallelAnim() {
        when(mActivityInterface.getParallelAnimationToLauncher(any(), anyLong(), any()))
                .thenReturn(null);
        SWIPE_HANDLER handler = createSwipeUpHandlerForGesture(GestureState.GestureEndTarget.HOME);
        runOnMainSync(() -> {
            verifyRecentsAnimationFinishedAndCallCallback();
            assertTrue(handler.mStateCallback.hasStates(STATE_HANDLER_INVALIDATED));
        });
    }

    /**
     * Verifies that RecentsAnimationController#finish() is called, and captures and runs any
     * callback that was passed to it. This ensures that STATE_CURRENT_TASK_FINISHED is correctly
     * set for example.
     */
    private void verifyRecentsAnimationFinishedAndCallCallback() {
        ArgumentCaptor<Runnable> finishCallback = ArgumentCaptor.forClass(Runnable.class);
        // Check if the 2 parameter method is called.
        verify(mRecentsAnimationController, atLeast(0)).finish(
                anyBoolean(), finishCallback.capture());
        if (finishCallback.getAllValues().isEmpty()) {
            // Check if the 3 parameter method is called.
            verify(mRecentsAnimationController).finish(
                    anyBoolean(), finishCallback.capture(), anyBoolean());
        }
        if (finishCallback.getValue() != null) {
            finishCallback.getValue().run();
        }
    }

    private SWIPE_HANDLER createSwipeUpHandlerForGesture(GestureState.GestureEndTarget endTarget) {
        boolean isQuickSwitch = endTarget == GestureState.GestureEndTarget.NEW_TASK;