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

Commit a0622f53 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Improve performance of VRR" into main

parents 57089e1b 84ddbe54
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -889,11 +889,11 @@ public class TextureView extends View {
     * @hide
     */
    @Override
    protected int calculateFrameRateCategory(int width, int height) {
    protected int calculateFrameRateCategory() {
        if (mMinusTwoFrameIntervalMillis > 15 && mMinusOneFrameIntervalMillis > 15) {
            return FRAME_RATE_CATEGORY_NORMAL;
        }
        return super.calculateFrameRateCategory(width, height);
        return super.calculateFrameRateCategory();
    }

    @UnsupportedAppUsage
+87 −77
Original line number Diff line number Diff line
@@ -5695,17 +5695,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    private ViewTranslationResponse mViewTranslationResponse;
    /**
     * Threshold size for something to be considered a small area update (in DP).
     * This is the dimension for both width and height.
     * The multiplier for mAttachInfo.mSmallSizePixels to consider a View to be small
     * if both dimensions are smaller than this.
     */
    private static final float FRAME_RATE_SMALL_SIZE_THRESHOLD = 40f;
    /**
     * Threshold size for something to be considered a small area update (in DP) if
     * it is narrow. This is for either width OR height. For example, a narrow progress
     * bar could be considered a small area.
     */
    private static final float FRAME_RATE_NARROW_THRESHOLD = 10f;
    private static final int FRAME_RATE_SQUARE_SMALL_SIZE_MULTIPLIER = 4;
    private static final long INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
    private static final int INFREQUENT_UPDATE_COUNTS = 2;
@@ -5740,6 +5733,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    @FlaggedApi(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public static final float REQUESTED_FRAME_RATE_CATEGORY_HIGH = -4;
    private int mSizeBasedFrameRateCategoryAndReason;
    /**
     * Simple constructor to use when creating a view from code.
     *
@@ -23561,6 +23556,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return renderNode;
        }
        mLastFrameX = mLeft + mRenderNode.getTranslationX();
        mLastFrameY = mTop + mRenderNode.getTranslationY();
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
                || !renderNode.hasDisplayList()
                || (mRecreateDisplayList)) {
@@ -24724,8 +24722,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        mFrameContentVelocity = -1;
        mLastFrameX = mLeft + mRenderNode.getTranslationX();
        mLastFrameY = mTop + mRenderNode.getTranslationY();
        /*
         * Draw traversal performs several drawing steps which must be executed
@@ -25474,6 +25470,21 @@ 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;
            if (newWidth <= narrowSize || newHeight <= narrowSize
                    || (newWidth <= smallSize && newHeight <= smallSize)) {
                int category = toolkitFrameRateBySizeReadOnly()
                        ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_SMALL;
            } else {
                int category = toolkitFrameRateDefaultNormalReadOnly()
                        ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                mSizeBasedFrameRateCategoryAndReason = category | FRAME_RATE_CATEGORY_REASON_LARGE;
            }
        }
        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
        if (mOverlay != null) {
            mOverlay.getOverlayView().setRight(newWidth);
@@ -32039,6 +32050,13 @@ 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.
         */
        final int mSmallSizePixels;
        /**
         * Creates a new set of attachment information with the specified
         * events handler and thread.
@@ -32056,6 +32074,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mHandler = handler;
            mRootCallbacks = effectPlayer;
            mTreeObserver = new ViewTreeObserver(context);
            mSmallSizePixels = (int) (context.getResources().getDisplayMetrics().density * 10);
        }
        void increaseSensitiveViewsCount() {
@@ -33784,28 +33803,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *
     * @hide
     */
    protected int calculateFrameRateCategory(int width, int height) {
    protected int calculateFrameRateCategory() {
        if (mMinusTwoFrameIntervalMillis + mMinusOneFrameIntervalMillis
                < INFREQUENT_UPDATE_INTERVAL_MILLIS) {
            DisplayMetrics displayMetrics = mResources.getDisplayMetrics();
            float density = displayMetrics.density;
            if (density == 0f) {
                density = 1f;
            }
            float widthDp = width / density;
            float heightDp = height / density;
            if (widthDp <= FRAME_RATE_NARROW_THRESHOLD
                    || heightDp <= FRAME_RATE_NARROW_THRESHOLD
                    || (widthDp <= FRAME_RATE_SMALL_SIZE_THRESHOLD
                    && heightDp <= FRAME_RATE_SMALL_SIZE_THRESHOLD)) {
                int category = toolkitFrameRateBySizeReadOnly()
                        ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
                return category | FRAME_RATE_CATEGORY_REASON_SMALL;
            } else {
                int category = toolkitFrameRateDefaultNormalReadOnly()
                        ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
                return category | FRAME_RATE_CATEGORY_REASON_LARGE;
            }
            return mSizeBasedFrameRateCategoryAndReason;
        }
        if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
@@ -33823,7 +33824,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            if (viewVelocityApi()) {
                float velocity = mFrameContentVelocity;
                if (velocity < 0f) {
                    velocity = calculateVelocity();
                    // 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;
                }
                if (velocity > 0f) {
                    float frameRate = convertVelocityToFrameRate(velocity);
@@ -33831,13 +33839,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                    return;
                }
            }
            if (!willNotDraw()) {
                if (sToolkitMetricsForFrameRateDecisionFlagValue) {
                    float sizePercentage = getSizePercentage();
                    viewRootImpl.recordViewPercentage(sizePercentage);
                }
                int frameRateCategory;
                if (Float.isNaN(mPreferredFrameRate)) {
                frameRateCategory = calculateFrameRateCategory(width, height);
                    if (mMinusTwoFrameIntervalMillis + mMinusOneFrameIntervalMillis
                            < INFREQUENT_UPDATE_INTERVAL_MILLIS && mAttachInfo != null) {
                        frameRateCategory = mSizeBasedFrameRateCategoryAndReason;
                    } else if (mInfrequentUpdateCount == INFREQUENT_UPDATE_COUNTS) {
                        frameRateCategory =
                                FRAME_RATE_CATEGORY_NORMAL
                                        | FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
                    } else {
                        frameRateCategory = mLastFrameRateCategory;
                    }
                } else if (mPreferredFrameRate < 0) {
                    if (mPreferredFrameRate == REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE) {
                        frameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE
@@ -33870,6 +33889,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                mLastFrameRateCategory = frameRateCategory;
            }
        }
    }
    private float convertVelocityToFrameRate(float velocityPps) {
        float density = getResources().getDisplayMetrics().density;
@@ -33878,16 +33898,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return Math.min(140f, 60f + (10f * (float) Math.floor(velocityDps / 300f)));
    }
    private float calculateVelocity() {
        // 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.
        float x = mLeft + mRenderNode.getTranslationX();
        float y = mTop + mRenderNode.getTranslationY();
        return (!Float.isNaN(mLastFrameX) && (x != mLastFrameX || y != mLastFrameY))
                ? 100_000f : 0f;
    }
    /**
     * Set the current velocity of the View, we only track positive value.
     * We will use the velocity information to adjust the frame rate when applicable.
+2 −4
Original line number Diff line number Diff line
@@ -12626,12 +12626,11 @@ public final class ViewRootImpl implements ViewParent,
        }
        mHasInvalidation = true;
        checkIdleness();
        if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)
                && mPreferredFrameRateCategory != oldCategory
        if (mPreferredFrameRateCategory != oldCategory
                && mPreferredFrameRateCategory == frameRateCategory
        ) {
            mFrameRateCategoryChangeReason = reason;
            mFrameRateCategoryView = view.getClass().getSimpleName();
            mFrameRateCategoryView = view == null ? "null" : view.getClass().getSimpleName();
        }
    }
@@ -12791,7 +12790,6 @@ public final class ViewRootImpl implements ViewParent,
        // uncomment this when we are ready for enabling dVRR
        // return sToolkitSetFrameRateReadOnlyFlagValue && isFrameRatePowerSavingsBalanced();
        return false;
    }
    private void checkIdleness() {
+10 −10
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package android.view;
import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_DEFAULT_NORMAL_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
@@ -137,8 +136,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = (int) (40 * density);
            layoutParams.width = (int) (40 * density);
            layoutParams.height = 4 * ((int) (10 * density));
            layoutParams.width = 4 * ((int) (10 * density));
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });
@@ -212,8 +211,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = (int) (40 * density);
            layoutParams.width = (int) Math.ceil(41 * density);
            layoutParams.height = 4 * ((int) (10 * density));
            layoutParams.width = 4 * ((int) Math.ceil(10 * density)) + 1;
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });
@@ -237,8 +236,8 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            float density = mActivity.getResources().getDisplayMetrics().density;
            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
            layoutParams.height = (int) Math.ceil(41 * density);
            layoutParams.width = (int) (40 * density);
            layoutParams.height = 4 * ((int) Math.ceil(10 * density)) + 1;
            layoutParams.width = 4 * ((int) (10 * density));
            mMovingView.setLayoutParams(layoutParams);
            mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch1::countDown);
        });
@@ -256,13 +255,14 @@ public class ViewFrameRateTest {
    }

    @Test
    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_DEFAULT_NORMAL_READ_ONLY})
    @RequiresFlagsEnabled(FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY)
    public void defaultNormal() throws Throwable {
        waitForFrameRateCategoryToSettle();
        mActivityRule.runOnUiThread(() -> {
            mMovingView.invalidate();
            assertEquals(FRAME_RATE_CATEGORY_NORMAL,
            int expected = toolkitFrameRateDefaultNormalReadOnly()
                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
            assertEquals(expected,
                    mViewRoot.getPreferredFrameRateCategory());
        });
    }
+1 −1
Original line number Diff line number Diff line
@@ -667,7 +667,7 @@ public class ViewRootImplTest {
    }

    /**
     * Test how values of the frame rate cateogry are aggregated.
     * Test how values of the frame rate category are aggregated.
     * It should take the max value among all of the voted categories per frame.
     */
    @Test