SF: Add setFrameRate vote to TimeStats
Test: SF unit tests
Bug: 172939060
Change-Id: I60ea90c6f31b4bb22f39dea654de14e6c354974c
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 974ae84..2094972 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -89,12 +89,15 @@
return byteString;
}
-std::string frameRateVoteToProtoByteString(float refreshRate, int frameRateCompatibility,
- int seamlessness) {
+std::string frameRateVoteToProtoByteString(
+ float refreshRate,
+ TimeStats::SetFrameRateVote::FrameRateCompatibility frameRateCompatibility,
+ TimeStats::SetFrameRateVote::Seamlessness seamlessness) {
util::ProtoOutputStream proto;
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 | 3 /* field id */, seamlessness);
+ proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */,
+ static_cast<int>(frameRateCompatibility));
+ proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, static_cast<int>(seamlessness));
std::string byteString;
proto.serializeToString(&byteString);
@@ -229,7 +232,10 @@
mStatsDelegate->statsEventWriteInt32(
event, layer->displayRefreshRateBucket); // display_refresh_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(),
frameRateVoteBytes.size()); // set_frame_rate_vote
std::string appDeadlineMissedBytes =
@@ -468,8 +474,10 @@
}
void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
- std::optional<Fps> renderRate) {
+ std::optional<Fps> renderRate,
+ SetFrameRateVote frameRateVote) {
ATRACE_CALL();
+ ALOGV("[%d]-flushAvailableRecordsToStatsLocked", layerId);
LayerRecord& layerRecord = mTimeStatsTracker[layerId];
TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord;
@@ -501,6 +509,9 @@
displayStats.stats[layerKey].uid = uid;
displayStats.stats[layerKey].layerName = layerName;
}
+ if (frameRateVote.frameRate > 0.0f) {
+ displayStats.stats[layerKey].setFrameRateVote = frameRateVote;
+ }
TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey];
timeStatsLayer.totalFrames++;
timeStatsLayer.droppedFrames += layerRecord.droppedFrames;
@@ -724,7 +735,8 @@
}
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;
ATRACE_CALL();
@@ -743,12 +755,13 @@
layerRecord.waitData++;
}
- flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
+ flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote);
}
void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber,
const std::shared_ptr<FenceTime>& presentFence,
- Fps displayRefreshRate, std::optional<Fps> renderRate) {
+ Fps displayRefreshRate, std::optional<Fps> renderRate,
+ SetFrameRateVote frameRateVote) {
if (!mEnabled.load()) return;
ATRACE_CALL();
@@ -768,7 +781,7 @@
layerRecord.waitData++;
}
- flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
+ flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate, frameRateVote);
}
static const constexpr int32_t kValidJankyReason = JankType::DisplayHAL |
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index fd112b9..a87b7cb 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -50,6 +50,8 @@
class TimeStats {
public:
+ using SetFrameRateVote = TimeStatsHelper::SetFrameRateVote;
+
virtual ~TimeStats() = default;
// Called once boot has been finished to perform additional capabilities,
@@ -110,10 +112,12 @@
// SetPresent{Time, Fence} are not expected to be called in the critical
// rendering path, as they flush prior fences if those fences have fired.
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,
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}
// key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the
@@ -307,10 +311,11 @@
void setAcquireFence(int32_t layerId, uint64_t frameNumber,
const std::shared_ptr<FenceTime>& acquireFence) override;
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,
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;
// Clean up the layer record
@@ -334,7 +339,8 @@
AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data);
bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord);
void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
- std::optional<Fps> renderRate);
+ std::optional<Fps> renderRate,
+ SetFrameRateVote frameRateVote);
void flushPowerTimeLocked();
void flushAvailableGlobalRecordsToStatsLocked();
bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName);
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index d116b02..a7e7db2 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -91,6 +91,37 @@
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 result = "\n";
StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket);
@@ -104,6 +135,8 @@
StringAppendF(&result, "badDesiredPresentFrames = %d\n", badDesiredPresentFrames);
result.append("Jank payload for this layer:\n");
result.append(jankPayload.toString());
+ result.append("SetFrateRate vote for this layer:\n");
+ result.append(setFrameRateVote.toString());
const auto iter = deltas.find("present2present");
if (iter != deltas.end()) {
const float averageTime = iter->second.averageTime();
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index 5ee28ce..2b37ffe 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -55,6 +55,28 @@
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 {
public:
uid_t uid;
@@ -67,6 +89,7 @@
int32_t lateAcquireFrames = 0;
int32_t badDesiredPresentFrames = 0;
JankPayload jankPayload;
+ SetFrameRateVote setFrameRateVote;
std::unordered_map<std::string, Histogram> deltas;
std::string toString() const;