blob: ffacbfef16b70f7b445d0baf1cc3f5a7ba6af114 [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) {
174 return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
175}
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
212TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
213 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
214 ASSERT_TRUE(mTimeStats->isEnabled());
215
216 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
217 ASSERT_FALSE(mTimeStats->isEnabled());
218}
219
220TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
221 constexpr size_t TOTAL_FRAMES = 5;
222 constexpr size_t MISSED_FRAMES = 4;
223 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
224
225 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
226
227 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
228 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
229 }
230 for (size_t i = 0; i < MISSED_FRAMES; i++) {
231 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
232 }
233 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
234 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
235 }
236
237 SFTimeStatsGlobalProto globalProto;
238 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
239
240 ASSERT_TRUE(globalProto.has_total_frames());
241 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
242 ASSERT_TRUE(globalProto.has_missed_frames());
243 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
244 ASSERT_TRUE(globalProto.has_client_composition_frames());
245 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
246}
247
248TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
249 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
250
251 ASSERT_NO_FATAL_FAILURE(
252 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
253 ASSERT_NO_FATAL_FAILURE(
254 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
255
256 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
257 ASSERT_NO_FATAL_FAILURE(
258 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
259 ASSERT_NO_FATAL_FAILURE(
260 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
261
262 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
263 ASSERT_NO_FATAL_FAILURE(
264 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
265 ASSERT_NO_FATAL_FAILURE(
266 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
267
268 SFTimeStatsGlobalProto globalProto;
269 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
270
271 ASSERT_EQ(1, globalProto.present_to_present_size());
272 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
273 EXPECT_EQ(1, histogramProto.frame_count());
274 EXPECT_EQ(2, histogramProto.time_millis());
275}
276
277TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
278 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
279
280 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
281 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
282
283 SFTimeStatsGlobalProto globalProto;
284 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
285
286 ASSERT_EQ(1, globalProto.stats_size());
287 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
288 ASSERT_TRUE(layerProto.has_layer_name());
289 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
290 ASSERT_TRUE(layerProto.has_total_frames());
291 EXPECT_EQ(1, layerProto.total_frames());
292 ASSERT_EQ(6, layerProto.deltas_size());
293 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
294 ASSERT_EQ(1, deltaProto.histograms_size());
295 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
296 EXPECT_EQ(1, histogramProto.frame_count());
297 if ("post2acquire" == deltaProto.delta_name()) {
298 EXPECT_EQ(1, histogramProto.time_millis());
299 } else if ("post2present" == deltaProto.delta_name()) {
300 EXPECT_EQ(4, histogramProto.time_millis());
301 } else if ("acquire2present" == deltaProto.delta_name()) {
302 EXPECT_EQ(3, histogramProto.time_millis());
303 } else if ("latch2present" == deltaProto.delta_name()) {
304 EXPECT_EQ(2, histogramProto.time_millis());
305 } else if ("desired2present" == deltaProto.delta_name()) {
306 EXPECT_EQ(1, histogramProto.time_millis());
307 } else if ("present2present" == deltaProto.delta_name()) {
308 EXPECT_EQ(1, histogramProto.time_millis());
309 } else {
310 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
311 }
312 }
313}
314
315TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
316 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
317
318 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
319 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
320
321 SFTimeStatsGlobalProto globalProto;
322 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
323
324 ASSERT_EQ(0, globalProto.stats_size());
325}
326
327TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
328 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
329
330 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
331 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
332 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
333 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
334
335 SFTimeStatsGlobalProto globalProto;
336 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
337
338 EXPECT_EQ(2, globalProto.stats_size());
339}
340
341TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
342 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
343
344 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
345 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
346
347 SFTimeStatsGlobalProto globalProto;
348 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
349
350 ASSERT_EQ(1, globalProto.stats_size());
351 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
352 ASSERT_TRUE(layerProto.has_layer_name());
353 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
354 ASSERT_TRUE(layerProto.has_total_frames());
355 EXPECT_EQ(1, layerProto.total_frames());
356 ASSERT_EQ(6, layerProto.deltas_size());
357 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
358 ASSERT_EQ(1, deltaProto.histograms_size());
359 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
360 EXPECT_EQ(1, histogramProto.frame_count());
361 if ("post2acquire" == deltaProto.delta_name()) {
362 EXPECT_EQ(0, histogramProto.time_millis());
363 } else if ("post2present" == deltaProto.delta_name()) {
364 EXPECT_EQ(2, histogramProto.time_millis());
365 } else if ("acquire2present" == deltaProto.delta_name()) {
366 EXPECT_EQ(2, histogramProto.time_millis());
367 } else if ("latch2present" == deltaProto.delta_name()) {
368 EXPECT_EQ(2, histogramProto.time_millis());
369 } else if ("desired2present" == deltaProto.delta_name()) {
370 EXPECT_EQ(1, histogramProto.time_millis());
371 } else if ("present2present" == deltaProto.delta_name()) {
372 EXPECT_EQ(1, histogramProto.time_millis());
373 } else {
374 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
375 }
376 }
377}
378
Alec Mourifb571ea2019-01-24 18:42:10 -0800379TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
380 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
381
382 uint32_t fpsOne = 30;
383 uint32_t fpsTwo = 90;
384 uint64_t millisOne = 5000;
385 uint64_t millisTwo = 7000;
386
387 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
388 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
389
390 SFTimeStatsGlobalProto globalProto;
391 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
392
393 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
394 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
395 expectedConfigOne->set_fps(fpsOne);
396 expectedBucketOne.set_duration_millis(millisOne);
397
398 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
399 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
400 expectedConfigTwo->set_fps(fpsTwo);
401 expectedBucketTwo.set_duration_millis(millisTwo);
402
403 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
404
405 std::unordered_set<uint32_t> seen_fps;
406 for (const auto& bucket : globalProto.display_config_stats()) {
407 seen_fps.emplace(bucket.config().fps());
408 if (fpsOne == bucket.config().fps()) {
409 EXPECT_EQ(millisOne, bucket.duration_millis());
410 } else if (fpsTwo == bucket.config().fps()) {
411 EXPECT_EQ(millisTwo, bucket.duration_millis());
412 } else {
413 FAIL() << "Unknown fps: " << bucket.config().fps();
414 }
415 }
416 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
417}
418
419TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
420 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
421
422 uint32_t fps = 30;
423 uint64_t millisOne = 5000;
424 uint64_t millisTwo = 7000;
425
426 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
427 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
428
429 SFTimeStatsGlobalProto globalProto;
430 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
431 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
432 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
433 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
434}
435
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800436TEST_F(TimeStatsTest, canRemoveTimeRecord) {
437 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
438
439 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
440 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
441 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
442 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
443
444 SFTimeStatsGlobalProto globalProto;
445 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
446
447 ASSERT_EQ(1, globalProto.stats_size());
448 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
449 ASSERT_TRUE(layerProto.has_total_frames());
450 EXPECT_EQ(1, layerProto.total_frames());
451}
452
453TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
454 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
455
456 uint64_t frameNumber = 1;
457 nsecs_t ts = 1000000;
458 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800459 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800460 frameNumber++;
461 ts += 1000000;
462 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
463 }
464
465 SFTimeStatsGlobalProto globalProto;
466 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
467
468 ASSERT_EQ(1, globalProto.stats_size());
469 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
470 ASSERT_TRUE(layerProto.has_total_frames());
471 EXPECT_EQ(1, layerProto.total_frames());
472}
473
474TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
475 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
476
477 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
478 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
479 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
480 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
481
482 SFTimeStatsGlobalProto globalProto;
483 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
484
485 ASSERT_EQ(1, globalProto.stats_size());
486 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
487 ASSERT_TRUE(layerProto.has_total_frames());
488 EXPECT_EQ(1, layerProto.total_frames());
489}
490
491TEST_F(TimeStatsTest, canClearTimeStats) {
492 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
493
494 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
495 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
496 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
497 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
498 ASSERT_NO_FATAL_FAILURE(
499 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
500 ASSERT_NO_FATAL_FAILURE(
501 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
502 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
503 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
504
505 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
506
507 SFTimeStatsGlobalProto globalProto;
508 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
509
510 EXPECT_EQ(0, globalProto.total_frames());
511 EXPECT_EQ(0, globalProto.missed_frames());
512 EXPECT_EQ(0, globalProto.client_composition_frames());
513 EXPECT_EQ(0, globalProto.present_to_present_size());
514 EXPECT_EQ(0, globalProto.stats_size());
515}
516
517TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
518 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
519
520 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
521 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
522 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
523 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
524 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
525
526 SFTimeStatsGlobalProto globalProto;
527 ASSERT_TRUE(
528 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
529
530 ASSERT_EQ(1, globalProto.stats_size());
531 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
532 ASSERT_TRUE(layerProto.has_layer_name());
533 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
534 ASSERT_TRUE(layerProto.has_total_frames());
535 EXPECT_EQ(2, layerProto.total_frames());
536}
537
538TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
539 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
540
541 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
542 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
543
544 SFTimeStatsGlobalProto globalProto;
545 ASSERT_TRUE(globalProto.ParseFromString(
546 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
547
548 ASSERT_EQ(0, globalProto.stats_size());
549}
550
551TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -0800552 if (g_noSlowTests) {
553 GTEST_SKIP();
554 }
555
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800556 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
557
558 for (size_t i = 0; i < 10000000; ++i) {
559 const int32_t layerID = genRandomInt32(-1, 10);
560 const int32_t frameNumber = genRandomInt32(1, 10);
561 switch (genRandomInt32(0, 100)) {
562 case 0:
563 ALOGV("removeTimeRecord");
564 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber));
565 continue;
566 case 1:
567 ALOGV("onDestroy");
568 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID));
569 continue;
570 }
571 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
572 const int32_t ts = genRandomInt32(1, 1000000000);
573 ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts);
574 setTimeStamp(type, layerID, frameNumber, ts);
575 }
576}
577
578} // namespace
579} // namespace android