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