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

Commit 0471b983 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Using FrameCallbacks instead of windowCallbacks for surface removal

WindowCallbacks is called during the draw pass, before the frame has
been sent to the surfaceFlinger. Frame callback will provide a closer
approximation for when the frame is actually rendered on screen.

Bug: 141126144
Change-Id: I62aab526c2ca24b00b5e7b312b36080f26c7b439
parent e29a9f79
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1336,7 +1336,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
                if (taskView != null && !mCanceled) {
                    // Defer finishing the animation until the next launcher frame with the
                    // new thumbnail
                    finishTransitionPosted = ViewUtils.postDraw(taskView,
                    finishTransitionPosted = ViewUtils.postFrameDrawn(taskView,
                            () -> mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED),
                            this::isCanceled);
                }
+53 −33
Original line number Diff line number Diff line
@@ -15,21 +15,23 @@
 */
package com.android.quickstep;

import android.graphics.Canvas;
import android.os.Handler;
import android.view.View;

import com.android.systemui.shared.system.WindowCallbacksCompat;
import com.android.launcher3.Utilities;
import com.android.systemui.shared.system.ViewRootImplCompat;

import java.util.function.BooleanSupplier;
import java.util.function.LongConsumer;

/**
 * Utility class for helpful methods related to {@link View} objects.
 */
public class ViewUtils {

    /** See {@link #postDraw(View, Runnable, BooleanSupplier)}} */
    public static boolean postDraw(View view, Runnable onFinishRunnable) {
        return postDraw(view, onFinishRunnable, () -> false);
    /** See {@link #postFrameDrawn(View, Runnable, BooleanSupplier)}} */
    public static boolean postFrameDrawn(View view, Runnable onFinishRunnable) {
        return postFrameDrawn(view, onFinishRunnable, () -> false);
    }

    /**
@@ -38,37 +40,55 @@ public class ViewUtils {
     *
     * @param onFinishRunnable runnable to be run right after the view finishes drawing.
     */
    public static boolean postDraw(View view, Runnable onFinishRunnable, BooleanSupplier canceled) {
        // Defer finishing the animation until the next launcher frame with the
        // new thumbnail
        return new WindowCallbacksCompat(view) {
            // The number of frames to defer until we actually finish the animation
            private int mDeferFrameCount = 2;
    public static boolean postFrameDrawn(
            View view, Runnable onFinishRunnable, BooleanSupplier canceled) {
        return new FrameHandler(view, onFinishRunnable, canceled).schedule();
    }

    private static class FrameHandler implements LongConsumer {

        final ViewRootImplCompat mViewRoot;
        final Runnable mFinishCallback;
        final BooleanSupplier mCancelled;
        final Handler mHandler;

        int mDeferFrameCount = 1;

        FrameHandler(View view, Runnable finishCallback, BooleanSupplier cancelled) {
            mViewRoot = new ViewRootImplCompat(view);
            mFinishCallback = finishCallback;
            mCancelled = cancelled;
            mHandler = new Handler();
        }

        @Override
            public void onPostDraw(Canvas canvas) {
                // If we were cancelled after this was attached, do not update
                // the state.
                if (canceled.getAsBoolean()) {
                    detach();
        public void accept(long l) {
            Utilities.postAsyncCallback(mHandler, this::onFrame);
        }

        private void onFrame() {
            if (mCancelled.getAsBoolean()) {
                return;
            }

            if (mDeferFrameCount > 0) {
                mDeferFrameCount--;
                    // Workaround, detach and reattach to invalidate the root node for
                    // another draw
                    detach();
                    attach();
                    view.invalidate();
                schedule();
                return;
            }

                if (onFinishRunnable != null) {
                    onFinishRunnable.run();
            if (mFinishCallback != null) {
                mFinishCallback.run();
            }
        }

        private boolean schedule() {
            if (mViewRoot.isValid()) {
                mViewRoot.registerRtFrameCallback(this);
                mViewRoot.getView().invalidate();
                return true;
            }
                detach();
            return false;
        }
        }.attach();
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -2442,7 +2442,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
            } else {
                taskView.getThumbnail().refresh();
            }
            ViewUtils.postDraw(taskView, onFinishRunnable);
            ViewUtils.postFrameDrawn(taskView, onFinishRunnable);
        } else {
            onFinishRunnable.run();
        }