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

Commit bf9b30b5 authored by Pascal Mütschard's avatar Pascal Mütschard Committed by Android (Google) Code Review
Browse files

Merge "Include the display refresh rate in the jank data." into main

parents b7036071 9410c197
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -436,13 +436,16 @@ public final class SurfaceControl implements Parcelable {
        // Jank due to unknown reasons.
        public static final int UNKNOWN = 0x80;

        public JankData(long frameVsyncId, @JankType int jankType) {
        public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs) {
            this.frameVsyncId = frameVsyncId;
            this.jankType = jankType;
            this.frameIntervalNs = frameIntervalNs;

        }

        public final long frameVsyncId;
        public final @JankType int jankType;
        public final long frameIntervalNs;
    }

    /**
+86 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.jank;

import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__UNKNOWN_REFRESH_RATE;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__VARIABLE_REFRESH_RATE;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_30_HZ;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_60_HZ;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_90_HZ;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_120_HZ;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_240_HZ;

import android.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Display refresh rate related functionality.
 * @hide
 */
public class DisplayRefreshRate {
    public static final int UNKNOWN_REFRESH_RATE =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__UNKNOWN_REFRESH_RATE;
    public static final int VARIABLE_REFRESH_RATE =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__VARIABLE_REFRESH_RATE;
    public static final int REFRESH_RATE_30_HZ =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_30_HZ;
    public static final int REFRESH_RATE_60_HZ =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_60_HZ;
    public static final int REFRESH_RATE_90_HZ =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_90_HZ;
    public static final int REFRESH_RATE_120_HZ =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_120_HZ;
    public static final int REFRESH_RATE_240_HZ =
            UIINTERACTION_FRAME_INFO_REPORTED__DISPLAY_REFRESH_RATE__RR_240_HZ;

    /** @hide */
    @IntDef({
        UNKNOWN_REFRESH_RATE,
        VARIABLE_REFRESH_RATE,
        REFRESH_RATE_30_HZ,
        REFRESH_RATE_60_HZ,
        REFRESH_RATE_90_HZ,
        REFRESH_RATE_120_HZ,
        REFRESH_RATE_240_HZ,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface RefreshRate {
    }

    private DisplayRefreshRate() {
    }

    /**
     * Computes the display refresh rate based off the frame interval.
     */
    @RefreshRate
    public static int getRefreshRate(long frameIntervalNs) {
        long rate = Math.round(1e9 / frameIntervalNs);
        if (rate < 50) {
            return REFRESH_RATE_30_HZ;
        } else if (rate < 80) {
            return REFRESH_RATE_60_HZ;
        } else if (rate < 110) {
            return REFRESH_RATE_90_HZ;
        } else if (rate < 180) {
            return REFRESH_RATE_120_HZ;
        } else {
            return REFRESH_RATE_240_HZ;
        }
    }
}
+23 −8
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_GPU_DEADL
import static android.view.SurfaceControl.JankData.PREDICTION_ERROR;
import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;

import static com.android.internal.jank.DisplayRefreshRate.UNKNOWN_REFRESH_RATE;
import static com.android.internal.jank.DisplayRefreshRate.VARIABLE_REFRESH_RATE;
import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_CANCEL;
import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_END;
import static com.android.internal.jank.InteractionJankMonitor.EXECUTOR_TASK_TIMEOUT;
@@ -49,6 +51,7 @@ import android.view.ViewRootImpl;
import android.view.WindowCallbacks;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.DisplayRefreshRate.RefreshRate;
import com.android.internal.jank.InteractionJankMonitor.Configuration;
import com.android.internal.jank.InteractionJankMonitor.Session;
import com.android.internal.util.FrameworkStatsLog;
@@ -132,26 +135,30 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
        boolean hwuiCallbackFired;
        boolean surfaceControlCallbackFired;
        @JankType int jankType;
        @RefreshRate int refreshRate;

        static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos,
                boolean isFirstFrame) {
            return new JankInfo(frameVsyncId, true, false, JANK_NONE, totalDurationNanos,
                    isFirstFrame);
            return new JankInfo(frameVsyncId, true, false, JANK_NONE, UNKNOWN_REFRESH_RATE,
                    totalDurationNanos, isFirstFrame);
        }

        static JankInfo createFromSurfaceControlCallback(long frameVsyncId,
                @JankType int jankType) {
            return new JankInfo(frameVsyncId, false, true, jankType, 0, false /* isFirstFrame */);
                @JankType int jankType, @RefreshRate int refreshRate) {
            return new JankInfo(
                    frameVsyncId, false, true, jankType, refreshRate, 0, false /* isFirstFrame */);
        }

