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

Commit 64982b53 authored by Peter Kalauskas's avatar Peter Kalauskas
Browse files

Fix jank in CUJ_NOTIFICATION_HEADS_UP_APPEAR

Use Choreographer to delay animation and mitigate jank in
J<NOTIFICATION_HEADS_UP_APPEAR>

Test: 1) setprop persist.debug.animator.trace_fraction true &&
      device_config put interaction_jank_monitor enabled true.
      2) Capture perfetto trace while posting test HUN. 3) Inspect the
      trace; verify that sysui's frames during the
      J<NOTIFICATION_HEADS_UP_APPEAR> CUJ are not in high latency state
Bug: 262705829
Change-Id: I34df2978310a27859725ede28dd556c35d4bd785
parent 3e92172c
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Canvas;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.Choreographer;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
@@ -492,12 +493,9 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        if (animationListener != null) {
            mAppearAnimator.addListener(animationListener);
        }
        if (delay > 0) {
        // we need to apply the initial state already to avoid drawn frames in the wrong state
        updateAppearAnimationAlpha();
        updateAppearRect();
            mAppearAnimator.setStartDelay(delay);
        }
        mAppearAnimator.addListener(new AnimatorListenerAdapter() {
            private boolean mWasCancelled;

@@ -528,8 +526,21 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
                mWasCancelled = true;
            }
        });

        // Cache the original animator so we can check if the animation should be started in the
        // Choreographer callback. It's possible that the original animator (mAppearAnimator) is
        // replaced with a new value before the callback is called.
        ValueAnimator cachedAnimator = mAppearAnimator;
        // Even when delay=0, starting the animation on the next frame is necessary to avoid jank.
        // Not doing so will increase the chances our Animator will be forced to skip a value of
        // the animation's progression, causing stutter.
        Choreographer.getInstance().postFrameCallbackDelayed(
                frameTimeNanos -> {
                    if (mAppearAnimator == cachedAnimator) {
                        mAppearAnimator.start();
                    }
                }, delay);
    }

    private int getCujType(boolean isAppearing) {
        if (mIsHeadsUpAnimation) {