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

Commit db711019 authored by Nick Chameyev's avatar Nick Chameyev Committed by Android (Google) Code Review
Browse files

Merge "Finish unfold transition after timeout" into main

parents 21e32624 201e538f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -597,9 +597,10 @@ public abstract class WMShellModule {
            TransactionPool transactionPool,
            Transitions transitions,
            @ShellMainThread ShellExecutor executor,
            @ShellMainThread Handler handler,
            ShellInit shellInit) {
        return new UnfoldTransitionHandler(shellInit, progressProvider.get(), animator,
                unfoldAnimator, transactionPool, executor, transitions);
                unfoldAnimator, transactionPool, executor, handler, transitions);
    }

    @WMSingleton
+22 −0
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@ import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TRANSITI

import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.os.Handler;
import android.os.IBinder;
import android.util.Slog;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
@@ -33,6 +35,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.shared.TransactionPool;
@@ -59,6 +62,10 @@ import java.util.concurrent.Executor;
 */
public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListener {

    private static final String TAG = "UnfoldTransitionHandler";
    @VisibleForTesting
    static final int FINISH_ANIMATION_TIMEOUT_MILLIS = 5_000;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({
            DefaultDisplayChange.DEFAULT_DISPLAY_NO_CHANGE,
@@ -75,6 +82,7 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene
    private final Transitions mTransitions;
    private final Executor mExecutor;
    private final TransactionPool mTransactionPool;
    private final Handler mHandler;

    @Nullable
    private TransitionFinishCallback mFinishCallback;
@@ -87,17 +95,25 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene
    private float mLastAnimationProgress = 0.0f;
    private final List<UnfoldTaskAnimator> mAnimators = new ArrayList<>();

    private final Runnable mAnimationPlayingTimeoutRunnable = () -> {
        Slog.wtf(TAG, "Timeout occurred when playing the unfold animation, "
                + "force finishing the transition");
        finishTransitionIfNeeded();
    };

    public UnfoldTransitionHandler(ShellInit shellInit,
            ShellUnfoldProgressProvider unfoldProgressProvider,
            FullscreenUnfoldTaskAnimator fullscreenUnfoldAnimator,
            SplitTaskUnfoldAnimator splitUnfoldTaskAnimator,
            TransactionPool transactionPool,
            Executor executor,
            Handler handler,
            Transitions transitions) {
        mUnfoldProgressProvider = unfoldProgressProvider;
        mTransitions = transitions;
        mTransactionPool = transactionPool;
        mExecutor = executor;
        mHandler = handler;

        mAnimators.add(splitUnfoldTaskAnimator);
        mAnimators.add(fullscreenUnfoldAnimator);
@@ -159,6 +175,11 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene
        // finish shell transition immediately
        if (mAnimationFinished) {
            finishTransitionIfNeeded();
        } else {
            // TODO: b/318803244 - remove timeout handling when we could guarantee that
            //  the animation will be always finished after receiving startAnimation
            mHandler.removeCallbacks(mAnimationPlayingTimeoutRunnable);
            mHandler.postDelayed(mAnimationPlayingTimeoutRunnable, FINISH_ANIMATION_TIMEOUT_MILLIS);
        }

        return true;
@@ -333,6 +354,7 @@ public class UnfoldTransitionHandler implements TransitionHandler, UnfoldListene
            animator.stop();
        }

        mHandler.removeCallbacks(mAnimationPlayingTimeoutRunnable);
        mFinishCallback.onTransitionFinished(null);
        mFinishCallback = null;
        mTransition = null;
+30 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_NONE;

import static com.android.wm.shell.unfold.UnfoldTransitionHandler.FINISH_ANIMATION_TIMEOUT_MILLIS;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
@@ -32,7 +34,9 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.test.TestLooper;
import android.view.Display;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
@@ -67,6 +71,8 @@ public class UnfoldTransitionHandlerTest {
    private FullscreenUnfoldTaskAnimator mFullscreenUnfoldTaskAnimator;
    private SplitTaskUnfoldAnimator mSplitTaskUnfoldAnimator;
    private Transitions mTransitions;
    private TestLooper mTestLooper;
    private Handler mHandler;

    private final IBinder mTransition = new Binder();

@@ -75,6 +81,9 @@ public class UnfoldTransitionHandlerTest {
        final ShellExecutor executor = new TestSyncExecutor();
        final ShellInit shellInit = new ShellInit(executor);

        mTestLooper = new TestLooper();
        mHandler = new Handler(mTestLooper.getLooper());

        mFullscreenUnfoldTaskAnimator = mock(FullscreenUnfoldTaskAnimator.class);
        mSplitTaskUnfoldAnimator = mock(SplitTaskUnfoldAnimator.class);
        mTransitions = mock(Transitions.class);
@@ -86,6 +95,7 @@ public class UnfoldTransitionHandlerTest {
                mSplitTaskUnfoldAnimator,
                mTransactionPool,
                executor,
                mHandler,
                mTransitions
        );

@@ -159,6 +169,7 @@ public class UnfoldTransitionHandlerTest {
        TransitionFinishCallback mergeFinishCallback = mock(TransitionFinishCallback.class);
        mUnfoldTransitionHandler.mergeAnimation(new Binder(), createFoldTransitionInfo(),
                mock(SurfaceControl.Transaction.class), mTransition, mergeFinishCallback);
        mTestLooper.dispatchAll();

        // Verify that fold transition is merged into unfold and that unfold is finished
        final InOrder inOrder = inOrder(mergeFinishCallback, finishCallback);
@@ -200,6 +211,25 @@ public class UnfoldTransitionHandlerTest {
        assertThat(animationStarted).isTrue();
    }

    @Test
    public void startAnimation_animationHasNotFinishedAfterTimeout_finishesTheTransition() {
        TransitionRequestInfo requestInfo = createUnfoldTransitionRequestInfo();
        mUnfoldTransitionHandler.handleRequest(mTransition, requestInfo);
        TransitionFinishCallback finishCallback = mock(TransitionFinishCallback.class);
        mUnfoldTransitionHandler.startAnimation(
                mTransition,
                mock(TransitionInfo.class),
                mock(SurfaceControl.Transaction.class),
                mock(SurfaceControl.Transaction.class),
                finishCallback
        );

        mTestLooper.moveTimeForward(FINISH_ANIMATION_TIMEOUT_MILLIS + 1);
        mTestLooper.dispatchAll();

        verify(finishCallback).onTransitionFinished(any());
    }

    @Test
    public void startAnimation_differentTransitionFromRequestWithResize_doesNotStartAnimation() {
        mUnfoldTransitionHandler.handleRequest(new Binder(), createNoneTransitionInfo());