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

Commit bc5d7291 authored by George Mount's avatar George Mount
Browse files

Further improve performance of VRR

Bug: 330765659
Bug: 330806626
Bug: 330818088
Bug: 330785773

Removed getTranslationX()/getTranslationY() calls during
invalidation.

Changed flag reading to use final constants.

Use int instead of long for duration millis comparison.

Use "switch" statement instead of consecutive "if"
statements.

Moved update time to updateDisplayListIfDirty() rather
than during invalidation in case invaliation happens
multiple times per draw.

Test: ran performance check. Now at 12% overhead
Change-Id: I10510f0f686f1430791e0ae3e5de6f99bad3593c
parent 46bc6e18
Loading
Loading
Loading
Loading
+96 −62
Original line number Diff line number Diff line
@@ -2431,6 +2431,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    protected static boolean sToolkitSetFrameRateReadOnlyFlagValue;
    private static boolean sToolkitMetricsForFrameRateDecisionFlagValue;
    private static final boolean sToolkitFrameRateDefaultNormalReadOnlyFlagValue =
            toolkitFrameRateDefaultNormalReadOnly();
    private static final boolean sToolkitFrameRateBySizeReadOnlyFlagValue =
            toolkitFrameRateBySizeReadOnly();
    // Used to set frame rate compatibility.
    @Surface.FrameRateCompatibility int mFrameRateCompatibility =
            FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
@@ -3764,6 +3769,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *         1                        PFLAG4_ROTARY_HAPTICS_WAITING_FOR_SCROLL_EVENT
     *       11                         PFLAG4_CONTENT_SENSITIVITY_MASK
     *      1                           PFLAG4_IS_COUNTED_AS_SENSITIVE
     *     1                            PFLAG4_HAS_DRAWN
     *    1                             PFLAG4_HAS_MOVED
     * |-------|-------|-------|-------|
     */
@@ -3896,6 +3903,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @see AttachInfo#mSensitiveViewsCount
     */
    private static final int PFLAG4_IS_COUNTED_AS_SENSITIVE = 0x4000000;
    /**
     * Whether this view has been drawn once with updateDisplayListIfDirty() or not.
     * Used by VRR to for quick detection of scrolling.
     */
    private static final int PFLAG4_HAS_DRAWN = 0x8000000;
    /**
     * Whether this view has been moved with either setTranslationX/Y or setLeft/Top.
     * Used by VRR to for quick detection of scrolling.
     */
    private static final int PFLAG4_HAS_MOVED = 0x10000000;
    /* End of masks for mPrivateFlags4 */
    /** @hide */
@@ -5695,12 +5715,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private ViewTranslationResponse mViewTranslationResponse;
    /**
     * The multiplier for mAttachInfo.mSmallSizePixels to consider a View to be small
     * if both dimensions are smaller than this.
     * The size in DP that is considered small for VRR purposes, if square.
     */
    private static final float FRAME_RATE_SQUARE_SMALL_SIZE_DP = 40f;
    /**
     * The size in DP that is considered small for VRR purposes in the narrow dimension. Used for
     * narrow Views like a progress bar.
     */
    private static final int FRAME_RATE_SQUARE_SMALL_SIZE_MULTIPLIER = 4;
    private static final float FRAME_RATE_NARROW_SIZE_DP = 10f;
    private static final long INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
    private static final int INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
    private static final int INFREQUENT_UPDATE_COUNTS = 2;
    // The preferred frame rate of the view that is mainly used for