        private JankInfo(long frameVsyncId, boolean hwuiCallbackFired,
                boolean surfaceControlCallbackFired, @JankType int jankType,
                @RefreshRate int refreshRate,
                long totalDurationNanos, boolean isFirstFrame) {
            this.frameVsyncId = frameVsyncId;
            this.hwuiCallbackFired = hwuiCallbackFired;
            this.surfaceControlCallbackFired = surfaceControlCallbackFired;
            this.totalDurationNanos = totalDurationNanos;
            this.jankType = jankType;
            this.refreshRate = refreshRate;
            this.totalDurationNanos = totalDurationNanos;
            this.isFirstFrame = isFirstFrame;
        }

@@ -468,14 +475,16 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
                if (!isInRange(jankStat.frameVsyncId)) {
                    continue;
                }
                int refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
                JankInfo info = findJankInfo(jankStat.frameVsyncId);
                if (info != null) {
                    info.surfaceControlCallbackFired = true;
                    info.jankType = jankStat.jankType;
                    info.refreshRate = refreshRate;
                } else {
                    mJankInfos.put((int) jankStat.frameVsyncId,
                            JankInfo.createFromSurfaceControlCallback(
                                    jankStat.frameVsyncId, jankStat.jankType));
                                    jankStat.frameVsyncId, jankStat.jankType, refreshRate));
                }
            }
            processJankInfos();
@@ -592,6 +601,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
        int missedSfFramesCount = 0;
        int maxSuccessiveMissedFramesCount = 0;
        int successiveMissedFramesCount = 0;
        @RefreshRate int refreshRate = UNKNOWN_REFRESH_RATE;

        for (int i = 0; i < mJankInfos.size(); i++) {
            JankInfo info = mJankInfos.valueAt(i);
@@ -627,6 +637,10 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
                            maxSuccessiveMissedFramesCount, successiveMissedFramesCount);
                    successiveMissedFramesCount = 0;
                }
                if (info.refreshRate != UNKNOWN_REFRESH_RATE && info.refreshRate != refreshRate) {
                    refreshRate = (refreshRate == UNKNOWN_REFRESH_RATE)
                            ? info.refreshRate : VARIABLE_REFRESH_RATE;
                }
                // TODO (b/174755489): Early latch currently gets fired way too often, so we have
                // to ignore it for now.
                if (!mSurfaceOnly && !info.hwuiCallbackFired) {
@@ -669,6 +683,7 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
            mStatsLog.write(
                    FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
                    mDisplayId,
                    refreshRate,
                    mSession.getStatsdInteractionType(),
                    totalFramesCount,
                    missedFramesCount,
@@ -866,10 +881,10 @@ public class FrameTracker extends SurfaceControl.OnJankDataListener
        }

        /** {@see FrameworkStatsLog#write) */
        public void write(int code, int displayId,
        public void write(int code, int displayId, @RefreshRate int refreshRate,
                int arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7) {
            FrameworkStatsLog.write(code, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
                    mDisplayResolutionTracker.getResolution(displayId));
                    mDisplayResolutionTracker.getResolution(displayId), refreshRate);
        }
    }

+4 −4
Original line number Diff line number Diff line
@@ -1951,8 +1951,9 @@ public:
        jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
                gJankDataClassInfo.clazz, nullptr);
        for (size_t i = 0; i < jankData.size(); i++) {
            jobject jJankData = env->NewObject(gJankDataClassInfo.clazz,
                    gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType);
            jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
                                               jankData[i].frameVsyncId, jankData[i].jankType,
                                               jankData[i].frameIntervalNs);
            env->SetObjectArrayElement(jJankDataArray, i, jJankData);
            env->DeleteLocalRef(jJankData);
        }
@@ -2523,8 +2524,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    jclass jankDataClazz =
                FindClassOrDie(env, "android/view/SurfaceControl$JankData");
    gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz);
    gJankDataClassInfo.ctor =
            GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JI)V");
    gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJ)V");
    jclass onJankDataListenerClazz =
            FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener");
    gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz);
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.jank;

import static com.android.internal.jank.DisplayRefreshRate.REFRESH_RATE_120_HZ;
import static com.android.internal.jank.DisplayRefreshRate.REFRESH_RATE_240_HZ;
import static com.android.internal.jank.DisplayRefreshRate.REFRESH_RATE_30_HZ;
import static com.android.internal.jank.DisplayRefreshRate.REFRESH_RATE_60_HZ;
import static com.android.internal.jank.DisplayRefreshRate.REFRESH_RATE_90_HZ;
import static com.android.internal.jank.DisplayRefreshRate.getRefreshRate;

import static com.google.common.truth.Truth.assertThat;

import androidx.test.filters.SmallTest;

import org.junit.Test;

@SmallTest
public class DisplayRefreshRateTest {
    @Test
    public void testRefreshRateMapping() {
        assertThat(getRefreshRate((long) 1e9 / 30)).isEqualTo(REFRESH_RATE_30_HZ);
        assertThat(getRefreshRate((long) 1e9 / 60)).isEqualTo(REFRESH_RATE_60_HZ);
        assertThat(getRefreshRate((long) 1e9 / 90)).isEqualTo(REFRESH_RATE_90_HZ);
        assertThat(getRefreshRate((long) 1e9 / 120)).isEqualTo(REFRESH_RATE_120_HZ);
        assertThat(getRefreshRate((long) 1e9 / 240)).isEqualTo(REFRESH_RATE_240_HZ);
    }
}
Loading