• 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 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <log/log.h>
24 #include <utils/String16.h>
25 #include <utils/Vector.h>
26 
27 #include <random>
28 #include <unordered_set>
29 
30 #include "TimeStats/TimeStats.h"
31 
32 #include "libsurfaceflinger_unittest_main.h"
33 
34 using namespace android::surfaceflinger;
35 using namespace google::protobuf;
36 
37 namespace android {
38 namespace {
39 
40 using testing::Contains;
41 using testing::SizeIs;
42 using testing::UnorderedElementsAre;
43 
44 // clang-format off
45 #define FMT_PROTO          true
46 #define FMT_STRING         false
47 #define LAYER_ID_0         0
48 #define LAYER_ID_1         1
49 #define LAYER_ID_INVALID   -1
50 #define NUM_LAYERS         1
51 #define NUM_LAYERS_INVALID "INVALID"
52 
53 enum InputCommand : int32_t {
54     ENABLE                 = 0,
55     DISABLE                = 1,
56     CLEAR                  = 2,
57     DUMP_ALL               = 3,
58     DUMP_MAXLAYERS_1       = 4,
59     DUMP_MAXLAYERS_INVALID = 5,
60     INPUT_COMMAND_BEGIN    = ENABLE,
61     INPUT_COMMAND_END      = DUMP_MAXLAYERS_INVALID,
62     INPUT_COMMAND_RANGE    = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
63 };
64 
65 enum TimeStamp : int32_t {
66     POST                   = 0,
67     ACQUIRE                = 1,
68     ACQUIRE_FENCE          = 2,
69     LATCH                  = 3,
70     DESIRED                = 4,
71     PRESENT                = 5,
72     PRESENT_FENCE          = 6,
73     TIME_STAMP_BEGIN       = POST,
74     TIME_STAMP_END         = PRESENT,
75     TIME_STAMP_RANGE       = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
76 };
77 
78 static const TimeStamp NORMAL_SEQUENCE[] = {
79         TimeStamp::POST,
80         TimeStamp::ACQUIRE,
81         TimeStamp::LATCH,
82         TimeStamp::DESIRED,
83         TimeStamp::PRESENT,
84 };
85 
86 static const TimeStamp NORMAL_SEQUENCE_2[] = {
87         TimeStamp::POST,
88         TimeStamp::ACQUIRE_FENCE,
89         TimeStamp::LATCH,
90         TimeStamp::DESIRED,
91         TimeStamp::PRESENT_FENCE,
92 };
93 
94 static const TimeStamp UNORDERED_SEQUENCE[] = {
95         TimeStamp::ACQUIRE,
96         TimeStamp::LATCH,
97         TimeStamp::POST,
98         TimeStamp::DESIRED,
99         TimeStamp::PRESENT,
100 };
101 
102 static const TimeStamp INCOMPLETE_SEQUENCE[] = {
103         TimeStamp::POST,
104 };
105 // clang-format on
106 
107 class TimeStatsTest : public testing::Test {
108 public:
TimeStatsTest()109     TimeStatsTest() {
110         const ::testing::TestInfo* const test_info =
111                 ::testing::UnitTest::GetInstance()->current_test_info();
112         ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
113     }
114 
~TimeStatsTest()115     ~TimeStatsTest() {
116         const ::testing::TestInfo* const test_info =
117                 ::testing::UnitTest::GetInstance()->current_test_info();
118         ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
119     }
120 
121     std::string inputCommand(InputCommand cmd, bool useProto);
122 
123     void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
124 
125     int32_t genRandomInt32(int32_t begin, int32_t end);
126 
127     template <size_t N>
insertTimeRecord(const TimeStamp (& sequence)[N],int32_t id,uint64_t frameNumber,nsecs_t ts)128     void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
129                           nsecs_t ts) {
130         for (size_t i = 0; i < N; i++, ts += 1000000) {
131             setTimeStamp(sequence[i], id, frameNumber, ts);
132         }
133     }
134 
135     std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
136     std::unique_ptr<TimeStats> mTimeStats = std::make_unique<impl::TimeStats>();
137 };
138 
inputCommand(InputCommand cmd,bool useProto)139 std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
140     std::string result;
141     Vector<String16> args;
142 
143     switch (cmd) {
144         case InputCommand::ENABLE:
145             args.push_back(String16("-enable"));
146             break;
147         case InputCommand::DISABLE:
148             args.push_back(String16("-disable"));
149             break;
150         case InputCommand::CLEAR:
151             args.push_back(String16("-clear"));
152             break;
153         case InputCommand::DUMP_ALL:
154             args.push_back(String16("-dump"));
155             break;
156         case InputCommand::DUMP_MAXLAYERS_1:
157             args.push_back(String16("-dump"));
158             args.push_back(String16("-maxlayers"));
159             args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
160             break;
161         case InputCommand::DUMP_MAXLAYERS_INVALID:
162             args.push_back(String16("-dump"));
163             args.push_back(String16("-maxlayers"));
164             args.push_back(String16(NUM_LAYERS_INVALID));
165             break;
166         default:
167             ALOGD("Invalid control command");
168     }
169 
170     EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
171     return result;
172 }
173 
genLayerName(int32_t layerID)174 static std::string genLayerName(int32_t layerID) {
175     return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
176 }
177 
setTimeStamp(TimeStamp type,int32_t id,uint64_t frameNumber,nsecs_t ts)178 void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
179     switch (type) {
180         case TimeStamp::POST:
181             ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id), ts));
182             break;
183         case TimeStamp::ACQUIRE:
184             ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
185             break;
186         case TimeStamp::ACQUIRE_FENCE:
187             ASSERT_NO_FATAL_FAILURE(
188                     mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
189             break;
190         case TimeStamp::LATCH:
191             ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
192             break;
193         case TimeStamp::DESIRED:
194             ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
195             break;
196         case TimeStamp::PRESENT:
197             ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts));
198             break;
199         case TimeStamp::PRESENT_FENCE:
200             ASSERT_NO_FATAL_FAILURE(
201                     mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
202             break;
203         default:
204             ALOGD("Invalid timestamp type");
205     }
206 }
207 
genRandomInt32(int32_t begin,int32_t end)208 int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
209     std::uniform_int_distribution<int32_t> distr(begin, end);
210     return distr(mRandomEngine);
211 }
212 
TEST_F(TimeStatsTest,canEnableAndDisableTimeStats)213 TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
214     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
215     ASSERT_TRUE(mTimeStats->isEnabled());
216 
217     EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
218     ASSERT_FALSE(mTimeStats->isEnabled());
219 }
220 
TEST_F(TimeStatsTest,canIncreaseGlobalStats)221 TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
222     constexpr size_t TOTAL_FRAMES = 5;
223     constexpr size_t MISSED_FRAMES = 4;
224     constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
225 
226     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
227 
228     for (size_t i = 0; i < TOTAL_FRAMES; i++) {
229         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
230     }
231     for (size_t i = 0; i < MISSED_FRAMES; i++) {
232         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
233     }
234     for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
235         ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
236     }
237 
238     SFTimeStatsGlobalProto globalProto;
239     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
240 
241     ASSERT_TRUE(globalProto.has_total_frames());
242     EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
243     ASSERT_TRUE(globalProto.has_missed_frames());
244     EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
245     ASSERT_TRUE(globalProto.has_client_composition_frames());
246     EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
247 }
248 
TEST_F(TimeStatsTest,canInsertGlobalPresentToPresent)249 TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
250     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
251 
252     ASSERT_NO_FATAL_FAILURE(
253             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
254     ASSERT_NO_FATAL_FAILURE(
255             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
256 
257     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
258     ASSERT_NO_FATAL_FAILURE(
259             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
260     ASSERT_NO_FATAL_FAILURE(
261             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
262 
263     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
264     ASSERT_NO_FATAL_FAILURE(
265             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
266     ASSERT_NO_FATAL_FAILURE(
267             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
268 
269     SFTimeStatsGlobalProto globalProto;
270     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
271 
272     ASSERT_EQ(1, globalProto.present_to_present_size());
273     const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
274     EXPECT_EQ(1, histogramProto.frame_count());
275     EXPECT_EQ(2, histogramProto.time_millis());
276 }
277 
TEST_F(TimeStatsTest,canInsertOneLayerTimeStats)278 TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
279     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
280 
281     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
282     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
283 
284     SFTimeStatsGlobalProto globalProto;
285     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
286 
287     ASSERT_EQ(1, globalProto.stats_size());
288     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
289     ASSERT_TRUE(layerProto.has_layer_name());
290     EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
291     ASSERT_TRUE(layerProto.has_total_frames());
292     EXPECT_EQ(1, layerProto.total_frames());
293     ASSERT_EQ(6, layerProto.deltas_size());
294     for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
295         ASSERT_EQ(1, deltaProto.histograms_size());
296         const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
297         EXPECT_EQ(1, histogramProto.frame_count());
298         if ("post2acquire" == deltaProto.delta_name()) {
299             EXPECT_EQ(1, histogramProto.time_millis());
300         } else if ("post2present" == deltaProto.delta_name()) {
301             EXPECT_EQ(4, histogramProto.time_millis());
302         } else if ("acquire2present" == deltaProto.delta_name()) {
303             EXPECT_EQ(3, histogramProto.time_millis());
304         } else if ("latch2present" == deltaProto.delta_name()) {
305             EXPECT_EQ(2, histogramProto.time_millis());
306         } else if ("desired2present" == deltaProto.delta_name()) {
307             EXPECT_EQ(1, histogramProto.time_millis());
308         } else if ("present2present" == deltaProto.delta_name()) {
309             EXPECT_EQ(1, histogramProto.time_millis());
310         } else {
311             FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
312         }
313     }
314 }
315 
TEST_F(TimeStatsTest,canNotInsertInvalidLayerNameTimeStats)316 TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
317     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
318 
319     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
320     insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
321 
322     SFTimeStatsGlobalProto globalProto;
323     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
324 
325     ASSERT_EQ(0, globalProto.stats_size());
326 }
327 
TEST_F(TimeStatsTest,canInsertMultipleLayersTimeStats)328 TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
329     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
330 
331     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
332     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
333     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
334     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
335 
336     SFTimeStatsGlobalProto globalProto;
337     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
338 
339     EXPECT_EQ(2, globalProto.stats_size());
340 }
341 
TEST_F(TimeStatsTest,canInsertUnorderedLayerTimeStats)342 TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
343     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
344 
345     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
346     insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
347 
348     SFTimeStatsGlobalProto globalProto;
349     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
350 
351     ASSERT_EQ(1, globalProto.stats_size());
352     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
353     ASSERT_TRUE(layerProto.has_layer_name());
354     EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
355     ASSERT_TRUE(layerProto.has_total_frames());
356     EXPECT_EQ(1, layerProto.total_frames());
357     ASSERT_EQ(6, layerProto.deltas_size());
358     for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
359         ASSERT_EQ(1, deltaProto.histograms_size());
360         const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
361         EXPECT_EQ(1, histogramProto.frame_count());
362         if ("post2acquire" == deltaProto.delta_name()) {
363             EXPECT_EQ(0, histogramProto.time_millis());
364         } else if ("post2present" == deltaProto.delta_name()) {
365             EXPECT_EQ(2, histogramProto.time_millis());
366         } else if ("acquire2present" == deltaProto.delta_name()) {
367             EXPECT_EQ(2, histogramProto.time_millis());
368         } else if ("latch2present" == deltaProto.delta_name()) {
369             EXPECT_EQ(2, histogramProto.time_millis());
370         } else if ("desired2present" == deltaProto.delta_name()) {
371             EXPECT_EQ(1, histogramProto.time_millis());
372         } else if ("present2present" == deltaProto.delta_name()) {
373             EXPECT_EQ(1, histogramProto.time_millis());
374         } else {
375             FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
376         }
377     }
378 }
379 
TEST_F(TimeStatsTest,recordRefreshRateNewConfigs)380 TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
381     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
382 
383     uint32_t fpsOne = 30;
384     uint32_t fpsTwo = 90;
385     uint64_t millisOne = 5000;
386     uint64_t millisTwo = 7000;
387 
388     mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
389     mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
390 
391     SFTimeStatsGlobalProto globalProto;
392     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
393 
394     SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
395     SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
396     expectedConfigOne->set_fps(fpsOne);
397     expectedBucketOne.set_duration_millis(millisOne);
398 
399     SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
400     SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
401     expectedConfigTwo->set_fps(fpsTwo);
402     expectedBucketTwo.set_duration_millis(millisTwo);
403 
404     EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
405 
406     std::unordered_set<uint32_t> seen_fps;
407     for (const auto& bucket : globalProto.display_config_stats()) {
408         seen_fps.emplace(bucket.config().fps());
409         if (fpsOne == bucket.config().fps()) {
410             EXPECT_EQ(millisOne, bucket.duration_millis());
411         } else if (fpsTwo == bucket.config().fps()) {
412             EXPECT_EQ(millisTwo, bucket.duration_millis());
413         } else {
414             FAIL() << "Unknown fps: " << bucket.config().fps();
415         }
416     }
417     EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
418 }
419 
TEST_F(TimeStatsTest,recordRefreshRateUpdatesConfig)420 TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
421     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
422 
423     uint32_t fps = 30;
424     uint64_t millisOne = 5000;
425     uint64_t millisTwo = 7000;
426 
427     mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
428     mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
429 
430     SFTimeStatsGlobalProto globalProto;
431     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
432     EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
433     EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
434     EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
435 }
436 
TEST_F(TimeStatsTest,canRemoveTimeRecord)437 TEST_F(TimeStatsTest, canRemoveTimeRecord) {
438     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
439 
440     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
441     insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
442     ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
443     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
444 
445     SFTimeStatsGlobalProto globalProto;
446     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
447 
448     ASSERT_EQ(1, globalProto.stats_size());
449     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
450     ASSERT_TRUE(layerProto.has_total_frames());
451     EXPECT_EQ(1, layerProto.total_frames());
452 }
453 
TEST_F(TimeStatsTest,canRecoverFromIncompleteTimeRecordError)454 TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
455     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
456 
457     uint64_t frameNumber = 1;
458     nsecs_t ts = 1000000;
459     insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
460     for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
461         frameNumber++;
462         ts += 1000000;
463         insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
464     }
465 
466     SFTimeStatsGlobalProto globalProto;
467     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
468 
469     ASSERT_EQ(1, globalProto.stats_size());
470     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
471     ASSERT_TRUE(layerProto.has_total_frames());
472     EXPECT_EQ(1, layerProto.total_frames());
473 }
474 
TEST_F(TimeStatsTest,layerTimeStatsOnDestroy)475 TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
476     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
477 
478     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
479     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
480     ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
481     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
482 
483     SFTimeStatsGlobalProto globalProto;
484     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
485 
486     ASSERT_EQ(1, globalProto.stats_size());
487     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
488     ASSERT_TRUE(layerProto.has_total_frames());
489     EXPECT_EQ(1, layerProto.total_frames());
490 }
491 
TEST_F(TimeStatsTest,canClearTimeStats)492 TEST_F(TimeStatsTest, canClearTimeStats) {
493     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
494 
495     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
496     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
497     ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
498     ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
499     ASSERT_NO_FATAL_FAILURE(
500             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
501     ASSERT_NO_FATAL_FAILURE(
502             mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
503     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
504     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
505 
506     EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
507 
508     SFTimeStatsGlobalProto globalProto;
509     ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
510 
511     EXPECT_EQ(0, globalProto.total_frames());
512     EXPECT_EQ(0, globalProto.missed_frames());
513     EXPECT_EQ(0, globalProto.client_composition_frames());
514     EXPECT_EQ(0, globalProto.present_to_present_size());
515     EXPECT_EQ(0, globalProto.stats_size());
516 }
517 
TEST_F(TimeStatsTest,canDumpWithMaxLayers)518 TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
519     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
520 
521     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
522     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
523     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
524     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
525     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
526 
527     SFTimeStatsGlobalProto globalProto;
528     ASSERT_TRUE(
529             globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
530 
531     ASSERT_EQ(1, globalProto.stats_size());
532     const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
533     ASSERT_TRUE(layerProto.has_layer_name());
534     EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
535     ASSERT_TRUE(layerProto.has_total_frames());
536     EXPECT_EQ(2, layerProto.total_frames());
537 }
538 
TEST_F(TimeStatsTest,canDumpWithInvalidMaxLayers)539 TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
540     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
541 
542     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
543     insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
544 
545     SFTimeStatsGlobalProto globalProto;
546     ASSERT_TRUE(globalProto.ParseFromString(
547             inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
548 
549     ASSERT_EQ(0, globalProto.stats_size());
550 }
551 
TEST_F(TimeStatsTest,canSurviveMonkey)552 TEST_F(TimeStatsTest, canSurviveMonkey) {
553     if (g_noSlowTests) {
554         GTEST_SKIP();
555     }
556 
557     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
558 
559     for (size_t i = 0; i < 10000000; ++i) {
560         const int32_t layerID = genRandomInt32(-1, 10);
561         const int32_t frameNumber = genRandomInt32(1, 10);
562         switch (genRandomInt32(0, 100)) {
563             case 0:
564                 ALOGV("removeTimeRecord");
565                 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber));
566                 continue;
567             case 1:
568                 ALOGV("onDestroy");
569                 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID));
570                 continue;
571         }
572         TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
573         const int32_t ts = genRandomInt32(1, 1000000000);
574         ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts);
575         setTimeStamp(type, layerID, frameNumber, ts);
576     }
577 }
578 
579 } // namespace
580 } // namespace android
581