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