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