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

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

Merge "Reduce the votePreferredFrameRate calls" into main

parents 2b7ddf10 c58708a6
Loading
Loading
Loading
Loading
+31 −24
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import static android.view.flags.Flags.sensitiveContentAppProtection;
import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;
import static android.view.flags.Flags.toolkitFrameRateViewEnablingReadOnly;
import static android.view.flags.Flags.toolkitMetricsForFrameRateDecision;
import static android.view.flags.Flags.toolkitSetFrameRateReadOnly;
@@ -2443,6 +2444,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            toolkitFrameRateSmallUsesPercentReadOnly();
    private static final boolean sToolkitFrameRateViewEnablingReadOnlyFlagValue =
            toolkitFrameRateViewEnablingReadOnly();
    private static boolean sToolkitFrameRateVelocityMappingReadOnlyFlagValue =
            toolkitFrameRateVelocityMappingReadOnly();
    // Used to set frame rate compatibility.
    @Surface.FrameRateCompatibility int mFrameRateCompatibility =
@@ -5739,6 +5742,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    private static final float FRAME_RATE_SIZE_PERCENTAGE_THRESHOLD = 0.07f;
    private static final float MAX_FRAME_RATE = 140;
    private static final int INFREQUENT_UPDATE_INTERVAL_MILLIS = 100;
    private static final int INFREQUENT_UPDATE_COUNTS = 2;
@@ -20824,12 +20829,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return;
        }
        // For VRR to vote the preferred frame rate
        if (sToolkitSetFrameRateReadOnlyFlagValue
                && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
            votePreferredFrameRate();
        }
        // Reset content capture caches
        mPrivateFlags4 &= ~PFLAG4_CONTENT_CAPTURE_IMPORTANCE_MASK;
        mContentCaptureSessionCached = false;
@@ -20932,11 +20931,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    protected void damageInParent() {
        if (mParent != null && mAttachInfo != null) {
            // For VRR to vote the preferred frame rate
            if (sToolkitSetFrameRateReadOnlyFlagValue
                    && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
                votePreferredFrameRate();
            }
            mParent.onDescendantInvalidated(this, this);
        }
    }
@@ -23624,12 +23618,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            return renderNode;
        }
        mPrivateFlags4 = (mPrivateFlags4 & ~PFLAG4_HAS_MOVED) | PFLAG4_HAS_DRAWN;
        // For VRR to vote the preferred frame rate
        if (sToolkitSetFrameRateReadOnlyFlagValue
                && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
            votePreferredFrameRate();
            updateInfrequentCount();
        }
        mPrivateFlags4 = (mPrivateFlags4 & ~PFLAG4_HAS_MOVED) | PFLAG4_HAS_DRAWN;
        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
                || !renderNode.hasDisplayList()
                || (mRecreateDisplayList)) {
@@ -23694,6 +23691,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
        }
        mFrameContentVelocity = -1;
        return renderNode;
    }
@@ -24792,8 +24791,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        final int privateFlags = mPrivateFlags;
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        mFrameContentVelocity = -1;
        /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
