Loading services/surfaceflinger/BufferLayer.cpp +37 −2 Original line number Original line Diff line number Diff line Loading @@ -329,6 +329,37 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { mRefreshPending = false; mRefreshPending = false; return hasReadyFrame(); return hasReadyFrame(); } } namespace { TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) { using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility; using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness; const auto frameRateCompatibility = [frameRate] { switch (frameRate.type) { case Layer::FrameRateCompatibility::Default: return FrameRateCompatibility::Default; case Layer::FrameRateCompatibility::ExactOrMultiple: return FrameRateCompatibility::ExactOrMultiple; default: return FrameRateCompatibility::Undefined; } }(); const auto seamlessness = [frameRate] { switch (frameRate.seamlessness) { case scheduler::Seamlessness::OnlySeamless: return Seamlessness::ShouldBeSeamless; case scheduler::Seamlessness::SeamedAndSeamless: return Seamlessness::NotRequired; default: return Seamlessness::Undefined; } }(); return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(), .frameRateCompatibility = frameRateCompatibility, .seamlessness = seamlessness}; } } // namespace bool BufferLayer::onPostComposition(const DisplayDevice* display, bool BufferLayer::onPostComposition(const DisplayDevice* display, const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& glDoneFence, Loading Loading @@ -381,7 +412,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); if (presentFence->isValid()) { if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, refreshRate, renderRate); refreshRate, renderRate, frameRateToSetFrameRateVotePayload( mDrawingState.frameRate)); mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); Loading @@ -393,7 +426,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, // timestamp instead. // timestamp instead. const nsecs_t actualPresentTime = display->getRefreshTimestamp(); const nsecs_t actualPresentTime = display->getRefreshTimestamp(); mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, refreshRate, renderRate); refreshRate, renderRate, frameRateToSetFrameRateVotePayload( mDrawingState.frameRate)); mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, actualPresentTime, actualPresentTime, FrameTracer::FrameEvent::PRESENT_FENCE); FrameTracer::FrameEvent::PRESENT_FENCE); Loading services/surfaceflinger/TimeStats/TimeStats.cpp +23 −10 Original line number Original line Diff line number Diff line Loading @@ -89,12 +89,15 @@ std::string histogramToProtoByteString(const std::unordered_map<int32_t, int32_t return byteString; return byteString; } } std::string frameRateVoteToProtoByteString(float refreshRate, int frameRateCompatibility, std::string frameRateVoteToProtoByteString( int seamlessness) { float refreshRate, TimeStats::SetFrameRateVote::FrameRateCompatibility frameRateCompatibility, TimeStats::SetFrameRateVote::Seamlessness seamlessness) { util::ProtoOutputStream proto; util::ProtoOutputStream proto; proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate); proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate); proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */, frameRateCompatibility); proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */, proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, seamlessness); static_cast<int>(frameRateCompatibility)); proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, static_cast<int>(seamlessness)); std::string byteString; std::string byteString; proto.serializeToString(&byteString); proto.serializeToString(&byteString); Loading Loading @@ -229,7 +232,10 @@ AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventLis mStatsDelegate->statsEventWriteInt32( mStatsDelegate->statsEventWriteInt32( event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket std::string frameRateVoteBytes = frameRateVoteToProtoByteString(0.0, 0, 0); std::string frameRateVoteBytes = frameRateVoteToProtoByteString(layer->setFrameRateVote.frameRate, layer->setFrameRateVote.frameRateCompatibility, layer->setFrameRateVote.seamlessness); mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(), mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(), frameRateVoteBytes.size()); // set_frame_rate_vote frameRateVoteBytes.size()); // set_frame_rate_vote std::string appDeadlineMissedBytes = std::string appDeadlineMissedBytes = Loading Loading @@ -468,8 +474,10 @@ static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) { } } void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, std::optional<Fps> renderRate) { std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { ATRACE_CALL(); ATRACE_CALL(); ALOGV("[%d]-flushAvailableRecordsToStatsLocked", layerId); LayerRecord& layerRecord = mTimeStatsTracker[layerId]; LayerRecord& layerRecord = mTimeStatsTracker[layerId]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; Loading Loading @@ -501,6 +509,9 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR displayStats.stats[layerKey].uid = uid; displayStats.stats[layerKey].uid = uid; displayStats.stats[layerKey].layerName = layerName; displayStats.stats[layerKey].layerName = layerName; } } if (frameRateVote.frameRate > 0.0f) { displayStats.stats[layerKey].setFrameRateVote = frameRateVote; } TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey]; TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey]; timeStatsLayer.totalFrames++; timeStatsLayer.totalFrames++; timeStatsLayer.droppedFrames += layerRecord.droppedFrames; timeStatsLayer.droppedFrames += layerRecord.droppedFrames; Loading Loading @@ -724,7 +735,8 @@ void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, } } void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) { Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { if (!mEnabled.load()) return; if (!mEnabled.load()) return; ATRACE_CALL(); ATRACE_CALL(); Loading @@ -743,12 +755,13 @@ void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t pr layerRecord.waitData++; layerRecord.waitData++; } } flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate); flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote); } } void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) { Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { if (!mEnabled.load()) return; if (!mEnabled.load()) return; ATRACE_CALL(); ATRACE_CALL(); Loading @@ -768,7 +781,7 @@ void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, layerRecord.waitData++; layerRecord.waitData++; } } flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate); flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote); } } static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL | static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL | Loading services/surfaceflinger/TimeStats/TimeStats.h +11 −5 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,8 @@ namespace android { class TimeStats { class TimeStats { public: public: using SetFrameRateVote = TimeStatsHelper::SetFrameRateVote; virtual ~TimeStats() = default; virtual ~TimeStats() = default; // Called once boot has been finished to perform additional capabilities, // Called once boot has been finished to perform additional capabilities, Loading Loading @@ -110,10 +112,12 @@ public: // SetPresent{Time, Fence} are not expected to be called in the critical // SetPresent{Time, Fence} are not expected to be called in the critical // rendering path, as they flush prior fences if those fences have fired. // rendering path, as they flush prior fences if those fences have fired. virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) = 0; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) = 0; virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) = 0; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) = 0; // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName} // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName} // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the Loading Loading @@ -307,10 +311,11 @@ public: void setAcquireFence(int32_t layerId, uint64_t frameNumber, void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& acquireFence) override; const std::shared_ptr<FenceTime>& acquireFence) override; void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) override; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) override; void setPresentFence(int32_t layerId, uint64_t frameNumber, void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) override; std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) override; void incrementJankyFrames(const JankyFramesInfo& info) override; void incrementJankyFrames(const JankyFramesInfo& info) override; // Clean up the layer record // Clean up the layer record Loading @@ -334,7 +339,8 @@ private: AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data); AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data); bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, std::optional<Fps> renderRate); std::optional<Fps> renderRate, SetFrameRateVote frameRateVote); void flushPowerTimeLocked(); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); void flushAvailableGlobalRecordsToStatsLocked(); bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName); bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName); Loading services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp +33 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,37 @@ std::string TimeStatsHelper::JankPayload::toString() const { return result; return result; } } std::string TimeStatsHelper::SetFrameRateVote::toString(FrameRateCompatibility compatibility) { switch (compatibility) { case FrameRateCompatibility::Undefined: return "Undefined"; case FrameRateCompatibility::Default: return "Default"; case FrameRateCompatibility::ExactOrMultiple: return "ExactOrMultiple"; } } std::string TimeStatsHelper::SetFrameRateVote::toString(Seamlessness seamlessness) { switch (seamlessness) { case Seamlessness::Undefined: return "Undefined"; case Seamlessness::ShouldBeSeamless: return "ShouldBeSeamless"; case Seamlessness::NotRequired: return "NotRequired"; } } std::string TimeStatsHelper::SetFrameRateVote::toString() const { std::string result; StringAppendF(&result, "frameRate = %.2f\n", frameRate); StringAppendF(&result, "frameRateCompatibility = %s\n", toString(frameRateCompatibility).c_str()); StringAppendF(&result, "seamlessness = %s\n", toString(seamlessness).c_str()); return result; } std::string TimeStatsHelper::TimeStatsLayer::toString() const { std::string TimeStatsHelper::TimeStatsLayer::toString() const { std::string result = "\n"; std::string result = "\n"; StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket); StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket); Loading @@ -104,6 +135,8 @@ std::string TimeStatsHelper::TimeStatsLayer::toString() const { StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames); StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames); result.append("Jank payload for this layer:\n"); result.append("Jank payload for this layer:\n"); result.append(jankPayload.toString()); result.append(jankPayload.toString()); result.append("SetFrateRate vote for this layer:\n"); result.append(setFrameRateVote.toString()); const auto iter = deltas.find("present2present"); const auto iter = deltas.find("present2present"); if (iter != deltas.end()) { if (iter != deltas.end()) { const float averageTime = iter->second.averageTime(); const float averageTime = iter->second.averageTime(); Loading services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +23 −0 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,28 @@ public: std::string toString() const; std::string toString() const; }; }; struct SetFrameRateVote { float frameRate = 0; // Needs to be in sync with atoms.proto enum class FrameRateCompatibility { Undefined = 0, Default = 1, ExactOrMultiple = 2, } frameRateCompatibility = FrameRateCompatibility::Undefined; // Needs to be in sync with atoms.proto enum class Seamlessness { Undefined = 0, ShouldBeSeamless = 1, NotRequired = 2, } seamlessness = Seamlessness::Undefined; static std::string toString(FrameRateCompatibility); static std::string toString(Seamlessness); std::string toString() const; }; class TimeStatsLayer { class TimeStatsLayer { public: public: uid_t uid; uid_t uid; Loading @@ -67,6 +89,7 @@ public: int32_t lateAcquireFrames = 0; int32_t lateAcquireFrames = 0; int32_t badDesiredPresentFrames = 0; int32_t badDesiredPresentFrames = 0; JankPayload jankPayload; JankPayload jankPayload; SetFrameRateVote setFrameRateVote; std::unordered_map<std::string, Histogram> deltas; std::unordered_map<std::string, Histogram> deltas; std::string toString() const; std::string toString() const; Loading Loading
services/surfaceflinger/BufferLayer.cpp +37 −2 Original line number Original line Diff line number Diff line Loading @@ -329,6 +329,37 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { mRefreshPending = false; mRefreshPending = false; return hasReadyFrame(); return hasReadyFrame(); } } namespace { TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) { using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility; using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness; const auto frameRateCompatibility = [frameRate] { switch (frameRate.type) { case Layer::FrameRateCompatibility::Default: return FrameRateCompatibility::Default; case Layer::FrameRateCompatibility::ExactOrMultiple: return FrameRateCompatibility::ExactOrMultiple; default: return FrameRateCompatibility::Undefined; } }(); const auto seamlessness = [frameRate] { switch (frameRate.seamlessness) { case scheduler::Seamlessness::OnlySeamless: return Seamlessness::ShouldBeSeamless; case scheduler::Seamlessness::SeamedAndSeamless: return Seamlessness::NotRequired; default: return Seamlessness::Undefined; } }(); return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(), .frameRateCompatibility = frameRateCompatibility, .seamlessness = seamlessness}; } } // namespace bool BufferLayer::onPostComposition(const DisplayDevice* display, bool BufferLayer::onPostComposition(const DisplayDevice* display, const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& glDoneFence, Loading Loading @@ -381,7 +412,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid()); if (presentFence->isValid()) { if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence, refreshRate, renderRate); refreshRate, renderRate, frameRateToSetFrameRateVotePayload( mDrawingState.frameRate)); mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence)); Loading @@ -393,7 +426,9 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, // timestamp instead. // timestamp instead. const nsecs_t actualPresentTime = display->getRefreshTimestamp(); const nsecs_t actualPresentTime = display->getRefreshTimestamp(); mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime, refreshRate, renderRate); refreshRate, renderRate, frameRateToSetFrameRateVotePayload( mDrawingState.frameRate)); mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, actualPresentTime, actualPresentTime, FrameTracer::FrameEvent::PRESENT_FENCE); FrameTracer::FrameEvent::PRESENT_FENCE); Loading
services/surfaceflinger/TimeStats/TimeStats.cpp +23 −10 Original line number Original line Diff line number Diff line Loading @@ -89,12 +89,15 @@ std::string histogramToProtoByteString(const std::unordered_map<int32_t, int32_t return byteString; return byteString; } } std::string frameRateVoteToProtoByteString(float refreshRate, int frameRateCompatibility, std::string frameRateVoteToProtoByteString( int seamlessness) { float refreshRate, TimeStats::SetFrameRateVote::FrameRateCompatibility frameRateCompatibility, TimeStats::SetFrameRateVote::Seamlessness seamlessness) { util::ProtoOutputStream proto; util::ProtoOutputStream proto; proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate); proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate); proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */, frameRateCompatibility); proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */, proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, seamlessness); static_cast<int>(frameRateCompatibility)); proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, static_cast<int>(seamlessness)); std::string byteString; std::string byteString; proto.serializeToString(&byteString); proto.serializeToString(&byteString); Loading Loading @@ -229,7 +232,10 @@ AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventLis mStatsDelegate->statsEventWriteInt32( mStatsDelegate->statsEventWriteInt32( event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket std::string frameRateVoteBytes = frameRateVoteToProtoByteString(0.0, 0, 0); std::string frameRateVoteBytes = frameRateVoteToProtoByteString(layer->setFrameRateVote.frameRate, layer->setFrameRateVote.frameRateCompatibility, layer->setFrameRateVote.seamlessness); mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(), mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(), frameRateVoteBytes.size()); // set_frame_rate_vote frameRateVoteBytes.size()); // set_frame_rate_vote std::string appDeadlineMissedBytes = std::string appDeadlineMissedBytes = Loading Loading @@ -468,8 +474,10 @@ static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) { } } void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, std::optional<Fps> renderRate) { std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { ATRACE_CALL(); ATRACE_CALL(); ALOGV("[%d]-flushAvailableRecordsToStatsLocked", layerId); LayerRecord& layerRecord = mTimeStatsTracker[layerId]; LayerRecord& layerRecord = mTimeStatsTracker[layerId]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; Loading Loading @@ -501,6 +509,9 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR displayStats.stats[layerKey].uid = uid; displayStats.stats[layerKey].uid = uid; displayStats.stats[layerKey].layerName = layerName; displayStats.stats[layerKey].layerName = layerName; } } if (frameRateVote.frameRate > 0.0f) { displayStats.stats[layerKey].setFrameRateVote = frameRateVote; } TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey]; TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey]; timeStatsLayer.totalFrames++; timeStatsLayer.totalFrames++; timeStatsLayer.droppedFrames += layerRecord.droppedFrames; timeStatsLayer.droppedFrames += layerRecord.droppedFrames; Loading Loading @@ -724,7 +735,8 @@ void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, } } void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) { Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { if (!mEnabled.load()) return; if (!mEnabled.load()) return; ATRACE_CALL(); ATRACE_CALL(); Loading @@ -743,12 +755,13 @@ void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t pr layerRecord.waitData++; layerRecord.waitData++; } } flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate); flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote); } } void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) { Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) { if (!mEnabled.load()) return; if (!mEnabled.load()) return; ATRACE_CALL(); ATRACE_CALL(); Loading @@ -768,7 +781,7 @@ void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, layerRecord.waitData++; layerRecord.waitData++; } } flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate); flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote); } } static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL | static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL | Loading
services/surfaceflinger/TimeStats/TimeStats.h +11 −5 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,8 @@ namespace android { class TimeStats { class TimeStats { public: public: using SetFrameRateVote = TimeStatsHelper::SetFrameRateVote; virtual ~TimeStats() = default; virtual ~TimeStats() = default; // Called once boot has been finished to perform additional capabilities, // Called once boot has been finished to perform additional capabilities, Loading Loading @@ -110,10 +112,12 @@ public: // SetPresent{Time, Fence} are not expected to be called in the critical // SetPresent{Time, Fence} are not expected to be called in the critical // rendering path, as they flush prior fences if those fences have fired. // rendering path, as they flush prior fences if those fences have fired. virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) = 0; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) = 0; virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) = 0; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) = 0; // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName} // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName} // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the Loading Loading @@ -307,10 +311,11 @@ public: void setAcquireFence(int32_t layerId, uint64_t frameNumber, void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& acquireFence) override; const std::shared_ptr<FenceTime>& acquireFence) override; void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime, Fps displayRefreshRate, std::optional<Fps> renderRate) override; Fps displayRefreshRate, std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) override; void setPresentFence(int32_t layerId, uint64_t frameNumber, void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate, std::optional<Fps> renderRate) override; std::optional<Fps> renderRate, SetFrameRateVote frameRateVote) override; void incrementJankyFrames(const JankyFramesInfo& info) override; void incrementJankyFrames(const JankyFramesInfo& info) override; // Clean up the layer record // Clean up the layer record Loading @@ -334,7 +339,8 @@ private: AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data); AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data); bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate, std::optional<Fps> renderRate); std::optional<Fps> renderRate, SetFrameRateVote frameRateVote); void flushPowerTimeLocked(); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); void flushAvailableGlobalRecordsToStatsLocked(); bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName); bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName); Loading
services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp +33 −0 Original line number Original line Diff line number Diff line Loading @@ -91,6 +91,37 @@ std::string TimeStatsHelper::JankPayload::toString() const { return result; return result; } } std::string TimeStatsHelper::SetFrameRateVote::toString(FrameRateCompatibility compatibility) { switch (compatibility) { case FrameRateCompatibility::Undefined: return "Undefined"; case FrameRateCompatibility::Default: return "Default"; case FrameRateCompatibility::ExactOrMultiple: return "ExactOrMultiple"; } } std::string TimeStatsHelper::SetFrameRateVote::toString(Seamlessness seamlessness) { switch (seamlessness) { case Seamlessness::Undefined: return "Undefined"; case Seamlessness::ShouldBeSeamless: return "ShouldBeSeamless"; case Seamlessness::NotRequired: return "NotRequired"; } } std::string TimeStatsHelper::SetFrameRateVote::toString() const { std::string result; StringAppendF(&result, "frameRate = %.2f\n", frameRate); StringAppendF(&result, "frameRateCompatibility = %s\n", toString(frameRateCompatibility).c_str()); StringAppendF(&result, "seamlessness = %s\n", toString(seamlessness).c_str()); return result; } std::string TimeStatsHelper::TimeStatsLayer::toString() const { std::string TimeStatsHelper::TimeStatsLayer::toString() const { std::string result = "\n"; std::string result = "\n"; StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket); StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket); Loading @@ -104,6 +135,8 @@ std::string TimeStatsHelper::TimeStatsLayer::toString() const { StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames); StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames); result.append("Jank payload for this layer:\n"); result.append("Jank payload for this layer:\n"); result.append(jankPayload.toString()); result.append(jankPayload.toString()); result.append("SetFrateRate vote for this layer:\n"); result.append(setFrameRateVote.toString()); const auto iter = deltas.find("present2present"); const auto iter = deltas.find("present2present"); if (iter != deltas.end()) { if (iter != deltas.end()) { const float averageTime = iter->second.averageTime(); const float averageTime = iter->second.averageTime(); Loading
services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +23 −0 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,28 @@ public: std::string toString() const; std::string toString() const; }; }; struct SetFrameRateVote { float frameRate = 0; // Needs to be in sync with atoms.proto enum class FrameRateCompatibility { Undefined = 0, Default = 1, ExactOrMultiple = 2, } frameRateCompatibility = FrameRateCompatibility::Undefined; // Needs to be in sync with atoms.proto enum class Seamlessness { Undefined = 0, ShouldBeSeamless = 1, NotRequired = 2, } seamlessness = Seamlessness::Undefined; static std::string toString(FrameRateCompatibility); static std::string toString(Seamlessness); std::string toString() const; }; class TimeStatsLayer { class TimeStatsLayer { public: public: uid_t uid; uid_t uid; Loading @@ -67,6 +89,7 @@ public: int32_t lateAcquireFrames = 0; int32_t lateAcquireFrames = 0; int32_t badDesiredPresentFrames = 0; int32_t badDesiredPresentFrames = 0; JankPayload jankPayload; JankPayload jankPayload; SetFrameRateVote setFrameRateVote; std::unordered_map<std::string, Histogram> deltas; std::unordered_map<std::string, Histogram> deltas; std::string toString() const; std::string toString() const; Loading