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

Commit 5814ab8b authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Move JankType to libgui

Such that we can also reference it from interfaces in libgui.

Test: Builds
Bug: 174755489
Change-Id: Iafb10d187ad2442379b08384407f8d53c2ad83fe
parent 62632381
Loading
Loading
Loading
Loading
+41 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2020 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.
 */

#pragma once

namespace android {

// Jank information tracked by SurfaceFlinger for the purpose of funneling to telemetry.
enum JankType {
    // No Jank
    None = 0x0,
    // Jank not related to SurfaceFlinger or the App
    Display = 0x1,
    // SF took too long on the CPU
    SurfaceFlingerDeadlineMissed = 0x2,
    // SF took too long on the GPU
    SurfaceFlingerGpuDeadlineMissed = 0x4,
    // Either App or GPU took too long on the frame
    AppDeadlineMissed = 0x8,
    // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a
    // jank
    // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame.
    PredictionExpired = 0x10,
    // Latching a buffer early might cause an early present of the frame
    SurfaceFlingerEarlyLatch = 0x20,
};

} // namespace android
+29 −29
Original line number Original line Diff line number Diff line
@@ -94,19 +94,19 @@ std::string toString(PredictionState predictionState) {
    }
    }
}
}


std::string toString(TimeStats::JankType jankType) {
std::string toString(JankType jankType) {
    switch (jankType) {
    switch (jankType) {
        case TimeStats::JankType::None:
        case JankType::None:
            return "None";
            return "None";
        case TimeStats::JankType::Display:
        case JankType::Display:
            return "Composer/Display - outside SF and App";
            return "Composer/Display - outside SF and App";
        case TimeStats::JankType::SurfaceFlingerDeadlineMissed:
        case JankType::SurfaceFlingerDeadlineMissed:
            return "SurfaceFlinger Deadline Missed";
            return "SurfaceFlinger Deadline Missed";
        case TimeStats::JankType::AppDeadlineMissed:
        case JankType::AppDeadlineMissed:
            return "App Deadline Missed";
            return "App Deadline Missed";
        case TimeStats::JankType::PredictionExpired:
        case JankType::PredictionExpired:
            return "Prediction Expired";
            return "Prediction Expired";
        case TimeStats::JankType::SurfaceFlingerEarlyLatch:
        case JankType::SurfaceFlingerEarlyLatch:
            return "SurfaceFlinger Early Latch";
            return "SurfaceFlinger Early Latch";
        default:
        default:
            return "Unclassified";
            return "Unclassified";
@@ -154,16 +154,16 @@ FrameTimelineEvent::PresentType presentTypeToProto(int32_t jankMetadata) {
    return FrameTimelineEvent::PRESENT_ON_TIME;
    return FrameTimelineEvent::PRESENT_ON_TIME;
}
}


FrameTimelineEvent::JankType JankTypeToProto(TimeStats::JankType jankType) {
FrameTimelineEvent::JankType JankTypeToProto(JankType jankType) {
    switch (jankType) {
    switch (jankType) {
        case TimeStats::None:
        case JankType::None:
            return FrameTimelineEvent::JANK_NONE;
            return FrameTimelineEvent::JANK_NONE;
        case TimeStats::Display:
        case JankType::Display:
            return FrameTimelineEvent::JANK_DISPLAY_HAL;
            return FrameTimelineEvent::JANK_DISPLAY_HAL;
        case TimeStats::SurfaceFlingerDeadlineMissed:
        case JankType::SurfaceFlingerDeadlineMissed:
            return FrameTimelineEvent::JANK_SF_DEADLINE_MISSED;
            return FrameTimelineEvent::JANK_SF_DEADLINE_MISSED;
        case TimeStats::AppDeadlineMissed:
        case JankType::AppDeadlineMissed:
        case TimeStats::PredictionExpired:
        case JankType::PredictionExpired:
            return FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
            return FrameTimelineEvent::JANK_APP_DEADLINE_MISSED;
        default:
        default:
            return FrameTimelineEvent::JANK_UNKNOWN;
            return FrameTimelineEvent::JANK_UNKNOWN;
@@ -217,7 +217,7 @@ SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::s
        mPredictions(predictions),
        mPredictions(predictions),
        mActuals({0, 0, 0}),
        mActuals({0, 0, 0}),
        mActualQueueTime(0),
        mActualQueueTime(0),
        mJankType(TimeStats::JankType::None),
        mJankType(JankType::None),
        mJankMetadata(0) {}
        mJankMetadata(0) {}


void SurfaceFrame::setPresentState(PresentState state) {
void SurfaceFrame::setPresentState(PresentState state) {
@@ -259,13 +259,13 @@ void SurfaceFrame::setActualPresentTime(nsecs_t presentTime) {
    mActuals.presentTime = presentTime;
    mActuals.presentTime = presentTime;
}
}


void SurfaceFrame::setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata) {
void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    mJankType = jankType;
    mJankType = jankType;
    mJankMetadata = jankMetadata;
    mJankMetadata = jankMetadata;
}
}


TimeStats::JankType SurfaceFrame::getJankType() const {
JankType SurfaceFrame::getJankType() const {
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    return mJankType;
    return mJankType;
}
}
@@ -300,7 +300,7 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t
    std::lock_guard<std::mutex> lock(mMutex);
    std::lock_guard<std::mutex> lock(mMutex);
    StringAppendF(&result, "%s", indent.c_str());
    StringAppendF(&result, "%s", indent.c_str());
    StringAppendF(&result, "Layer - %s", mDebugName.c_str());
    StringAppendF(&result, "Layer - %s", mDebugName.c_str());
    if (mJankType != TimeStats::JankType::None) {
    if (mJankType != JankType::None) {
        // Easily identify a janky Surface Frame in the dump
        // Easily identify a janky Surface Frame in the dump
        StringAppendF(&result, " [*] ");
        StringAppendF(&result, " [*] ");
    }
    }
@@ -454,7 +454,7 @@ void FrameTimeline::flushPendingPresentFences() {
            }
            }
        }
        }
        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
        if (signalTime != Fence::SIGNAL_TIME_INVALID) {
            int32_t totalJankReasons = TimeStats::JankType::None;
            int32_t totalJankReasons = JankType::None;
            auto& displayFrame = pendingPresentFence.second;
            auto& displayFrame = pendingPresentFence.second;
            displayFrame->surfaceFlingerActuals.presentTime = signalTime;
            displayFrame->surfaceFlingerActuals.presentTime = signalTime;


@@ -475,14 +475,14 @@ void FrameTimeline::flushPendingPresentFences() {


                if ((displayFrame->jankMetadata & EarlyFinish) &&
                if ((displayFrame->jankMetadata & EarlyFinish) &&
                    (displayFrame->jankMetadata & EarlyPresent)) {
                    (displayFrame->jankMetadata & EarlyPresent)) {
                    displayFrame->jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
                    displayFrame->jankType = JankType::SurfaceFlingerEarlyLatch;
                } else if ((displayFrame->jankMetadata & LateFinish) &&
                } else if ((displayFrame->jankMetadata & LateFinish) &&
                           (displayFrame->jankMetadata & LatePresent)) {
                           (displayFrame->jankMetadata & LatePresent)) {
                    displayFrame->jankType = TimeStats::JankType::SurfaceFlingerDeadlineMissed;
                    displayFrame->jankType = JankType::SurfaceFlingerDeadlineMissed;
                } else if (displayFrame->jankMetadata & EarlyPresent ||
                } else if (displayFrame->jankMetadata & EarlyPresent ||
                           displayFrame->jankMetadata & LatePresent) {
                           displayFrame->jankMetadata & LatePresent) {
                    // Cases where SF finished early but frame was presented late and vice versa
                    // Cases where SF finished early but frame was presented late and vice versa
                    displayFrame->jankType = TimeStats::JankType::Display;
                    displayFrame->jankType = JankType::Display;
                }
                }
            }
            }


@@ -503,12 +503,12 @@ void FrameTimeline::flushPendingPresentFences() {
                    const auto& predictionState = surfaceFrame->getPredictionState();
                    const auto& predictionState = surfaceFrame->getPredictionState();
                    if (predictionState == PredictionState::Expired) {
                    if (predictionState == PredictionState::Expired) {
                        // Jank analysis cannot be done on apps that don't use predictions
                        // Jank analysis cannot be done on apps that don't use predictions
                        surfaceFrame->setJankInfo(TimeStats::JankType::PredictionExpired, 0);
                        surfaceFrame->setJankInfo(JankType::PredictionExpired, 0);
                    } else if (predictionState == PredictionState::Valid) {
                    } else if (predictionState == PredictionState::Valid) {
                        const auto& actuals = surfaceFrame->getActuals();
                        const auto& actuals = surfaceFrame->getActuals();
                        const auto& predictions = surfaceFrame->getPredictions();
                        const auto& predictions = surfaceFrame->getPredictions();
                        int32_t jankMetadata = 0;
                        int32_t jankMetadata = 0;
                        TimeStats::JankType jankType = TimeStats::JankType::None;
                        JankType jankType = JankType::None;
                        if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
                        if (std::abs(actuals.endTime - predictions.endTime) > kDeadlineThreshold) {
                            jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
                            jankMetadata |= actuals.endTime > predictions.endTime ? LateFinish
                                                                                  : EarlyFinish;
                                                                                  : EarlyFinish;
@@ -520,13 +520,13 @@ void FrameTimeline::flushPendingPresentFences() {
                                    : EarlyPresent;
                                    : EarlyPresent;
                        }
                        }
                        if (jankMetadata & EarlyPresent) {
                        if (jankMetadata & EarlyPresent) {
                            jankType = TimeStats::JankType::SurfaceFlingerEarlyLatch;
                            jankType = JankType::SurfaceFlingerEarlyLatch;
                        } else if (jankMetadata & LatePresent) {
                        } else if (jankMetadata & LatePresent) {
                            if (jankMetadata & EarlyFinish) {
                            if (jankMetadata & EarlyFinish) {
                                // TODO(b/169890654): Classify this properly
                                // TODO(b/169890654): Classify this properly
                                jankType = TimeStats::JankType::Display;
                                jankType = JankType::Display;
                            } else {
                            } else {
                                jankType = TimeStats::JankType::AppDeadlineMissed;
                                jankType = JankType::AppDeadlineMissed;
                            }
                            }
                        }
                        }


@@ -576,7 +576,7 @@ nsecs_t FrameTimeline::findBaseTime(const std::shared_ptr<DisplayFrame>& display
void FrameTimeline::dumpDisplayFrame(std::string& result,
void FrameTimeline::dumpDisplayFrame(std::string& result,
                                     const std::shared_ptr<DisplayFrame>& displayFrame,
                                     const std::shared_ptr<DisplayFrame>& displayFrame,
                                     nsecs_t baseTime) {
                                     nsecs_t baseTime) {
    if (displayFrame->jankType != TimeStats::JankType::None) {
    if (displayFrame->jankType != JankType::None) {
        // Easily identify a janky Display Frame in the dump
        // Easily identify a janky Display Frame in the dump
        StringAppendF(&result, " [*] ");
        StringAppendF(&result, " [*] ");
    }
    }
@@ -610,11 +610,11 @@ void FrameTimeline::dumpJank(std::string& result) {
    nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
    nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : findBaseTime(mDisplayFrames[0]);
    for (size_t i = 0; i < mDisplayFrames.size(); i++) {
    for (size_t i = 0; i < mDisplayFrames.size(); i++) {
        const auto& displayFrame = mDisplayFrames[i];
        const auto& displayFrame = mDisplayFrames[i];
        if (displayFrame->jankType == TimeStats::JankType::None) {
        if (displayFrame->jankType == JankType::None) {
            // Check if any Surface Frame has been janky
            // Check if any Surface Frame has been janky
            bool isJanky = false;
            bool isJanky = false;
            for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
            for (const auto& surfaceFrame : displayFrame->surfaceFrames) {
                if (surfaceFrame->getJankType() != TimeStats::JankType::None) {
                if (surfaceFrame->getJankType() != JankType::None) {
                    isJanky = true;
                    isJanky = true;
                    break;
                    break;
                }
                }
+5 −4
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@


#include <../TimeStats/TimeStats.h>
#include <../TimeStats/TimeStats.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/JankInfo.h>
#include <perfetto/trace/android/frame_timeline_event.pbzero.h>
#include <perfetto/trace/android/frame_timeline_event.pbzero.h>
#include <perfetto/tracing.h>
#include <perfetto/tracing.h>
#include <ui/FenceTime.h>
#include <ui/FenceTime.h>
@@ -208,7 +209,7 @@ public:
    PresentState getPresentState() const override;
    PresentState getPresentState() const override;
    PredictionState getPredictionState() const override { return mPredictionState; };
    PredictionState getPredictionState() const override { return mPredictionState; };
    pid_t getOwnerPid() const override { return mOwnerPid; };
    pid_t getOwnerPid() const override { return mOwnerPid; };
    TimeStats::JankType getJankType() const;
    JankType getJankType() const;
    int64_t getToken() const { return mToken; };
    int64_t getToken() const { return mToken; };
    nsecs_t getBaseTime() const;
    nsecs_t getBaseTime() const;
    uid_t getOwnerUid() const { return mOwnerUid; };
    uid_t getOwnerUid() const { return mOwnerUid; };
@@ -219,7 +220,7 @@ public:
    void setAcquireFenceTime(nsecs_t acquireFenceTime) override;
    void setAcquireFenceTime(nsecs_t acquireFenceTime) override;
    void setPresentState(PresentState state) override;
    void setPresentState(PresentState state) override;
    void setActualPresentTime(nsecs_t presentTime);
    void setActualPresentTime(nsecs_t presentTime);
    void setJankInfo(TimeStats::JankType jankType, int32_t jankMetadata);
    void setJankInfo(JankType jankType, int32_t jankMetadata);


    // All the timestamps are dumped relative to the baseTime
    // All the timestamps are dumped relative to the baseTime
    void dump(std::string& result, const std::string& indent, nsecs_t baseTime);
    void dump(std::string& result, const std::string& indent, nsecs_t baseTime);
@@ -241,7 +242,7 @@ private:
    TimelineItem mActuals GUARDED_BY(mMutex);
    TimelineItem mActuals GUARDED_BY(mMutex);
    nsecs_t mActualQueueTime GUARDED_BY(mMutex);
    nsecs_t mActualQueueTime GUARDED_BY(mMutex);
    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
    TimeStats::JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank
    JankType mJankType GUARDED_BY(mMutex); // Enum for the type of jank
    int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank
    int32_t mJankMetadata GUARDED_BY(mMutex); // Additional details about the jank
};
};


@@ -301,7 +302,7 @@ private:
        std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;
        std::vector<std::unique_ptr<SurfaceFrame>> surfaceFrames;


        PredictionState predictionState = PredictionState::None;
        PredictionState predictionState = PredictionState::None;
        TimeStats::JankType jankType = TimeStats::JankType::None; // Enum for the type of jank
        JankType jankType = JankType::None; // Enum for the type of jank
        int32_t jankMetadata = 0x0; // Additional details about the jank
        int32_t jankMetadata = 0x0; // Additional details about the jank
    };
    };


+7 −7
Original line number Original line Diff line number Diff line
@@ -681,21 +681,21 @@ static void updateJankPayload(T& t, int32_t reasons) {
    t.jankPayload.totalFrames++;
    t.jankPayload.totalFrames++;


    static const constexpr int32_t kValidJankyReason =
    static const constexpr int32_t kValidJankyReason =
            TimeStats::JankType::SurfaceFlingerDeadlineMissed |
            JankType::SurfaceFlingerDeadlineMissed |
            TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed |
            JankType::SurfaceFlingerGpuDeadlineMissed |
            TimeStats::JankType::AppDeadlineMissed | TimeStats::JankType::Display;
            JankType::AppDeadlineMissed | JankType::Display;
    if (reasons & kValidJankyReason) {
    if (reasons & kValidJankyReason) {
        t.jankPayload.totalJankyFrames++;
        t.jankPayload.totalJankyFrames++;
        if ((reasons & TimeStats::JankType::SurfaceFlingerDeadlineMissed) != 0) {
        if ((reasons & JankType::SurfaceFlingerDeadlineMissed) != 0) {
            t.jankPayload.totalSFLongCpu++;
            t.jankPayload.totalSFLongCpu++;
        }
        }
        if ((reasons & TimeStats::JankType::SurfaceFlingerGpuDeadlineMissed) != 0) {
        if ((reasons & JankType::SurfaceFlingerGpuDeadlineMissed) != 0) {
            t.jankPayload.totalSFLongGpu++;
            t.jankPayload.totalSFLongGpu++;
        }
        }
        if ((reasons & TimeStats::JankType::Display) != 0) {
        if ((reasons & JankType::Display) != 0) {
            t.jankPayload.totalSFUnattributed++;
            t.jankPayload.totalSFUnattributed++;
        }
        }
        if ((reasons & TimeStats::JankType::AppDeadlineMissed) != 0) {
        if ((reasons & JankType::AppDeadlineMissed) != 0) {
            t.jankPayload.totalAppUnattributed++;
            t.jankPayload.totalAppUnattributed++;
        }
        }
    }
    }
+1 −20
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@
#include <statslog.h>
#include <statslog.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
#include <gui/JankInfo.h>
#include <ui/FenceTime.h>
#include <ui/FenceTime.h>
#include <utils/String16.h>
#include <utils/String16.h>
#include <utils/Vector.h>
#include <utils/Vector.h>
@@ -110,26 +111,6 @@ public:
    virtual void setPresentFence(int32_t layerId, uint64_t frameNumber,
    virtual void setPresentFence(int32_t layerId, uint64_t frameNumber,
                                 const std::shared_ptr<FenceTime>& presentFence) = 0;
                                 const std::shared_ptr<FenceTime>& presentFence) = 0;


    // Subset of jank metadata tracked by FrameTimeline for the purpose of funneling to telemetry.
    enum JankType {
        // No Jank
        None = 0x0,
        // Jank not related to SurfaceFlinger or the App
        Display = 0x1,
        // SF took too long on the CPU
        SurfaceFlingerDeadlineMissed = 0x2,
        // SF took too long on the GPU
        SurfaceFlingerGpuDeadlineMissed = 0x4,
        // Either App or GPU took too long on the frame
        AppDeadlineMissed = 0x8,
        // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a
        // jank
        // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame.
        PredictionExpired = 0x10,
        // Latching a buffer early might cause an early present of the frame
        SurfaceFlingerEarlyLatch = 0x20,
    };

    // Increments janky frames, tracked globally. Because FrameTimeline is the infrastructure
    // Increments janky frames, tracked globally. Because FrameTimeline is the infrastructure
    // responsible for computing jank in the system, this is expected to be called from
    // responsible for computing jank in the system, this is expected to be called from
    // FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there are no
    // FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there are no
Loading