• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // TODO(b/129481165): remove the #pragma below and fix conversion issues
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wconversion"
20 #pragma clang diagnostic ignored "-Wextra"
21 
22 #undef LOG_TAG
23 #define LOG_TAG "LibSurfaceFlingerUnittests"
24 
25 #include <TimeStats/TimeStats.h>
26 #include <gmock/gmock.h>
27 #include <gtest/gtest.h>
28 #include <log/log.h>
29 #include <timestatsatomsproto/TimeStatsAtomsProtoHeader.h>
30 #include <utils/String16.h>
31 #include <utils/Vector.h>
32 
33 #include <chrono>
34 #include <random>
35 #include <unordered_set>
36 
37 #include "libsurfaceflinger_unittest_main.h"
38 
39 using namespace android::surfaceflinger;
40 using namespace google::protobuf;
41 using namespace std::chrono_literals;
42 
43 namespace android {
44 namespace {
45 
46 using testing::_;
47 using testing::AnyNumber;
48 using testing::Contains;
49 using testing::HasSubstr;
50 using testing::InSequence;
51 using testing::Not;
52 using testing::SizeIs;
53 using testing::StrEq;
54 using testing::UnorderedElementsAre;
55 
56 using PowerMode = hardware::graphics::composer::V2_4::IComposerClient::PowerMode;
57 using SurfaceflingerStatsLayerInfo = android::surfaceflinger::SurfaceflingerStatsLayerInfo;
58 using SurfaceflingerStatsLayerInfoWrapper =
59         android::surfaceflinger::SurfaceflingerStatsLayerInfoWrapper;
60 
61 // clang-format off
62 #define FMT_PROTO             true
63 #define FMT_STRING            false
64 #define LAYER_ID_0            0
65 #define LAYER_ID_1            1
66 #define UID_0                 123
67 #define REFRESH_RATE_0        61
68 #define RENDER_RATE_0         31
69 #define REFRESH_RATE_BUCKET_0 60
70 #define RENDER_RATE_BUCKET_0  30
71 #define LAYER_ID_INVALID      -1
72 #define NUM_LAYERS            1
73 #define NUM_LAYERS_INVALID    "INVALID"
74 
75 const constexpr Fps kRefreshRate0 = Fps(static_cast<float>(REFRESH_RATE_0));
76 const constexpr Fps kRenderRate0 = Fps(static_cast<float>(RENDER_RATE_0));
77 static constexpr int32_t kGameMode = TimeStatsHelper::GameModeUnsupported;
78 
79 enum InputCommand : int32_t {
80     ENABLE                 = 0,
81     DISABLE                = 1,
82     CLEAR                  = 2,
83     DUMP_ALL               = 3,
84     DUMP_MAXLAYERS_1       = 4,
85     DUMP_MAXLAYERS_INVALID = 5,
86     INPUT_COMMAND_BEGIN    = ENABLE,
87     INPUT_COMMAND_END      = DUMP_MAXLAYERS_INVALID,
88     INPUT_COMMAND_RANGE    = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
89 };
90 
91 enum TimeStamp : int32_t {
92     POST                   = 0,
93     ACQUIRE                = 1,
94     ACQUIRE_FENCE          = 2,
95     LATCH                  = 3,
96     DESIRED                = 4,
97     PRESENT                = 5,
98     PRESENT_FENCE          = 6,
99     TIME_STAMP_BEGIN       = POST,
100     TIME_STAMP_END         = PRESENT,
101     TIME_STAMP_RANGE       = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
102 };
103 
104 static const TimeStamp NORMAL_SEQUENCE[] = {
105         TimeStamp::POST,
106         TimeStamp::ACQUIRE,
107         TimeStamp::LATCH,
108         TimeStamp::DESIRED,
109         TimeStamp::PRESENT,
110 };
111 
112 static const TimeStamp NORMAL_SEQUENCE_2[] = {
113         TimeStamp::POST,
114         TimeStamp::ACQUIRE_FENCE,
115         TimeStamp::LATCH,
116         TimeStamp::DESIRED,
117         TimeStamp::PRESENT_FENCE,
118 };
119 
120 static const TimeStamp UNORDERED_SEQUENCE[] = {
121         TimeStamp::ACQUIRE,
122         TimeStamp::LATCH,
123         TimeStamp::POST,
124         TimeStamp::DESIRED,
125         TimeStamp::PRESENT,
126 };
127 
128 static const TimeStamp INCOMPLETE_SEQUENCE[] = {
129         TimeStamp::POST,
130 };
131 // clang-format on
132 
133 class TimeStatsTest : public testing::Test {
134 public:
TimeStatsTest()135     TimeStatsTest() {
136         const ::testing::TestInfo* const test_info =
137                 ::testing::UnitTest::GetInstance()->current_test_info();
138         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
139     }
140 
~TimeStatsTest()141     ~TimeStatsTest() {
142         const ::testing::TestInfo* const test_info =
143                 ::testing::UnitTest::GetInstance()->current_test_info();
144         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
145     }
146 
147     std::string inputCommand(InputCommand cmd, bool useProto);
148 
149     void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
150                       TimeStats::SetFrameRateVote frameRateVote, int32_t gameMode);
151 
152     int32_t genRandomInt32(int32_t begin, int32_t end);
153 
154     template <size_t N>
insertTimeRecord(const TimeStamp (& sequence)[N],int32_t id,uint64_t frameNumber,nsecs_t ts,TimeStats::SetFrameRateVote frameRateVote={},int32_t gameMode=kGameMode)155     void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
156                           nsecs_t ts, TimeStats::SetFrameRateVote frameRateVote = {},
157                           int32_t gameMode = kGameMode) {
158         for (size_t i = 0; i < N; i++, ts += 1000000) {
159             setTimeStamp(sequence[i], id, frameNumber, ts, frameRateVote, gameMode);
160         }
161     }
162 
163     std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
164     std::unique_ptr<TimeStats> mTimeStats =
165             std::make_unique<impl::TimeStats>(std::nullopt, std::nullopt);
166 };
167 
inputCommand(InputCommand cmd,bool useProto)168 std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
169     std::string result;
170     Vector<String16> args;
171 
172     switch (cmd) {
173         case InputCommand::ENABLE:
174             args.push_back(String16("-enable"));
175             break;
176         case InputCommand::DISABLE:
177             args.push_back(String16("-disable"));
178             break;
179         case InputCommand::CLEAR:
180             args.push_back(String16("-clear"));
181             break;
182         case InputCommand::DUMP_ALL:
183             args.push_back(String16("-dump"));
184             break;
185         case InputCommand::DUMP_MAXLAYERS_1:
186             args.push_back(String16("-dump"));
187             args.push_back(String16("-maxlayers"));
188             args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
189             break;
190         case InputCommand::DUMP_MAXLAYERS_INVALID:
191             args.push_back(String16("-dump"));
192             args.push_back(String16("-maxlayers"));
193             args.push_back(String16(NUM_LAYERS_INVALID));
194             break;
195         default:
196             ALOGD("Invalid control command");
197     }
198 
199     EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
200     return result;
201 }
202 
genLayerName(int32_t layerId)203 static std::string genLayerName(int32_t layerId) {
204     return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.example.fake#") + std::to_string(layerId);
205 }
206 
setTimeStamp(TimeStamp type,int32_t id,uint64_t frameNumber,nsecs_t ts,TimeStats::SetFrameRateVote frameRateVote,int32_t gameMode)207 void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
208                                  TimeStats::SetFrameRateVote frameRateVote, int32_t gameMode) {
209     switch (type) {
210         case TimeStamp::POST:
211             ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id),
212                                                             UID_0, ts, gameMode));
213             break;
214         case TimeStamp::ACQUIRE:
215             ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
216             break;
217         case TimeStamp::ACQUIRE_FENCE:
218             ASSERT_NO_FATAL_FAILURE(
219                     mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
220             break;
221         case TimeStamp::LATCH:
222             ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
223             break;
224         case TimeStamp::DESIRED:
225             ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
226             break;
227         case TimeStamp::PRESENT:
228             ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts, kRefreshRate0,
229                                                                kRenderRate0, frameRateVote,
230                                                                gameMode));
231             break;
232         case TimeStamp::PRESENT_FENCE:
233             ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentFence(id, frameNumber,
234                                                                 std::make_shared<FenceTime>(ts),
235                                                                 kRefreshRate0, kRenderRate0,
236                                                                 frameRateVote, gameMode));
237             break;
238         default:
239             ALOGD("Invalid timestamp type");
240     }
241 }
242 
genRandomInt32(int32_t begin,int32_t end)243 int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
244     std::uniform_int_distribution<int32_t> distr(begin, end);
245     return distr(mRandomEngine);
246 }
247 
TEST_F(TimeStatsTest,disabledByDefault)248 TEST_F(TimeStatsTest, disabledByDefault) {
249     ASSERT_FALSE(mTimeStats->isEnabled());
250 }
251 
TEST_F(TimeStatsTest,canEnableAndDisableTimeStats)252 TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
253     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
254     ASSERT_TRUE(mTimeStats->isEnabled());
255 
256     EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
257     ASSERT_FALSE(mTimeStats->isEnabled());
258 }
259 
TEST_F(TimeStatsTest,canIncreaseGlobalStats)260 TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
261     constexpr size_t TOTAL_FRAMES = 5;
262     constexpr size_t MISSED_FRAMES = 4;
263     constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
264 
265     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
266 
267     for (size_t i = 0; i < TOTAL_FRAMES; i++) {
268         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
269     }
270     for (size_t i = 0; i < MISSED_FRAMES; i++) {
271         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
272     }
273     for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
274         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
275     }
276 
277     SFTimeStatsGlobalProto globalProto;
278     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
279 
280     ASSERT_TRUE(globalProto.has_total_frames());
281     EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
282     ASSERT_TRUE(globalProto.has_missed_frames());
283     EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
284     ASSERT_TRUE(globalProto.has_client_composition_frames());
285     EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
286 }
287 
TEST_F(TimeStatsTest,canIncreaseLateAcquireFrames)288 TEST_F(TimeStatsTest, canIncreaseLateAcquireFrames) {
289     // this stat is not in the proto so verify by checking the string dump
290     constexpr size_t LATE_ACQUIRE_FRAMES = 2;
291 
292     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
293 
294     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
295     for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
296         mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
297     }
298     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
299 
300     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
301     const std::string expectedResult = "lateAcquireFrames = " + std::to_string(LATE_ACQUIRE_FRAMES);
302     EXPECT_THAT(result, HasSubstr(expectedResult));
303 }
304 
TEST_F(TimeStatsTest,canIncreaseBadDesiredPresent)305 TEST_F(TimeStatsTest, canIncreaseBadDesiredPresent) {
306     // this stat is not in the proto so verify by checking the string dump
307     constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 2;
308 
309     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
310 
311     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
312     for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
313         mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
314     }
315     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
316 
317     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
318     const std::string expectedResult =
319             "badDesiredPresentFrames = " + std::to_string(BAD_DESIRED_PRESENT_FRAMES);
320     EXPECT_THAT(result, HasSubstr(expectedResult));
321 }
322 
TEST_F(TimeStatsTest,canIncreaseJankyFramesForLayer)323 TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
324     // this stat is not in the proto so verify by checking the string dump
325     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
326 
327     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
328     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
329                                       kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
330                                       3});
331     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
332                                       kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
333                                       3});
334     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
335                                       kGameMode, JankType::DisplayHAL, 1, 2, 3});
336     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
337                                       kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
338     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
339                                       kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
340     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
341                                       kGameMode, JankType::PredictionError, 1, 2, 3});
342     mTimeStats->incrementJankyFrames(
343             {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
344              JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
345     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
346                                       kGameMode, JankType::None, 1, 2, 3});
347 
348     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
349     std::string expectedResult =
350             "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
351     EXPECT_THAT(result, HasSubstr(expectedResult));
352     expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
353     EXPECT_THAT(result, HasSubstr(expectedResult));
354     expectedResult = "totalTimelineFrames = " + std::to_string(8);
355     EXPECT_THAT(result, HasSubstr(expectedResult));
356     expectedResult = "jankyFrames = " + std::to_string(7);
357     EXPECT_THAT(result, HasSubstr(expectedResult));
358     expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
359     EXPECT_THAT(result, HasSubstr(expectedResult));
360     expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
361     EXPECT_THAT(result, HasSubstr(expectedResult));
362     expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
363     EXPECT_THAT(result, HasSubstr(expectedResult));
364     expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
365     EXPECT_THAT(result, HasSubstr(expectedResult));
366     expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
367     EXPECT_THAT(result, HasSubstr(expectedResult));
368     expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
369     EXPECT_THAT(result, HasSubstr(expectedResult));
370     expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
371     EXPECT_THAT(result, HasSubstr(expectedResult));
372 }
373 
TEST_F(TimeStatsTest,canCaptureSetFrameRateVote)374 TEST_F(TimeStatsTest, canCaptureSetFrameRateVote) {
375     // this stat is not in the proto so verify by checking the string dump
376     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
377 
378     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
379 
380     const auto frameRate60 = TimeStats::SetFrameRateVote{
381             .frameRate = 60.0f,
382             .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
383             .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
384     };
385     const auto frameRate90 = TimeStats::SetFrameRateVote{
386             .frameRate = 90.0f,
387             .frameRateCompatibility =
388                     TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
389             .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
390     };
391     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
392     std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
393     std::string expectedResult = "frameRate = 60.00";
394     EXPECT_THAT(result, HasSubstr(expectedResult));
395     expectedResult = "frameRateCompatibility = Default";
396     EXPECT_THAT(result, HasSubstr(expectedResult));
397     expectedResult = "seamlessness = ShouldBeSeamless";
398     EXPECT_THAT(result, HasSubstr(expectedResult));
399 
400     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRate90);
401     result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
402     expectedResult = "frameRate = 90.00";
403     EXPECT_THAT(result, HasSubstr(expectedResult));
404     expectedResult = "frameRateCompatibility = ExactOrMultiple";
405     EXPECT_THAT(result, HasSubstr(expectedResult));
406     expectedResult = "seamlessness = NotRequired";
407     EXPECT_THAT(result, HasSubstr(expectedResult));
408 
409     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRate60);
410     result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
411     expectedResult = "frameRate = 60.00";
412     EXPECT_THAT(result, HasSubstr(expectedResult));
413     expectedResult = "frameRateCompatibility = Default";
414     EXPECT_THAT(result, HasSubstr(expectedResult));
415     expectedResult = "seamlessness = ShouldBeSeamless";
416     EXPECT_THAT(result, HasSubstr(expectedResult));
417 }
418 
TEST_F(TimeStatsTest,canCaptureSetFrameRateVoteAfterZeroForLayer)419 TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) {
420     // this stat is not in the proto so verify by checking the string dump
421     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
422 
423     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
424 
425     const auto frameRate90 = TimeStats::SetFrameRateVote{
426             .frameRate = 90.0f,
427             .frameRateCompatibility =
428                     TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
429             .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
430     };
431     const auto frameRateDefault = TimeStats::SetFrameRateVote{
432             .frameRate = 0.0f,
433             .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
434             .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
435     };
436     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate90);
437     std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
438     std::string expectedResult = "frameRate = 90.00";
439     EXPECT_THAT(result, HasSubstr(expectedResult));
440     expectedResult = "frameRateCompatibility = ExactOrMultiple";
441     EXPECT_THAT(result, HasSubstr(expectedResult));
442     expectedResult = "seamlessness = NotRequired";
443     EXPECT_THAT(result, HasSubstr(expectedResult));
444 
445     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRateDefault);
446     result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
447     expectedResult = "frameRate = 90.00";
448     EXPECT_THAT(result, HasSubstr(expectedResult));
449     expectedResult = "frameRateCompatibility = ExactOrMultiple";
450     EXPECT_THAT(result, HasSubstr(expectedResult));
451     expectedResult = "seamlessness = NotRequired";
452     EXPECT_THAT(result, HasSubstr(expectedResult));
453 
454     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRateDefault);
455     result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
456     expectedResult = "frameRate = 90.00";
457     EXPECT_THAT(result, HasSubstr(expectedResult));
458     expectedResult = "frameRateCompatibility = ExactOrMultiple";
459     EXPECT_THAT(result, HasSubstr(expectedResult));
460     expectedResult = "seamlessness = NotRequired";
461     EXPECT_THAT(result, HasSubstr(expectedResult));
462 }
463 
TEST_F(TimeStatsTest,canIncreaseClientCompositionReusedFrames)464 TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) {
465     // this stat is not in the proto so verify by checking the string dump
466     constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2;
467 
468     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
469     for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) {
470         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
471     }
472 
473     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
474     const std::string expectedResult =
475             "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES);
476     EXPECT_THAT(result, HasSubstr(expectedResult));
477 }
478 
TEST_F(TimeStatsTest,canIncreaseRefreshRateSwitches)479 TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
480     // this stat is not in the proto so verify by checking the string dump
481     constexpr size_t REFRESH_RATE_SWITCHES = 2;
482 
483     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
484     for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
485         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
486     }
487 
488     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
489     const std::string expectedResult =
490             "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
491     EXPECT_THAT(result, HasSubstr(expectedResult));
492 }
493 
TEST_F(TimeStatsTest,canIncreaseCompositionStrategyChanges)494 TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) {
495     // this stat is not in the proto so verify by checking the string dump
496     constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2;
497 
498     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
499     for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) {
500         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
501     }
502 
503     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
504     const std::string expectedResult =
505             "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES);
506     EXPECT_THAT(result, HasSubstr(expectedResult));
507 }
508 
TEST_F(TimeStatsTest,canAverageFrameDuration)509 TEST_F(TimeStatsTest, canAverageFrameDuration) {
510     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
511     mTimeStats->setPowerMode(PowerMode::ON);
512     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
513                                     std::chrono::nanoseconds(6ms).count());
514     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
515                                     std::chrono::nanoseconds(16ms).count());
516 
517     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
518     EXPECT_THAT(result, HasSubstr("averageFrameDuration = 10.000 ms"));
519 }
520 
TEST_F(TimeStatsTest,canAverageRenderEngineTimings)521 TEST_F(TimeStatsTest, canAverageRenderEngineTimings) {
522     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
523     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
524                                            std::make_shared<FenceTime>(
525                                                    std::chrono::duration_cast<
526                                                            std::chrono::nanoseconds>(3ms)
527                                                            .count()));
528 
529     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
530                                            std::chrono::nanoseconds(8ms).count());
531 
532     // Push a fake present fence to trigger flushing the RenderEngine timings.
533     mTimeStats->setPowerMode(PowerMode::ON);
534     mTimeStats->setPresentFenceGlobal(
535             std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
536 
537     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
538     EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 3.000 ms"));
539 }
540 
TEST_F(TimeStatsTest,canInsertGlobalPresentToPresent)541 TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
542     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
543 
544     ASSERT_NO_FATAL_FAILURE(
545             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
546     ASSERT_NO_FATAL_FAILURE(
547             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
548 
549     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
550     ASSERT_NO_FATAL_FAILURE(
551             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
552     ASSERT_NO_FATAL_FAILURE(
553             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
554 
555     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
556     ASSERT_NO_FATAL_FAILURE(
557             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
558     ASSERT_NO_FATAL_FAILURE(
559             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
560 
561     SFTimeStatsGlobalProto globalProto;
562     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
563 
564     ASSERT_EQ(1, globalProto.present_to_present_size());
565     const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
566     EXPECT_EQ(1, histogramProto.frame_count());
567     EXPECT_EQ(2, histogramProto.time_millis());
568 }
569 
TEST_F(TimeStatsTest,canInsertGlobalFrameDuration)570 TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
571     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
572 
573     mTimeStats->setPowerMode(PowerMode::OFF);
574     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
575                                     std::chrono::nanoseconds(5ms).count());
576     mTimeStats->setPowerMode(PowerMode::ON);
577     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
578                                     std::chrono::nanoseconds(6ms).count());
579 
580     SFTimeStatsGlobalProto globalProto;
581     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
582 
583     ASSERT_EQ(1, globalProto.frame_duration_size());
584     const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.frame_duration().Get(0);
585     EXPECT_EQ(1, histogramProto.frame_count());
586     EXPECT_EQ(3, histogramProto.time_millis());
587 }
588 
TEST_F(TimeStatsTest,canInsertGlobalRenderEngineTiming)589 TEST_F(TimeStatsTest, canInsertGlobalRenderEngineTiming) {
590     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
591 
592     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
593                                            std::make_shared<FenceTime>(
594                                                    std::chrono::duration_cast<
595                                                            std::chrono::nanoseconds>(3ms)
596                                                            .count()));
597 
598     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
599                                            std::chrono::nanoseconds(6ms).count());
600 
601     // First verify that flushing RenderEngine durations did not occur yet.
602     SFTimeStatsGlobalProto preFlushProto;
603     ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
604     ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
605 
606     // Push a fake present fence to trigger flushing the RenderEngine timings.
607     mTimeStats->setPowerMode(PowerMode::ON);
608     mTimeStats->setPresentFenceGlobal(
609             std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
610 
611     // Now we can verify that RenderEngine durations were flushed now.
612     SFTimeStatsGlobalProto postFlushProto;
613     ASSERT_TRUE(postFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
614 
615     ASSERT_EQ(1, postFlushProto.render_engine_timing_size());
616     const SFTimeStatsHistogramBucketProto& histogramProto =
617             postFlushProto.render_engine_timing().Get(0);
618     EXPECT_EQ(2, histogramProto.frame_count());
619     EXPECT_EQ(2, histogramProto.time_millis());
620 }
621 
TEST_F(TimeStatsTest,canInsertOneLayerTimeStats)622 TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
623     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
624 
625     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
626     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
627 
628     SFTimeStatsGlobalProto globalProto;
629     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
630 
631     ASSERT_EQ(1, globalProto.stats_size());
632     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
633     ASSERT_TRUE(layerProto.has_layer_name());
634     EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
635     ASSERT_TRUE(layerProto.has_total_frames());
636     EXPECT_EQ(1, layerProto.total_frames());
637     ASSERT_EQ(6, layerProto.deltas_size());
638     for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
639         ASSERT_EQ(1, deltaProto.histograms_size());
640         const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
641         EXPECT_EQ(1, histogramProto.frame_count());
642         if ("post2acquire" == deltaProto.delta_name()) {
643             EXPECT_EQ(1, histogramProto.time_millis());
644         } else if ("post2present" == deltaProto.delta_name()) {
645             EXPECT_EQ(4, histogramProto.time_millis());
646         } else if ("acquire2present" == deltaProto.delta_name()) {
647             EXPECT_EQ(3, histogramProto.time_millis());
648         } else if ("latch2present" == deltaProto.delta_name()) {
649             EXPECT_EQ(2, histogramProto.time_millis());
650         } else if ("desired2present" == deltaProto.delta_name()) {
651             EXPECT_EQ(1, histogramProto.time_millis());
652         } else if ("present2present" == deltaProto.delta_name()) {
653             EXPECT_EQ(1, histogramProto.time_millis());
654         } else {
655             FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
656         }
657     }
658 }
659 
TEST_F(TimeStatsTest,canNotInsertInvalidLayerNameTimeStats)660 TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
661     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
662 
663     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
664     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
665 
666     SFTimeStatsGlobalProto globalProto;
667     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
668 
669     ASSERT_EQ(0, globalProto.stats_size());
670 }
671 
TEST_F(TimeStatsTest,canInsertMultipleLayersTimeStats)672 TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
673     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
674 
675     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
676     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
677     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
678     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
679 
680     SFTimeStatsGlobalProto globalProto;
681     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
682 
683     EXPECT_EQ(2, globalProto.stats_size());
684 }
685 
TEST_F(TimeStatsTest,canInsertUnorderedLayerTimeStats)686 TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
687     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
688 
689     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
690     insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
691 
692     SFTimeStatsGlobalProto globalProto;
693     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
694 
695     ASSERT_EQ(1, globalProto.stats_size());
696     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
697     ASSERT_TRUE(layerProto.has_layer_name());
698     EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
699     ASSERT_TRUE(layerProto.has_total_frames());
700     EXPECT_EQ(1, layerProto.total_frames());
701     ASSERT_EQ(6, layerProto.deltas_size());
702     for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
703         ASSERT_EQ(1, deltaProto.histograms_size());
704         const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
705         EXPECT_EQ(1, histogramProto.frame_count());
706         if ("post2acquire" == deltaProto.delta_name()) {
707             EXPECT_EQ(0, histogramProto.time_millis());
708         } else if ("post2present" == deltaProto.delta_name()) {
709             EXPECT_EQ(2, histogramProto.time_millis());
710         } else if ("acquire2present" == deltaProto.delta_name()) {
711             EXPECT_EQ(2, histogramProto.time_millis());
712         } else if ("latch2present" == deltaProto.delta_name()) {
713             EXPECT_EQ(2, histogramProto.time_millis());
714         } else if ("desired2present" == deltaProto.delta_name()) {
715             EXPECT_EQ(1, histogramProto.time_millis());
716         } else if ("present2present" == deltaProto.delta_name()) {
717             EXPECT_EQ(1, histogramProto.time_millis());
718         } else {
719             FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
720         }
721     }
722 }
723 
TEST_F(TimeStatsTest,recordRefreshRateNewConfigs)724 TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
725     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
726 
727     uint32_t fpsOne = 30;
728     uint32_t fpsTwo = 90;
729     uint64_t millisOne = 5000;
730     uint64_t millisTwo = 7000;
731 
732     mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
733     mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
734 
735     SFTimeStatsGlobalProto globalProto;
736     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
737 
738     SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
739     SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
740     expectedConfigOne->set_fps(fpsOne);
741     expectedBucketOne.set_duration_millis(millisOne);
742 
743     SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
744     SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
745     expectedConfigTwo->set_fps(fpsTwo);
746     expectedBucketTwo.set_duration_millis(millisTwo);
747 
748     EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
749 
750     std::unordered_set<uint32_t> seen_fps;
751     for (const auto& bucket : globalProto.display_config_stats()) {
752         seen_fps.emplace(bucket.config().fps());
753         if (fpsOne == bucket.config().fps()) {
754             EXPECT_EQ(millisOne, bucket.duration_millis());
755         } else if (fpsTwo == bucket.config().fps()) {
756             EXPECT_EQ(millisTwo, bucket.duration_millis());
757         } else {
758             FAIL() << "Unknown fps: " << bucket.config().fps();
759         }
760     }
761     EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
762 }
763 
TEST_F(TimeStatsTest,recordRefreshRateUpdatesConfig)764 TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
765     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
766 
767     uint32_t fps = 30;
768     uint64_t millisOne = 5000;
769     uint64_t millisTwo = 7000;
770 
771     mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
772     mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
773 
774     SFTimeStatsGlobalProto globalProto;
775     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
776     EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
777     EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
778     EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
779 }
780 
TEST_F(TimeStatsTest,canRemoveTimeRecord)781 TEST_F(TimeStatsTest, canRemoveTimeRecord) {
782     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
783 
784     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
785     insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
786     ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
787     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
788 
789     SFTimeStatsGlobalProto globalProto;
790     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
791 
792     ASSERT_EQ(1, globalProto.stats_size());
793     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
794     ASSERT_TRUE(layerProto.has_total_frames());
795     EXPECT_EQ(1, layerProto.total_frames());
796 }
797 
TEST_F(TimeStatsTest,canRecoverFromIncompleteTimeRecordError)798 TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
799     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
800 
801     uint64_t frameNumber = 1;
802     nsecs_t ts = 1000000;
803     insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
804     for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
805         frameNumber++;
806         ts += 1000000;
807         insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
808     }
809 
810     SFTimeStatsGlobalProto globalProto;
811     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
812 
813     ASSERT_EQ(1, globalProto.stats_size());
814     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
815     ASSERT_TRUE(layerProto.has_total_frames());
816     EXPECT_EQ(1, layerProto.total_frames());
817 }
818 
TEST_F(TimeStatsTest,layerTimeStatsOnDestroy)819 TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
820     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
821 
822     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
823     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
824     ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
825     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
826 
827     SFTimeStatsGlobalProto globalProto;
828     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
829 
830     ASSERT_EQ(1, globalProto.stats_size());
831     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
832     ASSERT_TRUE(layerProto.has_total_frames());
833     EXPECT_EQ(1, layerProto.total_frames());
834 }
835 
TEST_F(TimeStatsTest,canClearTimeStats)836 TEST_F(TimeStatsTest, canClearTimeStats) {
837     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
838 
839     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
840     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
841     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
842     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
843 
844     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
845                                     std::chrono::nanoseconds(6ms).count());
846     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
847                                            std::chrono::nanoseconds(6ms).count());
848     ASSERT_NO_FATAL_FAILURE(
849             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
850     ASSERT_NO_FATAL_FAILURE(
851             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
852     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
853     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
854 
855     EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
856 
857     SFTimeStatsGlobalProto globalProto;
858     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
859 
860     EXPECT_EQ(0, globalProto.total_frames());
861     EXPECT_EQ(0, globalProto.missed_frames());
862     EXPECT_EQ(0, globalProto.client_composition_frames());
863     EXPECT_EQ(0, globalProto.present_to_present_size());
864     EXPECT_EQ(0, globalProto.frame_duration_size());
865     EXPECT_EQ(0, globalProto.render_engine_timing_size());
866     EXPECT_EQ(0, globalProto.stats_size());
867 }
868 
TEST_F(TimeStatsTest,canClearDumpOnlyTimeStats)869 TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) {
870     // These stats are not in the proto so verify by checking the string dump.
871     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
872     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
873     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
874     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
875     mTimeStats->setPowerMode(PowerMode::ON);
876     mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
877                                     std::chrono::nanoseconds(5ms).count());
878     mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
879                                            std::chrono::nanoseconds(6ms).count());
880     mTimeStats->setPresentFenceGlobal(
881             std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
882 
883     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
884                                       kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
885                                       3});
886     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
887                                       kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
888                                       3});
889     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
890                                       kGameMode, JankType::DisplayHAL, 1, 2, 3});
891     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
892                                       kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
893     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
894                                       kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
895     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
896                                       kGameMode, JankType::PredictionError, 1, 2, 3});
897     mTimeStats->incrementJankyFrames(
898             {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
899              JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
900     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
901                                       kGameMode, JankType::None, 1, 2, 3});
902 
903     EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
904 
905     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
906     EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
907     EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
908     EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
909     EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
910     EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
911     std::string expectedResult = "totalTimelineFrames = ";
912     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
913     expectedResult = "jankyFrames = ";
914     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
915     expectedResult = "sfLongCpuJankyFrames = ";
916     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
917     expectedResult = "sfLongGpuJankyFrames = ";
918     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
919     expectedResult = "sfUnattributedJankyFrames = ";
920     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
921     expectedResult = "appUnattributedJankyFrames = ";
922     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
923     expectedResult = "sfSchedulingJankyFrames = ";
924     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
925     expectedResult = "sfPredictionErrorJankyFrames = ";
926     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
927     expectedResult = "appBufferStuffingJankyFrames = ";
928     EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
929 }
930 
TEST_F(TimeStatsTest,canDumpWithMaxLayers)931 TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
932     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
933 
934     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
935     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
936     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
937     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
938     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
939 
940     SFTimeStatsGlobalProto globalProto;
941     ASSERT_TRUE(
942             globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
943 
944     ASSERT_EQ(1, globalProto.stats_size());
945     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
946     ASSERT_TRUE(layerProto.has_layer_name());
947     EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
948     ASSERT_TRUE(layerProto.has_total_frames());
949     EXPECT_EQ(2, layerProto.total_frames());
950 }
951 
TEST_F(TimeStatsTest,canDumpWithInvalidMaxLayers)952 TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
953     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
954 
955     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
956     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
957 
958     SFTimeStatsGlobalProto globalProto;
959     ASSERT_TRUE(globalProto.ParseFromString(
960             inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
961 
962     ASSERT_EQ(0, globalProto.stats_size());
963 }
964 
TEST_F(TimeStatsTest,noInfInAverageFPS)965 TEST_F(TimeStatsTest, noInfInAverageFPS) {
966     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
967     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
968     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 1000000);
969 
970     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
971     EXPECT_THAT(result, HasSubstr("averageFPS = 0.000"));
972 }
973 
974 namespace {
buildExpectedHistogram(const std::vector<int32_t> & times,const std::vector<int32_t> & frameCounts)975 FrameTimingHistogram buildExpectedHistogram(const std::vector<int32_t>& times,
976                                             const std::vector<int32_t>& frameCounts) {
977     FrameTimingHistogram histogram;
978     for (int i = 0; i < times.size(); i++) {
979         ALOGE("Writing time: %d", times[i]);
980         histogram.add_time_millis_buckets(times[i]);
981         ALOGE("Writing count: %d", frameCounts[i]);
982         histogram.add_frame_counts((int64_t)frameCounts[i]);
983     }
984     return histogram;
985 }
986 } // namespace
987 
988 MATCHER_P(HistogramEq, expected, "") {
989     *result_listener << "Histograms are not equal! \n";
990 
991     if (arg.time_millis_buckets_size() != expected.time_millis_buckets_size()) {
992         *result_listener << "Time millis bucket are different sizes. Expected: "
993                          << expected.time_millis_buckets_size() << ". Actual "
994                          << arg.time_millis_buckets_size();
995         return false;
996     }
997     if (arg.frame_counts_size() != expected.frame_counts_size()) {
998         *result_listener << "Frame counts are different sizes. Expected: "
999                          << expected.frame_counts_size() << ". Actual " << arg.frame_counts_size();
1000         return false;
1001     }
1002 
1003     for (int i = 0; i < expected.time_millis_buckets_size(); i++) {
1004         if (arg.time_millis_buckets(i) != expected.time_millis_buckets(i)) {
1005             *result_listener << "time_millis_bucket[" << i
1006                              << "] is different. Expected: " << expected.time_millis_buckets(i)
1007                              << ". Actual: " << arg.time_millis_buckets(i);
1008             return false;
1009         }
1010         if (arg.frame_counts(i) != expected.frame_counts(i)) {
1011             *result_listener << "frame_counts[" << i
1012                              << "] is different. Expected: " << expected.frame_counts(i)
1013                              << ". Actual: " << arg.frame_counts(i);
1014             return false;
1015         }
1016     }
1017     return true;
1018 }
1019 
TEST_F(TimeStatsTest,globalStatsCallback)1020 TEST_F(TimeStatsTest, globalStatsCallback) {
1021     constexpr size_t TOTAL_FRAMES = 5;
1022     constexpr size_t MISSED_FRAMES = 4;
1023     constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
1024     constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
1025     constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1026     constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1027     constexpr nsecs_t APP_DEADLINE_DELTA = 3'000'000;
1028 
1029     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1030 
1031     for (size_t i = 0; i < TOTAL_FRAMES; i++) {
1032         mTimeStats->incrementTotalFrames();
1033     }
1034     for (size_t i = 0; i < MISSED_FRAMES; i++) {
1035         mTimeStats->incrementMissedFrames();
1036     }
1037     for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
1038         mTimeStats->incrementClientCompositionFrames();
1039     }
1040 
1041     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1042 
1043     mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
1044     mTimeStats->setPowerMode(PowerMode::ON);
1045     mTimeStats->recordFrameDuration(1000000, 3000000);
1046     mTimeStats->recordRenderEngineDuration(2000000, 4000000);
1047     mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
1048 
1049     mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1050     mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1051 
1052     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1053                                       kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed,
1054                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1055                                       APP_DEADLINE_DELTA});
1056     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1057                                       kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed,
1058                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1059                                       APP_DEADLINE_DELTA});
1060     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1061                                       kGameMode, JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
1062                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1063     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1064                                       kGameMode, JankType::AppDeadlineMissed,
1065                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1066                                       APP_DEADLINE_DELTA});
1067     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1068                                       kGameMode, JankType::SurfaceFlingerScheduling,
1069                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1070                                       APP_DEADLINE_DELTA});
1071     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1072                                       kGameMode, JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
1073                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1074     mTimeStats->incrementJankyFrames(
1075             {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
1076              JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1077              DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1078     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1079                                       kGameMode, JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1080                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1081     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1082                                       kGameMode, JankType::None, DISPLAY_DEADLINE_DELTA,
1083                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1084 
1085     std::string pulledData;
1086     EXPECT_TRUE(mTimeStats->onPullAtom(10062 /*SURFACEFLINGER_STATS_GLOBAL_INFO*/, &pulledData));
1087 
1088     android::surfaceflinger::SurfaceflingerStatsGlobalInfoWrapper atomList;
1089     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1090     ASSERT_EQ(atomList.atom_size(), 1);
1091     const android::surfaceflinger::SurfaceflingerStatsGlobalInfo& atom = atomList.atom(0);
1092 
1093     EXPECT_EQ(atom.total_frames(), TOTAL_FRAMES);
1094     EXPECT_EQ(atom.missed_frames(), MISSED_FRAMES);
1095     EXPECT_EQ(atom.client_composition_frames(), CLIENT_COMPOSITION_FRAMES);
1096     // Display on millis is not checked.
1097     EXPECT_EQ(atom.animation_millis(), 2);
1098     EXPECT_EQ(atom.event_connection_count(), DISPLAY_EVENT_CONNECTIONS);
1099     EXPECT_THAT(atom.frame_duration(), HistogramEq(buildExpectedHistogram({2}, {1})));
1100     EXPECT_THAT(atom.render_engine_timing(), HistogramEq(buildExpectedHistogram({1, 2}, {1, 1})));
1101     EXPECT_EQ(atom.total_timeline_frames(), 9);
1102     EXPECT_EQ(atom.total_janky_frames(), 7);
1103     EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1104     EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1105     EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1106     EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1107     EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1108     EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1109     EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 2);
1110     EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1111     EXPECT_THAT(atom.sf_deadline_misses(), HistogramEq(buildExpectedHistogram({1}, {7})));
1112     EXPECT_THAT(atom.sf_prediction_errors(), HistogramEq(buildExpectedHistogram({2}, {7})));
1113     EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1114 
1115     SFTimeStatsGlobalProto globalProto;
1116     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1117 
1118     EXPECT_EQ(0, globalProto.total_frames());
1119     EXPECT_EQ(0, globalProto.missed_frames());
1120     EXPECT_EQ(0, globalProto.client_composition_frames());
1121     EXPECT_EQ(0, globalProto.present_to_present_size());
1122 
1123     // also check dump-only stats: expect that global stats are indeed dropped but there should
1124     // still be stats for the layer
1125     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1126     std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
1127     EXPECT_THAT(result, HasSubstr(expectedResult));
1128     expectedResult = "totalTimelineFrames = " + std::to_string(9);
1129     EXPECT_THAT(result, HasSubstr(expectedResult));
1130     expectedResult = "jankyFrames = " + std::to_string(0);
1131     EXPECT_THAT(result, HasSubstr(expectedResult));
1132     expectedResult = "jankyFrames = " + std::to_string(7);
1133     EXPECT_THAT(result, HasSubstr(expectedResult));
1134     expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
1135     EXPECT_THAT(result, HasSubstr(expectedResult));
1136     expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1137     EXPECT_THAT(result, HasSubstr(expectedResult));
1138     expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
1139     EXPECT_THAT(result, HasSubstr(expectedResult));
1140     expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1141     EXPECT_THAT(result, HasSubstr(expectedResult));
1142     expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
1143     EXPECT_THAT(result, HasSubstr(expectedResult));
1144     expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1145     EXPECT_THAT(result, HasSubstr(expectedResult));
1146     expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
1147     EXPECT_THAT(result, HasSubstr(expectedResult));
1148     expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1149     EXPECT_THAT(result, HasSubstr(expectedResult));
1150     expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
1151     EXPECT_THAT(result, HasSubstr(expectedResult));
1152     expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1153     EXPECT_THAT(result, HasSubstr(expectedResult));
1154     expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
1155     EXPECT_THAT(result, HasSubstr(expectedResult));
1156     expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1157     EXPECT_THAT(result, HasSubstr(expectedResult));
1158     expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
1159     EXPECT_THAT(result, HasSubstr(expectedResult));
1160     expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(2);
1161     EXPECT_THAT(result, HasSubstr(expectedResult));
1162 }
1163 
TEST_F(TimeStatsTest,layerStatsCallback_pullsAllAndClears)1164 TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
1165     constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1166     constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1167     constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1168     constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1169     constexpr nsecs_t APP_DEADLINE_DELTA_2MS = 2'000'000;
1170     constexpr nsecs_t APP_DEADLINE_DELTA_3MS = 3'000'000;
1171     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1172 
1173     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1174                      TimeStatsHelper::GameModeStandard);
1175     for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1176         mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1177     }
1178     for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1179         mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1180     }
1181     const auto frameRate60 = TimeStats::SetFrameRateVote{
1182             .frameRate = 60.0f,
1183             .frameRateCompatibility =
1184                     TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1185             .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1186     };
1187     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60,
1188                      TimeStatsHelper::GameModeStandard);
1189 
1190     mTimeStats->incrementJankyFrames(
1191             {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1192              TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerCpuDeadlineMissed,
1193              DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
1194     mTimeStats->incrementJankyFrames(
1195             {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1196              TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerGpuDeadlineMissed,
1197              DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
1198     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1199                                       TimeStatsHelper::GameModeStandard, JankType::DisplayHAL,
1200                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1201                                       APP_DEADLINE_DELTA_3MS});
1202     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1203                                       TimeStatsHelper::GameModeStandard,
1204                                       JankType::AppDeadlineMissed, DISPLAY_DEADLINE_DELTA,
1205                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
1206     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1207                                       TimeStatsHelper::GameModeStandard,
1208                                       JankType::SurfaceFlingerScheduling, DISPLAY_DEADLINE_DELTA,
1209                                       DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_2MS});
1210     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1211                                       TimeStatsHelper::GameModeStandard, JankType::PredictionError,
1212                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1213                                       APP_DEADLINE_DELTA_2MS});
1214     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1215                                       TimeStatsHelper::GameModeStandard,
1216                                       JankType::AppDeadlineMissed | JankType::BufferStuffing,
1217                                       DISPLAY_DEADLINE_DELTA, APP_DEADLINE_DELTA_2MS,
1218                                       APP_DEADLINE_DELTA_2MS});
1219     mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1220                                       TimeStatsHelper::GameModeStandard, JankType::None,
1221                                       DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1222                                       APP_DEADLINE_DELTA_3MS});
1223 
1224     std::string pulledData;
1225     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1226 
1227     SurfaceflingerStatsLayerInfoWrapper atomList;
1228     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1229     ASSERT_EQ(atomList.atom_size(), 1);
1230     const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
1231 
1232     EXPECT_EQ(atom.layer_name(), genLayerName(LAYER_ID_0));
1233     EXPECT_EQ(atom.total_frames(), 1);
1234     EXPECT_EQ(atom.dropped_frames(), 0);
1235     EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1236     EXPECT_THAT(atom.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1237     EXPECT_THAT(atom.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1238     EXPECT_THAT(atom.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1239     EXPECT_THAT(atom.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1240     EXPECT_THAT(atom.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1241     EXPECT_EQ(atom.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1242     EXPECT_EQ(atom.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1243     EXPECT_EQ(atom.uid(), UID_0);
1244     EXPECT_EQ(atom.total_timeline_frames(), 8);
1245     EXPECT_EQ(atom.total_janky_frames(), 7);
1246     EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1247     EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1248     EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1249     EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1250     EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1251     EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1252     EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 1);
1253     EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1254     EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1255     EXPECT_THAT(atom.set_frame_rate_vote().frame_rate(), testing::FloatEq(frameRate60.frameRate));
1256     EXPECT_EQ((int)atom.set_frame_rate_vote().frame_rate_compatibility(),
1257               (int)frameRate60.frameRateCompatibility);
1258     EXPECT_EQ((int)atom.set_frame_rate_vote().seamlessness(), (int)frameRate60.seamlessness);
1259     EXPECT_THAT(atom.app_deadline_misses(), HistogramEq(buildExpectedHistogram({3, 2}, {4, 3})));
1260     EXPECT_EQ(atom.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
1261 
1262     SFTimeStatsGlobalProto globalProto;
1263     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1264 
1265     EXPECT_EQ(0, globalProto.stats_size());
1266 
1267     // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1268     // be global stats
1269     const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1270     std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1271     EXPECT_THAT(result, HasSubstr(expectedResult));
1272     expectedResult = "jankyFrames = " + std::to_string(7);
1273     EXPECT_THAT(result, HasSubstr(expectedResult));
1274     expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1275     EXPECT_THAT(result, HasSubstr(expectedResult));
1276     expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1277     EXPECT_THAT(result, HasSubstr(expectedResult));
1278     expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1279     EXPECT_THAT(result, HasSubstr(expectedResult));
1280     expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1281     EXPECT_THAT(result, HasSubstr(expectedResult));
1282     expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1283     EXPECT_THAT(result, HasSubstr(expectedResult));
1284     expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1285     EXPECT_THAT(result, HasSubstr(expectedResult));
1286     expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1287     EXPECT_THAT(result, HasSubstr(expectedResult));
1288 
1289     std::string expectedMissing = "uid = " + std::to_string(UID_0);
1290     EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
1291 }
1292 
TEST_F(TimeStatsTest,layerStatsCallback_multipleGameModes)1293 TEST_F(TimeStatsTest, layerStatsCallback_multipleGameModes) {
1294     constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1295     constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1296     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1297 
1298     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1299                      TimeStatsHelper::GameModeStandard);
1300     for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1301         mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1302     }
1303     for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1304         mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1305     }
1306     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, {},
1307                      TimeStatsHelper::GameModeStandard);
1308 
1309     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, {},
1310                      TimeStatsHelper::GameModePerformance);
1311 
1312     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 4000000, {}, TimeStatsHelper::GameModeBattery);
1313     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 5, 4000000, {}, TimeStatsHelper::GameModeBattery);
1314 
1315     std::string pulledData;
1316     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1317 
1318     SurfaceflingerStatsLayerInfoWrapper atomList;
1319     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1320     // The first time record is never uploaded to stats.
1321     ASSERT_EQ(atomList.atom_size(), 3);
1322     // Layers are ordered based on the hash in LayerStatsKey. For this test, the order happens to
1323     // be: 0 - Battery 1 - Performance 2 - Standard
1324     const SurfaceflingerStatsLayerInfo& atom0 = atomList.atom(0);
1325 
1326     EXPECT_EQ(atom0.layer_name(), genLayerName(LAYER_ID_0));
1327     EXPECT_EQ(atom0.total_frames(), 2);
1328     EXPECT_EQ(atom0.dropped_frames(), 0);
1329     EXPECT_THAT(atom0.present_to_present(), HistogramEq(buildExpectedHistogram({0, 1}, {1, 1})));
1330     EXPECT_THAT(atom0.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {2})));
1331     EXPECT_THAT(atom0.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {2})));
1332     EXPECT_THAT(atom0.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {2})));
1333     EXPECT_THAT(atom0.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1334     EXPECT_THAT(atom0.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {2})));
1335     EXPECT_EQ(atom0.late_acquire_frames(), 0);
1336     EXPECT_EQ(atom0.bad_desired_present_frames(), 0);
1337     EXPECT_EQ(atom0.uid(), UID_0);
1338     EXPECT_EQ(atom0.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1339     EXPECT_EQ(atom0.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1340     EXPECT_EQ(atom0.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_BATTERY);
1341 
1342     const SurfaceflingerStatsLayerInfo& atom1 = atomList.atom(1);
1343 
1344     EXPECT_EQ(atom1.layer_name(), genLayerName(LAYER_ID_0));
1345     EXPECT_EQ(atom1.total_frames(), 1);
1346     EXPECT_EQ(atom1.dropped_frames(), 0);
1347     EXPECT_THAT(atom1.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1348     EXPECT_THAT(atom1.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1349     EXPECT_THAT(atom1.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1350     EXPECT_THAT(atom1.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1351     EXPECT_THAT(atom1.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1352     EXPECT_THAT(atom1.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1353     EXPECT_EQ(atom1.late_acquire_frames(), 0);
1354     EXPECT_EQ(atom1.bad_desired_present_frames(), 0);
1355     EXPECT_EQ(atom1.uid(), UID_0);
1356     EXPECT_EQ(atom1.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1357     EXPECT_EQ(atom1.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1358     EXPECT_EQ(atom1.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_PERFORMANCE);
1359 
1360     const SurfaceflingerStatsLayerInfo& atom2 = atomList.atom(2);
1361 
1362     EXPECT_EQ(atom2.layer_name(), genLayerName(LAYER_ID_0));
1363     EXPECT_EQ(atom2.total_frames(), 1);
1364     EXPECT_EQ(atom2.dropped_frames(), 0);
1365     EXPECT_THAT(atom2.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1366     EXPECT_THAT(atom2.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1367     EXPECT_THAT(atom2.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1368     EXPECT_THAT(atom2.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1369     EXPECT_THAT(atom2.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1370     EXPECT_THAT(atom2.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1371     EXPECT_EQ(atom2.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1372     EXPECT_EQ(atom2.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1373     EXPECT_EQ(atom2.uid(), UID_0);
1374     EXPECT_EQ(atom2.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1375     EXPECT_EQ(atom2.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1376     EXPECT_EQ(atom2.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
1377 }
1378 
TEST_F(TimeStatsTest,layerStatsCallback_pullsMultipleLayers)1379 TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1380     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1381 
1382     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1383     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1384     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1385     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1386 
1387     std::string pulledData;
1388     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1389 
1390     SurfaceflingerStatsLayerInfoWrapper atomList;
1391     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1392     ASSERT_EQ(atomList.atom_size(), 2);
1393     std::vector<std::string> actualLayerNames = {atomList.atom(0).layer_name(),
1394                                                  atomList.atom(1).layer_name()};
1395     EXPECT_THAT(actualLayerNames,
1396                 UnorderedElementsAre(genLayerName(LAYER_ID_0), genLayerName(LAYER_ID_1)));
1397 }
1398 
TEST_F(TimeStatsTest,layerStatsCallback_pullsMultipleBuckets)1399 TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1400     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1401 
1402     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1403     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1404     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1405     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1406 
1407     // Now make sure that TimeStats flushes global stats to set the callback.
1408     mTimeStats->setPowerMode(PowerMode::ON);
1409     mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1410     mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1411 
1412     std::string pulledData;
1413     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1414 
1415     SurfaceflingerStatsLayerInfoWrapper atomList;
1416     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1417     ASSERT_EQ(atomList.atom_size(), 1);
1418     const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
1419     EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1, 2}, {2, 1})));
1420 }
1421 
TEST_F(TimeStatsTest,layerStatsCallback_limitsHistogramBuckets)1422 TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
1423     mTimeStats = std::make_unique<impl::TimeStats>(std::nullopt, 1);
1424     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1425 
1426     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1427     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1428     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1429     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1430 
1431     std::string pulledData;
1432     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1433 
1434     SurfaceflingerStatsLayerInfoWrapper atomList;
1435     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1436     ASSERT_EQ(atomList.atom_size(), 1);
1437     const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
1438     EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1439 }
1440 
TEST_F(TimeStatsTest,layerStatsCallback_limitsLayers)1441 TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
1442     mTimeStats = std::make_unique<impl::TimeStats>(1, std::nullopt);
1443     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1444 
1445     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1446     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1447     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1448     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1449     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1450 
1451     std::string pulledData;
1452     EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1453 
1454     SurfaceflingerStatsLayerInfoWrapper atomList;
1455     ASSERT_TRUE(atomList.ParseFromString(pulledData));
1456     ASSERT_EQ(atomList.atom_size(), 1);
1457     EXPECT_EQ(atomList.atom(0).layer_name(), genLayerName(LAYER_ID_1));
1458 }
1459 
TEST_F(TimeStatsTest,canSurviveMonkey)1460 TEST_F(TimeStatsTest, canSurviveMonkey) {
1461     if (g_noSlowTests) {
1462         GTEST_SKIP();
1463     }
1464 
1465     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1466 
1467     for (size_t i = 0; i < 10000000; ++i) {
1468         const int32_t layerId = genRandomInt32(-1, 10);
1469         const int32_t frameNumber = genRandomInt32(1, 10);
1470         switch (genRandomInt32(0, 100)) {
1471             case 0:
1472                 ALOGV("removeTimeRecord");
1473                 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
1474                 continue;
1475             case 1:
1476                 ALOGV("onDestroy");
1477                 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
1478                 continue;
1479         }
1480         TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1481         const int32_t ts = genRandomInt32(1, 1000000000);
1482         ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
1483         setTimeStamp(type, layerId, frameNumber, ts, {}, kGameMode);
1484     }
1485 }
1486 
TEST_F(TimeStatsTest,refreshRateIsClampedToNearestBucket)1487 TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) {
1488     // this stat is not in the proto so verify by checking the string dump
1489     const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) {
1490         EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
1491         EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1492 
1493         insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1494         mTimeStats->incrementJankyFrames({fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0),
1495                                           kGameMode, JankType::None, 0, 0, 0});
1496         const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1497         std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps";
1498         EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps;
1499     };
1500 
1501     verifyRefreshRateBucket(Fps(91.f), 90);
1502     verifyRefreshRateBucket(Fps(89.f), 90);
1503 
1504     verifyRefreshRateBucket(Fps(61.f), 60);
1505     verifyRefreshRateBucket(Fps(59.f), 60);
1506 
1507     verifyRefreshRateBucket(Fps(31.f), 30);
1508     verifyRefreshRateBucket(Fps(29.f), 30);
1509 }
1510 
1511 } // namespace
1512 } // namespace android
1513 
1514 // TODO(b/129481165): remove the #pragma below and fix conversion issues
1515 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
1516