@@ -33888,32 +33885,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return mLastFrameRateCategory;
    }
    private void votePreferredFrameRate() {
    /**
     * Used to vote the preferred frame rate and frame rate category to ViewRootImpl
     *
     * @hide
     */
    protected void votePreferredFrameRate() {
        // use toolkitSetFrameRate flag to gate the change
        ViewRootImpl viewRootImpl = getViewRootImpl();
        int width = mRight - mLeft;
        int height = mBottom - mTop;
        float alpha = mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
        int visibility = mViewFlags & VISIBILITY_MASK;
        if (viewRootImpl != null && (width != 0 && height != 0)
                && alpha != 0 && visibility == View.VISIBLE
        ) {
        if (viewRootImpl != null && (width != 0 && height != 0)) {
            if (mAttachInfo.mViewVelocityApi) {
                float velocity = mFrameContentVelocity;
                int mask = PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN;
                if (velocity < 0f && (mPrivateFlags4 & mask) == mask) {
                float frameRate = 0;
                if (velocity < 0f
                        && (mPrivateFlags4 & mask) == mask
                        && mParent instanceof View
                        && ((View) mParent).mFrameContentVelocity <= 0
                ) {
                    // 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.
                    velocity = Float.POSITIVE_INFINITY;
                    frameRate = MAX_FRAME_RATE;
                }
                if (velocity > 0f) {
                    float frameRate = convertVelocityToFrameRate(velocity);
                    if (sToolkitFrameRateVelocityMappingReadOnlyFlagValue) {
                        frameRate = convertVelocityToFrameRate(velocity);
                    }
                    viewRootImpl.votePreferredFrameRate(frameRate, FRAME_RATE_COMPATIBILITY_GTE);
                    return;
                }
            }
            if (!willNotDraw()) {
            if (!willNotDraw() && isDirty()) {
                if (sToolkitMetricsForFrameRateDecisionFlagValue) {
                    float sizePercentage = width * height / mAttachInfo.mDisplayPixelCount;
                    viewRootImpl.recordViewPercentage(sizePercentage);
@@ -33962,7 +33969,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        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)));
        return Math.min(MAX_FRAME_RATE, 60f + (10f * (float) Math.floor(velocityDps / 300f)));
    }
    /**
+2 −0
Original line number Diff line number Diff line
@@ -4227,6 +4227,7 @@ public final class ViewRootImpl implements ViewParent,
                ? mFrameRateCategoryLowCount - 1 : mFrameRateCategoryLowCount;
        mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
        mPreferredFrameRate = -1;
        mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
        mIsFrameRateConflicted = false;
    }
@@ -12496,6 +12497,7 @@ public final class ViewRootImpl implements ViewParent,
    private void setPreferredFrameRateCategory(int preferredFrameRateCategory) {
        if (!shouldSetFrameRateCategory()
                || (mFrameRateCompatibility == FRAME_RATE_COMPATIBILITY_GTE
                && mPreferredFrameRate > 0
                && sToolkitFrameRateVelocityMappingReadOnlyFlagValue)) {
            return;
        }
+116 −32
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.Surface.FRAME_RATE_COMPATIBILITY_GTE;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
@@ -27,18 +26,23 @@ import static android.view.flags.Flags.FLAG_VIEW_VELOCITY_API;
import static android.view.flags.Flags.toolkitFrameRateBySizeReadOnly;
import static android.view.flags.Flags.toolkitFrameRateDefaultNormalReadOnly;
import static android.view.flags.Flags.toolkitFrameRateSmallUsesPercentReadOnly;
import static android.view.flags.Flags.toolkitFrameRateVelocityMappingReadOnly;

import static junit.framework.Assert.assertEquals;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.annotation.NonNull;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.DisplayMetrics;
import android.widget.FrameLayout;

import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
@@ -69,6 +73,8 @@ public class ViewFrameRateTest {
    private Activity mActivity;
    private View mMovingView;
    private ViewRootImpl mViewRoot;
    private CountDownLatch mAfterDrawLatch;
    private Throwable mAfterDrawThrowable;

    @Before
    public void setUp() throws Throwable {
@@ -82,23 +88,34 @@ public class ViewFrameRateTest {
            parent = parent.getParent();
        }
        mViewRoot = (ViewRootImpl) parent;
        mAfterDrawThrowable = null;
    }

    @UiThreadTest
    @Test
    @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API,
            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
    public void frameRateChangesWhenContentMoves() {
    public void frameRateChangesWhenContentMoves() throws Throwable {
        waitForFrameRateCategoryToSettle();
        mActivityRule.runOnUiThread(() -> {
            mMovingView.offsetLeftAndRight(100);
        float frameRate = mViewRoot.getPreferredFrameRate();
            runAfterDraw(() -> {
                if (toolkitFrameRateVelocityMappingReadOnly()) {
                    float frameRate = mViewRoot.getLastPreferredFrameRate();
                    assertTrue(frameRate > 0);
                } else {
                    assertEquals(FRAME_RATE_CATEGORY_HIGH,
                            mViewRoot.getLastPreferredFrameRateCategory());
                }
            });
        });
        waitForAfterDraw();
    }

    @UiThreadTest
    @Test
    @RequiresFlagsEnabled(FLAG_VIEW_VELOCITY_API)
    public void firstFrameNoMovement() {
        assertEquals(0f, mViewRoot.getPreferredFrameRate(), 0f);
        assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
    }

    @Test
@@ -141,9 +158,34 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            mMovingView.setFrameContentVelocity(1f);
            mMovingView.invalidate();
            assertEquals(60f, mViewRoot.getPreferredFrameRate(), 0f);
            assertEquals(FRAME_RATE_COMPATIBILITY_GTE, mViewRoot.getFrameRateCompatibility());
            runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f));
        });
        waitForAfterDraw();
    }

    @Test
    @RequiresFlagsEnabled({FLAG_VIEW_VELOCITY_API,
            FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY,
            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
    public void velocityWithChildMovement() throws Throwable {
        FrameLayout frameLayout = new FrameLayout(mActivity);
        mActivityRule.runOnUiThread(() -> {
            ViewGroup.LayoutParams fullSize = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            mActivity.setContentView(frameLayout, fullSize);
            if (mMovingView.getParent() instanceof ViewGroup) {
                ((ViewGroup) mMovingView.getParent()).removeView(mMovingView);
            }
            frameLayout.addView(mMovingView, fullSize);
        });
        waitForFrameRateCategoryToSettle();
        mActivityRule.runOnUiThread(() -> {
            frameLayout.setFrameContentVelocity(1f);
            mMovingView.offsetTopAndBottom(100);
            runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f));
        });
        waitForAfterDraw();
    }

    @Test
@@ -161,23 +203,9 @@ public class ViewFrameRateTest {
        mActivityRule.runOnUiThread(() -> {
            mMovingView.setFrameContentVelocity(1_000_000_000f);
            mMovingView.invalidate();
            assertEquals(140f, mViewRoot.getPreferredFrameRate(), 0f);
            assertEquals(FRAME_RATE_COMPATIBILITY_GTE, mViewRoot.getFrameRateCompatibility());
        });
    }

    private void waitForFrameRateCategoryToSettle() throws Throwable {
        for (int i = 0; i < 5; i++) {
            final CountDownLatch drawLatch = new CountDownLatch(1);

            // Now that it is small, any invalidation should have a normal category
            mActivityRule.runOnUiThread(() -> {
                mMovingView.invalidate();
                mMovingView.getViewTreeObserver().addOnDrawListener(drawLatch::countDown);
            runAfterDraw(() -> assertEquals(140f, mViewRoot.getLastPreferredFrameRate(), 0f));
        });

            assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
        }
        waitForAfterDraw();
    }

    @Test
@@ -211,8 +239,10 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateBySizeReadOnly()
                    ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(
                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    @Test
@@ -245,8 +275,10 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateBySizeReadOnly()
                    ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(
                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    @Test
@@ -279,8 +311,10 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateBySizeReadOnly()
                    ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(
                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    @Test
@@ -313,8 +347,10 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateDefaultNormalReadOnly()
                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(
                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    @Test
@@ -347,8 +383,10 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateDefaultNormalReadOnly()
                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
            assertEquals(expected, mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(
                    () -> assertEquals(expected, mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    @Test
@@ -367,8 +405,54 @@ public class ViewFrameRateTest {
            mMovingView.invalidate();
            int expected = toolkitFrameRateDefaultNormalReadOnly()
                    ? FRAME_RATE_CATEGORY_NORMAL : FRAME_RATE_CATEGORY_HIGH;
            assertEquals(expected,
                    mViewRoot.getPreferredFrameRateCategory());
            runAfterDraw(() -> assertEquals(expected,
                    mViewRoot.getLastPreferredFrameRateCategory()));
        });
        waitForAfterDraw();
    }

    private void runAfterDraw(@NonNull Runnable runnable) {
        Handler handler = new Handler(Looper.getMainLooper());
        mAfterDrawLatch = new CountDownLatch(1);
        ViewTreeObserver.OnDrawListener listener = new ViewTreeObserver.OnDrawListener() {
            @Override
            public void onDraw() {
                handler.postAtFrontOfQueue(() -> {
                    mMovingView.getViewTreeObserver().removeOnDrawListener(this);
                    try {
                        runnable.run();
                    } catch (Throwable t) {
                        mAfterDrawThrowable = t;
                    }
                    mAfterDrawLatch.countDown();
                });
            }
        };
        mMovingView.getViewTreeObserver().addOnDrawListener(listener);
    }

    private void waitForAfterDraw() throws Throwable {
        assertTrue(mAfterDrawLatch.await(1, TimeUnit.SECONDS));
        if (mAfterDrawThrowable != null) {
            throw mAfterDrawThrowable;
        }
    }

    private void waitForFrameRateCategoryToSettle() throws Throwable {
        for (int i = 0; i < 5 || mViewRoot.getIsFrameRateBoosting(); i++) {
            final CountDownLatch drawLatch = new CountDownLatch(1);

            // Now that it is small, any invalidation should have a normal category
            ViewTreeObserver.OnDrawListener listener = drawLatch::countDown;

            mActivityRule.runOnUiThread(() -> {
                mMovingView.invalidate();
                mMovingView.getViewTreeObserver().addOnDrawListener(listener);
            });

            assertTrue(drawLatch.await(1, TimeUnit.SECONDS));
            mActivityRule.runOnUiThread(
                    () -> mMovingView.getViewTreeObserver().removeOnDrawListener(listener));
        }
    }
}
+336 −189

File changed.

Preview size limit exceeded, changes collapsed.