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