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

Commit 41edbbf8 authored by Jorim Jaggi's avatar Jorim Jaggi Committed by Automerger Merge Worker
Browse files

Merge "Change hwui jank detection to use deadline & gpu completion (1/2)" into...

Merge "Change hwui jank detection to use deadline & gpu completion (1/2)" into sc-dev am: 21142c13

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13562070

Change-Id: If103b9233588dd21c007f608caac598350ef68bf
parents 63e35f3f 21142c13
Loading
Loading
Loading
Loading
+29 −18
Original line number Diff line number Diff line
@@ -177,8 +177,14 @@ public final class Choreographer {
    private boolean mCallbacksRunning;
    @UnsupportedAppUsage
    private long mLastFrameTimeNanos;
    @UnsupportedAppUsage

    /** DO NOT USE since this will not updated when screen refresh changes. */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
            publicAlternatives = "Use {@link android.view.Display#getRefreshRate} instead")
    @Deprecated
    private long mFrameIntervalNanos;
    private long mLastFrameIntervalNanos;

    private boolean mDebugPrintNextFrameTimeDelta;
    private int mFPSDivisor = 1;
    private DisplayEventReceiver.VsyncEventData mLastVsyncEventData =
@@ -392,7 +398,9 @@ public final class Choreographer {
     * @hide
     */
    public long getFrameIntervalNanos() {
        return mFrameIntervalNanos;
        synchronized (mLock) {
            return mLastFrameIntervalNanos;
        }
    }

    void dump(String prefix, PrintWriter writer) {
@@ -688,6 +696,7 @@ public final class Choreographer {
    void doFrame(long frameTimeNanos, int frame,
            DisplayEventReceiver.VsyncEventData vsyncEventData) {
        final long startNanos;
        final long frameIntervalNanos = vsyncEventData.frameInterval;
        synchronized (mLock) {
            if (!mFrameScheduled) {
                return; // no work to do
@@ -702,17 +711,17 @@ public final class Choreographer {
            long intendedFrameTimeNanos = frameTimeNanos;
            startNanos = System.nanoTime();
            final long jitterNanos = startNanos - frameTimeNanos;
            if (jitterNanos >= mFrameIntervalNanos) {
                final long skippedFrames = jitterNanos / mFrameIntervalNanos;
            if (jitterNanos >= frameIntervalNanos) {
                final long skippedFrames = jitterNanos / frameIntervalNanos;
                if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                    Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                            + "The application may be doing too much work on its main thread.");
                }
                final long lastFrameOffset = jitterNanos % mFrameIntervalNanos;
                final long lastFrameOffset = jitterNanos % frameIntervalNanos;
                if (DEBUG_JANK) {
                    Log.d(TAG, "Missed vsync by " + (jitterNanos * 0.000001f) + " ms "
                            + "which is more than the frame interval of "
                            + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                            + (frameIntervalNanos * 0.000001f) + " ms!  "
                            + "Skipping " + skippedFrames + " frames and setting frame "
                            + "time to " + (lastFrameOffset * 0.000001f) + " ms in the past.");
                }
@@ -730,16 +739,17 @@ public final class Choreographer {

            if (mFPSDivisor > 1) {
                long timeSinceVsync = frameTimeNanos - mLastFrameTimeNanos;
                if (timeSinceVsync < (mFrameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
                if (timeSinceVsync < (frameIntervalNanos * mFPSDivisor) && timeSinceVsync > 0) {
                    scheduleVsyncLocked();
                    return;
                }
            }

            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos, vsyncEventData.id,
                    vsyncEventData.frameDeadline, startNanos);
                    vsyncEventData.frameDeadline, startNanos, vsyncEventData.frameInterval);
            mFrameScheduled = false;
            mLastFrameTimeNanos = frameTimeNanos;
            mLastFrameIntervalNanos = frameIntervalNanos;
            mLastVsyncEventData = vsyncEventData;
        }

@@ -751,16 +761,17 @@ public final class Choreographer {
            AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);

            mFrameInfo.markInputHandlingStart();
            doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos, frameIntervalNanos);

            mFrameInfo.markAnimationsStart();
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos, frameIntervalNanos);
            doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION, frameTimeNanos,
                    frameIntervalNanos);

            mFrameInfo.markPerformTraversalsStart();
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos, frameIntervalNanos);

            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos, frameIntervalNanos);
        } finally {
            AnimationUtils.unlockAnimationClock();
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
@@ -774,7 +785,7 @@ public final class Choreographer {
        }
    }

    void doCallbacks(int callbackType, long frameTimeNanos) {
    void doCallbacks(int callbackType, long frameTimeNanos, long frameIntervalNanos) {
        CallbackRecord callbacks;
        synchronized (mLock) {
            // We use "now" to determine when callbacks become due because it's possible
@@ -799,13 +810,13 @@ public final class Choreographer {
            if (callbackType == Choreographer.CALLBACK_COMMIT) {
                final long jitterNanos = now - frameTimeNanos;
                Trace.traceCounter(Trace.TRACE_TAG_VIEW, "jitterNanos", (int) jitterNanos);
                if (jitterNanos >= 2 * mFrameIntervalNanos) {
                    final long lastFrameOffset = jitterNanos % mFrameIntervalNanos
                            + mFrameIntervalNanos;
                if (jitterNanos >= 2 * frameIntervalNanos) {
                    final long lastFrameOffset = jitterNanos % frameIntervalNanos
                            + frameIntervalNanos;
                    if (DEBUG_JANK) {
                        Log.d(TAG, "Commit callback delayed by " + (jitterNanos * 0.000001f)
                                + " ms which is more than twice the frame interval of "
                                + (mFrameIntervalNanos * 0.000001f) + " ms!  "
                                + (frameIntervalNanos * 0.000001f) + " ms!  "
                                + "Setting frame time to " + (lastFrameOffset * 0.000001f)
                                + " ms in the past.");
                        mDebugPrintNextFrameTimeDelta = true;
+12 −3
Original line number Diff line number Diff line
@@ -146,14 +146,23 @@ public abstract class DisplayEventReceiver {
        // allotted for the frame to be completed.
        public final long frameDeadline;

        VsyncEventData(long id, long frameDeadline) {
        /**
         * The current interval between frames in ns. This will be used to align
         * {@link FrameInfo#VSYNC} to the current vsync in case Choreographer callback was heavily
         * delayed by the app.
         */
        public final long frameInterval;

        VsyncEventData(long id, long frameDeadline, long frameInterval) {
            this.id = id;
            this.frameDeadline = frameDeadline;
            this.frameInterval = frameInterval;
        }

        VsyncEventData() {
            this.id = FrameInfo.INVALID_VSYNC_ID;
            this.frameDeadline = Long.MAX_VALUE;
            this.frameInterval = -1;
        }
    }

@@ -247,9 +256,9 @@ public abstract class DisplayEventReceiver {
    // Called from native code.
    @SuppressWarnings("unused")
    private void dispatchVsync(long timestampNanos, long physicalDisplayId, int frame,
            long frameTimelineVsyncId, long frameDeadline) {
            long frameTimelineVsyncId, long frameDeadline, long frameInterval) {
        onVsync(timestampNanos, physicalDisplayId, frame,
                new VsyncEventData(frameTimelineVsyncId, frameDeadline));
                new VsyncEventData(frameTimelineVsyncId, frameDeadline, frameInterval));
    }

    // Called from native code.
+12 −11
Original line number Diff line number Diff line
@@ -243,18 +243,19 @@ public final class FrameMetrics {
        int DRAW_START = 8;
        int FRAME_DEADLINE = 9;
        int FRAME_START_TIME = 10;
        int SYNC_QUEUED = 11;
        int SYNC_START = 12;
        int ISSUE_DRAW_COMMANDS_START = 13;
        int SWAP_BUFFERS = 14;
        int FRAME_COMPLETED = 15;
        int DEQUEUE_BUFFER_DURATION = 16;
        int QUEUE_BUFFER_DURATION = 17;
        int GPU_COMPLETED = 18;
        int SWAP_BUFFERS_COMPLETED = 19;
        int DISPLAY_PRESENT_TIME = 20;
        int FRAME_INTERVAL = 11;
        int SYNC_QUEUED = 12;
        int SYNC_START = 13;
        int ISSUE_DRAW_COMMANDS_START = 14;
        int SWAP_BUFFERS = 15;
        int FRAME_COMPLETED = 16;
        int DEQUEUE_BUFFER_DURATION = 17;
        int QUEUE_BUFFER_DURATION = 18;
        int GPU_COMPLETED = 19;
        int SWAP_BUFFERS_COMPLETED = 20;
        int DISPLAY_PRESENT_TIME = 21;

        int FRAME_STATS_COUNT = 21; // must always be last and in sync with
        int FRAME_STATS_COUNT = 22; // must always be last and in sync with
                                    // FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h
    }

+2 −2
Original line number Diff line number Diff line
@@ -107,7 +107,7 @@ void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDispla
        ALOGV("receiver %p ~ Invoking vsync handler.", this);
        env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
                            timestamp, displayId.value, count, vsyncEventData.id,
                            vsyncEventData.deadlineTimestamp);
                            vsyncEventData.deadlineTimestamp, vsyncEventData.frameInterval);
        ALOGV("receiver %p ~ Returned from vsync handler.", this);
    }

@@ -239,7 +239,7 @@ int register_android_view_DisplayEventReceiver(JNIEnv* env) {

    gDisplayEventReceiverClassInfo.dispatchVsync =
            GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchVsync",
                             "(JJIJJ)V");
                             "(JJIJJJ)V");
    gDisplayEventReceiverClassInfo.dispatchHotplug = GetMethodIDOrDie(env,
            gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug", "(JJZ)V");
    gDisplayEventReceiverClassInfo.dispatchModeChanged =
+6 −2
Original line number Diff line number Diff line
@@ -90,19 +90,23 @@ public final class FrameInfo {
    // When frame actually started.
    public static final int FRAME_START_TIME = 10;

    // Interval between two consecutive frames
    public static final int FRAME_INTERVAL = 11;

    // Must be the last one
    // This value must be in sync with `UI_THREAD_FRAME_INFO_SIZE` in FrameInfo.h
    private static final int FRAME_INFO_SIZE = FRAME_START_TIME + 1;
    private static final int FRAME_INFO_SIZE = FRAME_INTERVAL + 1;

    /** checkstyle */
    public void setVsync(long intendedVsync, long usedVsync, long frameTimelineVsyncId,
            long frameDeadline, long frameStartTime) {
            long frameDeadline, long frameStartTime, long frameInterval) {
        frameInfo[FRAME_TIMELINE_VSYNC_ID] = frameTimelineVsyncId;
        frameInfo[INTENDED_VSYNC] = intendedVsync;
        frameInfo[VSYNC] = usedVsync;
        frameInfo[FLAGS] = 0;
        frameInfo[FRAME_DEADLINE] = frameDeadline;
        frameInfo[FRAME_START_TIME] = frameStartTime;
        frameInfo[FRAME_INTERVAL] = frameInterval;
    }

    /** checkstyle */
Loading