@@ -5712,16 +5737,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    /**
     * @hide
     */
    protected long mMinusOneFrameIntervalMillis = 0;
    protected int mMinusOneFrameIntervalMillis = 0;
    /**
     * @hide
     */
    protected long mMinusTwoFrameIntervalMillis = 0;
    protected int mMinusTwoFrameIntervalMillis = 0;
    private int mLastFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
    private float mLastFrameX = Float.NaN;
    private float mLastFrameY = Float.NaN;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_DEFAULT = Float.NaN;
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
@@ -19420,6 +19442,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public final void setTop(int top) {
        if (top != mTop) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
@@ -19544,6 +19567,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public final void setLeft(int left) {
        if (left != mLeft) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (mAttachInfo != null) {
@@ -19800,6 +19824,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @RemotableViewMethod
    public void setTranslationX(float translationX) {
        if (translationX != getTranslationX()) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            invalidateViewProperty(true, false);
            mRenderNode.setTranslationX(translationX);
            invalidateViewProperty(false, true);
@@ -19836,6 +19861,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @RemotableViewMethod
    public void setTranslationY(float translationY) {
        if (translationY != getTranslationY()) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            invalidateViewProperty(true, false);
            mRenderNode.setTranslationY(translationY);
            invalidateViewProperty(false, true);
@@ -20308,6 +20334,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public void offsetTopAndBottom(int offset) {
        if (offset != 0) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (isHardwareAccelerated()) {
@@ -20359,6 +20386,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    public void offsetLeftAndRight(int offset) {
        if (offset != 0) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            final boolean matrixIsIdentity = hasIdentityMatrix();
            if (matrixIsIdentity) {
                if (isHardwareAccelerated()) {
@@ -20758,7 +20786,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        // For VRR to vote the preferred frame rate
        if (sToolkitSetFrameRateReadOnlyFlagValue) {
            updateInfrequentCount();
            votePreferredFrameRate();
        }
@@ -20866,7 +20893,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        if (mParent != null && mAttachInfo != null) {
            // For VRR to vote the preferred frame rate
            if (sToolkitSetFrameRateReadOnlyFlagValue) {
                updateInfrequentCount();
                votePreferredFrameRate();
            }
            mParent.onDescendantInvalidated(this, this);
@@ -23556,8 +23582,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return renderNode;
        }
        mLastFrameX = mLeft + mRenderNode.getTranslationX();
        mLastFrameY = mTop + mRenderNode.getTranslationY();
        mPrivateFlags4 = (mPrivateFlags4 & ~PFLAG4_HAS_MOVED) | PFLAG4_HAS_DRAWN;
        if (sToolkitSetFrameRateReadOnlyFlagValue) {
            updateInfrequentCount();
        }
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
                || !renderNode.hasDisplayList()
@@ -25398,6 +25426,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        }
        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
            changed = true;
            // Remember our drawn bit
@@ -25471,15 +25500,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
        if (mAttachInfo != null) {
            int narrowSize = mAttachInfo.mSmallSizePixels;
            int smallSize = narrowSize * FRAME_RATE_SQUARE_SMALL_SIZE_MULTIPLIER;
            float density = mAttachInfo.mDensity;
            int narrowSize = (int) (density * FRAME_RATE_NARROW_SIZE_DP);
            int smallSize = (int) (density * FRAME_RATE_SQUARE_SMALL_SIZE_DP);
            if (newWidth <= narrowSize || newHeight <= narrowSize
                    || (newWidth <= smallSize && newHeight <= smallSize)) {
                int category = toolkitFrameRateBySizeReadOnly()
                int category = sToolkitFrameRateBySizeReadOnlyFlagValue
                        ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_SMALL;
            } else {
                int category = toolkitFrameRateDefaultNormalReadOnly()
                int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
                        ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_LARGE;
            }
@@ -32051,11 +32081,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        int mSensitiveViewsCount;
        /**
         * The size used for a View to be considered small for the purposes of using
         * low refresh rate by default. This is the size in one direction, so a long, thin
         * item like a progress bar can be compared to this.
         * The value of viewVelocityApi(), read only once per ViewRootImpl
         */
        final boolean mViewVelocityApi = viewVelocityApi();
        /**
         * Density so that it doesn't need to be retrieved on every invalidation.
         */
        final int mSmallSizePixels;
        final float mDensity;
        /**
         * Creates a new set of attachment information with the specified
@@ -32074,7 +32107,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mHandler = handler;
            mRootCallbacks = effectPlayer;
            mTreeObserver = new ViewTreeObserver(context);
            mSmallSizePixels = (int) (context.getResources().getDisplayMetrics().density * 10);
            mDensity = context.getResources().getDisplayMetrics().density;
        }
        void increaseSensitiveViewsCount() {
@@ -33821,17 +33854,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        if (viewRootImpl != null && (width != 0 && height != 0)) {
            if (viewVelocityApi()) {
            if (mAttachInfo.mViewVelocityApi) {
                float velocity = mFrameContentVelocity;
                if (velocity < 0f) {
                int mask = PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN;
                if (velocity < 0f && (mPrivateFlags4 & mask) == mask) {
                    // This current calculation is very simple. If something on the screen moved,
                    // then it votes for the highest velocity. If it doesn't move, then return 0.
                    RenderNode renderNode = mRenderNode;
                    float x = mLeft + renderNode.getTranslationX();
                    float y = mTop + renderNode.getTranslationY();
                    velocity = (!Float.isNaN(mLastFrameX) && (x != mLastFrameX || y != mLastFrameY))
                            ? 100_000f : 0f;
                    velocity = Float.POSITIVE_INFINITY;
                }
                if (velocity > 0f) {
                    float frameRate = convertVelocityToFrameRate(velocity);
@@ -33849,25 +33878,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                if (Float.isNaN(mPreferredFrameRate)) {
                    frameRateCategory = calculateFrameRateCategory();
                } else if (mPreferredFrameRate < 0) {
                    if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE) {
                    switch ((int) mPreferredFrameRate) {
                        case (int) REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE ->
                                frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_LOW) {
                        case (int) REQUESTED_FRAME_RATE_CATEGORY_LOW ->
                                frameRateCategory = FRAME_RATE_CATEGORY_LOW
                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NORMAL) {
                        case (int) REQUESTED_FRAME_RATE_CATEGORY_NORMAL ->
                                frameRateCategory = FRAME_RATE_CATEGORY_NORMAL
                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    } else if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_HIGH) {
                        case (int) REQUESTED_FRAME_RATE_CATEGORY_HIGH ->
                                frameRateCategory = FRAME_RATE_CATEGORY_HIGH
                                        | FRAME_RATE_CATEGORY_REASON_REQUESTED;
                    } else {
                        default -> {
                            // invalid frame rate, use default
                        int category = toolkitFrameRateDefaultNormalReadOnly()
                            int category = sToolkitFrameRateDefaultNormalReadOnlyFlagValue
                                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                            frameRateCategory = category
                                    | FRAME_RATE_CATEGORY_REASON_INVALID;
                        }
                    }
                } else {
                    viewRootImpl.votePreferredFrameRate(mPreferredFrameRate,
                            mFrameRateCompatibility);
@@ -33883,7 +33914,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    private float convertVelocityToFrameRate(float velocityPps) {
        float density = getResources().getDisplayMetrics().density;
        float density = mAttachInfo.mDensity;
        float velocityDps = velocityPps / density;
        // Choose a frame rate in increments of 10fps
        return Math.min(140f, 60f + (10f * (float) Math.floor(velocityDps / 300f)));
@@ -33971,8 +34002,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * - otherwise, use the previous category value.
     */
    private void updateInfrequentCount() {
        if (!willNotDraw()) {
            long currentTimeMillis = getDrawingTime();
        long timeIntervalMillis = currentTimeMillis - mLastUpdateTimeMillis;
            int timeIntervalMillis =
                    (int) Math.min(Integer.MAX_VALUE, currentTimeMillis - mLastUpdateTimeMillis);
            mMinusTwoFrameIntervalMillis = mMinusOneFrameIntervalMillis;
            mMinusOneFrameIntervalMillis = timeIntervalMillis;
@@ -33988,3 +34021,4 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            }
        }
    }
}
+8 −8
Original line number Diff line number Diff line
@@ -12617,14 +12617,14 @@ public final class ViewRootImpl implements ViewParent,
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
    public void votePreferredFrameRateCategory(int frameRateCategory, int reason, View view) {
        if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH) {
            mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_HIGH_HINT) {
            mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_NORMAL) {
        switch (frameRateCategory) {
            case FRAME_RATE_CATEGORY_LOW -> mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
            case FRAME_RATE_CATEGORY_NORMAL ->
                    mFrameRateCategoryNormalCount = FRAME_RATE_CATEGORY_COUNT;
        } else if (frameRateCategory == FRAME_RATE_CATEGORY_LOW) {
            mFrameRateCategoryLowCount = FRAME_RATE_CATEGORY_COUNT;
            case FRAME_RATE_CATEGORY_HIGH_HINT ->
                    mFrameRateCategoryHighHintCount = FRAME_RATE_CATEGORY_COUNT;
            case FRAME_RATE_CATEGORY_HIGH ->
                    mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
        }
        int oldCategory = mPreferredFrameRateCategory;
+6 −6
Original line number Diff line number Diff line
@@ -136,8 +136,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = 4 * ((int) (10 * density));
            layoutParams.width = 4 * ((int) (10 * density));
            layoutParams.height = ((int) (40 * density));
            layoutParams.width = ((int) (40 * density));
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });
@@ -211,8 +211,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = 4 * ((int) (10 * density));
            layoutParams.width = 4 * ((int) Math.ceil(10 * density)) + 1;
            layoutParams.height = (int) (40 * density);
            layoutParams.width = ((int) Math.ceil(40 * density)) + 1;
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });
@@ -236,8 +236,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = 4 * ((int) Math.ceil(10 * density)) + 1;
            layoutParams.width = 4 * ((int) (10 * density));
            layoutParams.height = ((int) Math.ceil(40 * density)) + 1;
            layoutParams.width = ((int) (40 * density));
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });