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

Commit d3ceb3dc authored by Jerry Chang's avatar Jerry Chang Committed by Vinit Nayak
Browse files

Reset floating split task view after remote animation finished

Move reseting floating task view for entering split after remote
animation finished to prevent the floating task view disappear before
opening split task view being visible and causing flicker.

Bug: 199377815
Test: Manual check the flicker disappear
Change-Id: I4a864335972842570c61291a7a0c423edeb74578
parent e37b51b3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -349,7 +349,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
        mActionsView = findViewById(R.id.overview_actions_view);
        RecentsView overviewPanel = (RecentsView) getOverviewPanel();
        SplitSelectStateController controller =
                new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this));
                new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
        overviewPanel.init(mActionsView, controller);
        mActionsView.setDp(getDeviceProfile());
        mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
+1 −1
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
        SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);

        SplitSelectStateController controller =
                new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this));
                new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
        mDragLayer.recreateControllers();
        mFallbackRecentsView.init(mActionsView, controller);
    }
+55 −21
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLAT
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;

@@ -42,6 +43,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
@@ -79,6 +81,8 @@ import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;

import java.util.ArrayList;

/**
 * Utility class for helpful methods related to {@link TaskView} objects and their tasks.
 */
@@ -427,35 +431,65 @@ public final class TaskViewUtils {
            @NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
            @NonNull RemoteAnimationTargetCompat[] nonAppTargets,
            @NonNull Runnable finishCallback) {
        final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
        final ArrayList<SurfaceControl> closingTargets = new ArrayList<>();

        final int[] splitRoots = new int[2];
        for (int i = 0; i < appTargets.length; ++i) {
            final int taskId = appTargets[i].taskInfo != null ? appTargets[i].taskInfo.taskId : -1;
            final int mode = appTargets[i].mode;
            if (taskId == initialTask.key.id || taskId == secondTask.key.id) {
                if (mode != MODE_OPENING) {
                    throw new IllegalStateException(
                            "Expected task to be opening, but it is " + mode);
        for (RemoteAnimationTargetCompat appTarget : appTargets) {
            final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
            final int mode = appTarget.mode;
            final SurfaceControl leash = appTarget.leash.getSurfaceControl();
            if (leash == null) {
                continue;
            }
                splitRoots[taskId == initialTask.key.id ? 0 : 1] = i;

            if (mode == MODE_OPENING) {
                openingTargets.add(leash);
            } else if (taskId == initialTask.key.id || taskId == secondTask.key.id) {
                throw new IllegalStateException("Expected task to be opening, but it is " + mode);
            } else if (mode == MODE_CLOSING) {
                closingTargets.add(leash);
            }
        }

        SurfaceControl.Transaction t = new SurfaceControl.Transaction();

        // This is where we should animate the split roots. For now, though, just make them visible.
        for (int i = 0; i < 2; ++i) {
            t.show(appTargets[splitRoots[i]].leash.getSurfaceControl());
            t.setAlpha(appTargets[splitRoots[i]].leash.getSurfaceControl(), 1.f);
        for (int i = 0; i < nonAppTargets.length; ++i) {
            final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
            if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
                openingTargets.add(leash);
            }
        }

        // This contains the initial state (before animation), so apply this at the beginning of
        // the animation.
        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
        animator.addUpdateListener(valueAnimator -> {
            float progress = valueAnimator.getAnimatedFraction();
            for (SurfaceControl leash: openingTargets) {
                t.setAlpha(leash, progress);
            }
            for (SurfaceControl leash: closingTargets) {
                t.setAlpha(leash, 1 - progress);
            }
            t.apply();
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                for (SurfaceControl leash: openingTargets) {
                    t.show(leash).setAlpha(leash, 0.0f);
                }
                t.apply();
            }

        // Once there is an animation, this should be called AFTER the animation completes.
            @Override
            public void onAnimationEnd(Animator animation) {
                for (SurfaceControl leash: closingTargets) {
                    t.hide(leash);
                }
                super.onAnimationEnd(animation);
                finishCallback.run();
            }
        });
        animator.start();
    }

    public static void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
            @NonNull RemoteAnimationTargetCompat[] appTargets,
+23 −13
Original line number Diff line number Diff line
@@ -16,17 +16,20 @@

package com.android.quickstep.util;

import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;

import android.app.ActivityThread;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.window.TransitionInfo;

import com.android.launcher3.Utilities;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.SystemUiProxy;
@@ -47,13 +50,15 @@ import java.util.function.Consumer;
 */
public class SplitSelectStateController {

    private final Handler mHandler;
    private final SystemUiProxy mSystemUiProxy;
    private @StagePosition int mStagePosition;
    private Task mInitialTask;
    private Task mSecondTask;
    private Rect mInitialBounds;

    public SplitSelectStateController(SystemUiProxy systemUiProxy) {
    public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
        mHandler = handler;
        mSystemUiProxy = systemUiProxy;
    }

@@ -70,9 +75,9 @@ public class SplitSelectStateController {
    /**
     * To be called after second task selected
     */
    public void setSecondTaskId(Task taskView) {
    public void setSecondTaskId(Task taskView, Consumer<Boolean> callback) {
        mSecondTask = taskView;
        launchTasks(mInitialTask, mSecondTask, mStagePosition, null /*callback*/);
        launchTasks(mInitialTask, mSecondTask, mStagePosition, callback);
    }

    /**
@@ -151,22 +156,27 @@ public class SplitSelectStateController {
        public void onAnimationStart(int transit, RemoteAnimationTargetCompat[] apps,
                RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
                Runnable finishedCallback) {
            TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
            postAsyncCallback(mHandler,
                    () -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
                            mSecondTask, apps, wallpapers, nonApps, () -> {
                                finishedCallback.run();
                                if (mSuccessCallback != null) {
                                    mSuccessCallback.accept(true);
                                }
                    });
                            }));

            // After successful launch, call resetState
            resetState();
        }

        @Override
        public void onAnimationCancelled() {
            postAsyncCallback(mHandler, () -> {
                if (mSuccessCallback != null) {
                    mSuccessCallback.accept(false);
                }
            });

            resetState();
        }
    }
+3 −4
Original line number Diff line number Diff line
@@ -3836,10 +3836,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
                secondTaskEndingBounds, taskView.getThumbnail(),
                true /*fadeWithThumbnail*/);
        pendingAnimation.addEndListener(aBoolean -> {
            mSplitSelectStateController.setSecondTaskId(taskView.getTask());
            resetFromSplitSelectionState();
        });
        pendingAnimation.addEndListener(aBoolean ->
                mSplitSelectStateController.setSecondTaskId(taskView.getTask(),
                aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
        mSecondSplitHiddenTaskView = taskView;
        taskView.setVisibility(INVISIBLE);
        pendingAnimation.buildAnim().start();