blob: f01e603f20ad9da4f3dc40da0bad936339163159 [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>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080023#include <log/log.h>
Mikael Pessa2e1608f2019-07-19 11:25:35 -070024#include <perfetto/trace/trace.pb.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080025#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());
Mikael Pessa2e1608f2019-07-19 11:25:35 -0700112
113 // Need to initialize tracing in process for testing, and only once per test suite.
114 static bool wasInitialized = false;
115 if (!wasInitialized) {
116 perfetto::TracingInitArgs args;
117 args.backends = perfetto::kInProcessBackend;
118 perfetto::Tracing::Initialize(args);
119 wasInitialized = true;
120 }
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800121 }
122
123 ~TimeStatsTest() {
124 const ::testing::TestInfo* const test_info =
125 ::testing::UnitTest::GetInstance()->current_test_info();
126 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
127 }
128
Mikael Pessa2e1608f2019-07-19 11:25:35 -0700129 void SetUp() override {
130 mTimeStats = std::make_unique<impl::TimeStats>();
131 mTimeStats->registerTracingDataSource();
132 }
133
134 void TearDown() override { mTimeStats.reset(); }
135
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800136 std::string inputCommand(InputCommand cmd, bool useProto);
137
138 void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
139
140 int32_t genRandomInt32(int32_t begin, int32_t end);
141
142 template <size_t N>
143 void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
144 nsecs_t ts) {
145 for (size_t i = 0; i < N; i++, ts += 1000000) {
146 setTimeStamp(sequence[i], id, frameNumber, ts);
147 }
148 }
149
Mikael Pessa2e1608f2019-07-19 11:25:35 -0700150 // Each tracing session can be used for a single block of Start -> Stop.
151 static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
152 perfetto::TraceConfig cfg;
153 cfg.set_duration_ms(500);
154 cfg.add_buffers()->set_size_kb(1024);
155 auto* ds_cfg = cfg.add_data_sources()->mutable_config();
156 ds_cfg->set_name(TimeStats::kTimeStatsDataSource);
157
158 auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
159 tracingSession->Setup(cfg);
160 return tracingSession;
161 }
162
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800163 std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
Mikael Pessa2e1608f2019-07-19 11:25:35 -0700164 std::unique_ptr<TimeStats> mTimeStats;
165 FenceToFenceTimeMap fenceFactory;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800166};
167
168std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
Yiwei Zhang5434a782018-12-05 18:06:32 -0800169 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800170 Vector<String16> args;
171
172 switch (cmd) {
173 case InputCommand::ENABLE:
174 args.push_back(String16("-enable"));
175 break;
176 case InputCommand::DISABLE:
177 args.push_back(String16("-disable"));
178 break;
179 case InputCommand::CLEAR:
180 args.push_back(String16("-clear"));
181 break;
182 case InputCommand::DUMP_ALL:
183 args.push_back(String16("-dump"));
184 break;
185 case InputCommand::DUMP_MAXLAYERS_1:
186 args.push_back(String16("-dump"));
187 args.push_back(String16("-maxlayers"));
188 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
189 break;
190 case InputCommand::DUMP_MAXLAYERS_INVALID:
191 args.push_back(String16("-dump"));
192 args.push_back(String16("-maxlayers"));
193 args.push_back(String16(NUM_LAYERS_INVALID));
194 break;
195 default:
196 ALOGD("Invalid control command");
197 }
198
Dominik Laskowskic2867142019-01-21 11:33:38 -0800199 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800200 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800201}
202
203static std::string genLayerName(int32_t layerID) {
204 return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
205}
206
207void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
208 switch (type) {
209 case TimeStamp::POST:
210 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id), ts));
211 break;
212 case TimeStamp::ACQUIRE:
213 ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
214 break;
215 case TimeStamp::ACQUIRE_FENCE:
216 ASSERT_NO_FATAL_FAILURE(
217 mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
218 break;
219 case TimeStamp::LATCH:
220 ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
221 break;
222 case TimeStamp::DESIRED:
223 ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
224 break;
225 case TimeStamp::PRESENT:
226 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts));
227 break;
228 case TimeStamp::PRESENT_FENCE:
229 ASSERT_NO_FATAL_FAILURE(
230 mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
231 break;
232 default:
233 ALOGD("Invalid timestamp type");
234 }
235}
236
237int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
238 std::uniform_int_distribution<int32_t> distr(begin, end);
239 return distr(mRandomEngine);
240}
241
Mikael Pessa2e1608f2019-07-19 11:25:35 -0700242TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) {
243 EXPECT_EQ(mTimeStats->miniDump(),
244 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
245 "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
246
247 const std::string layerName = "co.layername#0";
248 const int32_t layerID = 5;
249 mTimeStats->traceNewLayer(layerID, layerName);
250
251 EXPECT_EQ(mTimeStats->miniDump(),
252 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
253 "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
254
255 auto tracingSession = getTracingSessionForTest();
256 tracingSession->StartBlocking();
257 EXPECT_EQ(mTimeStats->miniDump(),
258 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
259 "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
260 mTimeStats->traceNewLayer(layerID, layerName);
261 EXPECT_EQ(mTimeStats->miniDump(),
262 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
263 "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
264 tracingSession->StopBlocking();
265}
266
267TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) {
268 EXPECT_EQ(mTimeStats->miniDump(),
269 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
270 "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
271
272 const std::string layerName = "co.layername#0";
273 const int32_t layerID = 5;
274 const int32_t secondLayerID = 6;
275
276 auto tracingSession = getTracingSessionForTest();
277 tracingSession->StartBlocking();
278 mTimeStats->traceNewLayer(layerID, layerName);
279 mTimeStats->traceNewLayer(secondLayerID, layerName);
280 EXPECT_EQ(mTimeStats->miniDump(),
281 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
282 "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n");
283 tracingSession->StopBlocking();
284
285 mTimeStats->onDestroy(layerID);
286 EXPECT_EQ(mTimeStats->miniDump(),
287 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
288 "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
289 mTimeStats->onDestroy(layerID);
290 EXPECT_EQ(mTimeStats->miniDump(),
291 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
292 "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
293 mTimeStats->onDestroy(secondLayerID);
294 EXPECT_EQ(mTimeStats->miniDump(),
295 "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
296 "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
297}
298
299TEST_F(TimeStatsTest, canTraceAfterAddingLayer) {
300 const std::string layerName = "co.layername#0";
301 const int32_t layerID = 1;
302 const uint32_t bufferID = 2;
303 const uint64_t frameNumber = 3;
304 const nsecs_t timestamp = 4;
305 const nsecs_t duration = 5;
306 const auto type = TimeStats::FrameEvent::POST;
307
308 {
309 auto tracingSession = getTracingSessionForTest();
310
311 tracingSession->StartBlocking();
312 // Clean up irrelevant traces.
313 tracingSession->ReadTraceBlocking();
314
315 mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
316 // Create second trace packet to finalize the previous one.
317 mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
318 tracingSession->StopBlocking();
319
320 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
321 EXPECT_EQ(raw_trace.size(), 0);
322 }
323
324 {
325 auto tracingSession = getTracingSessionForTest();
326
327 tracingSession->StartBlocking();
328 // Clean up irrelevant traces.
329 tracingSession->ReadTraceBlocking();
330
331 mTimeStats->traceNewLayer(layerID, layerName);
332 mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
333 // Create second trace packet to finalize the previous one.
334 mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
335 tracingSession->StopBlocking();
336
337 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
338 ASSERT_GT(raw_trace.size(), 0);
339
340 perfetto::protos::Trace trace;
341 ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
342 ASSERT_FALSE(trace.packet().empty());
343 EXPECT_EQ(trace.packet().size(), 1);
344
345 const auto& packet = trace.packet().Get(0);
346 ASSERT_TRUE(packet.has_timestamp());
347 EXPECT_EQ(packet.timestamp(), timestamp);
348 ASSERT_TRUE(packet.has_graphics_frame_event());
349 const auto& frame_event = packet.graphics_frame_event();
350 ASSERT_TRUE(frame_event.has_buffer_event());
351 const auto& buffer_event = frame_event.buffer_event();
352 ASSERT_TRUE(buffer_event.has_buffer_id());
353 EXPECT_EQ(buffer_event.buffer_id(), bufferID);
354 ASSERT_TRUE(buffer_event.has_frame_number());
355 EXPECT_EQ(buffer_event.frame_number(), frameNumber);
356 ASSERT_TRUE(buffer_event.has_type());
357 EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
358 ASSERT_TRUE(buffer_event.has_duration_ns());
359 EXPECT_EQ(buffer_event.duration_ns(), duration);
360 }
361}
362
363TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
364 const std::string layerName = "co.layername#0";
365 const int32_t layerID = 5;
366 const uint32_t bufferID = 4;
367 const uint64_t frameNumber = 3;
368 const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
369
370 {
371 auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
372 fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
373 auto tracingSession = getTracingSessionForTest();
374 tracingSession->StartBlocking();
375 // Clean up irrelevant traces.
376 tracingSession->ReadTraceBlocking();
377 // Trace.
378 mTimeStats->traceNewLayer(layerID, layerName);
379 mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
380 // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
381 mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
382 tracingSession->StopBlocking();
383 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
384 EXPECT_EQ(raw_trace.size(), 0);
385 }
386
387 {
388 auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
389 auto tracingSession = getTracingSessionForTest();
390 tracingSession->StartBlocking();
391 // Clean up irrelevant traces.
392 tracingSession->ReadTraceBlocking();
393 mTimeStats->traceNewLayer(layerID, layerName);
394 mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
395 const nsecs_t timestamp = systemTime();
396 fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
397 // Create extra trace packet to trigger and finalize fence trace packets.
398 mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
399 tracingSession->StopBlocking();
400
401 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
402 ASSERT_GT(raw_trace.size(), 0);
403
404 perfetto::protos::Trace trace;
405 ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
406 ASSERT_FALSE(trace.packet().empty());
407 EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
408
409 const auto& packet = trace.packet().Get(1);
410 ASSERT_TRUE(packet.has_timestamp());
411 EXPECT_EQ(packet.timestamp(), timestamp);
412 ASSERT_TRUE(packet.has_graphics_frame_event());
413 const auto& frame_event = packet.graphics_frame_event();
414 ASSERT_TRUE(frame_event.has_buffer_event());
415 const auto& buffer_event = frame_event.buffer_event();
416 ASSERT_TRUE(buffer_event.has_buffer_id());
417 EXPECT_EQ(buffer_event.buffer_id(), bufferID);
418 ASSERT_TRUE(buffer_event.has_frame_number());
419 EXPECT_EQ(buffer_event.frame_number(), frameNumber);
420 ASSERT_TRUE(buffer_event.has_type());
421 EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
422 EXPECT_FALSE(buffer_event.has_duration_ns());
423 }
424}
425
426TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
427 const std::string layerName = "co.layername#0";
428 const int32_t layerID = 5;
429 const uint32_t bufferID = 4;
430 const uint64_t frameNumber = 3;
431 const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
432
433 auto tracingSession = getTracingSessionForTest();
434
435 tracingSession->StartBlocking();
436 // Clean up irrelevant traces.
437 tracingSession->ReadTraceBlocking();
438 mTimeStats->traceNewLayer(layerID, layerName);
439
440 // traceFence called after fence signalled.
441 const nsecs_t signalTime1 = systemTime();
442 const nsecs_t startTime1 = signalTime1 + 100000;
443 auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
444 fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
445 mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
446
447 // traceFence called before fence signalled.
448 const nsecs_t signalTime2 = systemTime();
449 const nsecs_t startTime2 = signalTime2 + 100000;
450 auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
451 mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
452 fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
453
454 // Create extra trace packet to trigger and finalize fence trace packets.
455 mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
456 tracingSession->StopBlocking();
457
458 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
459 ASSERT_GT(raw_trace.size(), 0);
460
461 perfetto::protos::Trace trace;
462 ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
463 ASSERT_FALSE(trace.packet().empty());
464 EXPECT_EQ(trace.packet().size(), 2);
465
466 const auto& packet1 = trace.packet().Get(0);
467 ASSERT_TRUE(packet1.has_timestamp());
468 EXPECT_EQ(packet1.timestamp(), signalTime1);
469 ASSERT_TRUE(packet1.has_graphics_frame_event());
470 ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
471 ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
472
473 const auto& packet2 = trace.packet().Get(1);
474 ASSERT_TRUE(packet2.has_timestamp());
475 EXPECT_EQ(packet2.timestamp(), signalTime2);
476 ASSERT_TRUE(packet2.has_graphics_frame_event());
477 ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
478 ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
479}
480
481TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
482 const std::string layerName = "co.layername#0";
483 const int32_t layerID = 5;
484 const uint32_t bufferID = 4;
485 const uint64_t frameNumber = 3;
486 const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
487 const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline;
488
489 auto tracingSession = getTracingSessionForTest();
490 auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
491
492 tracingSession->StartBlocking();
493 // Clean up irrelevant traces.
494 tracingSession->ReadTraceBlocking();
495 mTimeStats->traceNewLayer(layerID, layerName);
496 mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type);
497 fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
498 // Create extra trace packet to trigger and finalize any previous fence packets.
499 mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
500 tracingSession->StopBlocking();
501
502 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
503 EXPECT_EQ(raw_trace.size(), 0);
504}
505
506TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
507 const std::string layerName = "co.layername#0";
508 const int32_t layerID = 5;
509 const uint32_t bufferID = 4;
510 const uint64_t frameNumber = 3;
511 const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
512 const nsecs_t duration = 1234;
513
514 auto tracingSession = getTracingSessionForTest();
515
516 tracingSession->StartBlocking();
517 // Clean up irrelevant traces.
518 tracingSession->ReadTraceBlocking();
519 mTimeStats->traceNewLayer(layerID, layerName);
520
521 // traceFence called after fence signalled.
522 const nsecs_t signalTime1 = systemTime();
523 const nsecs_t startTime1 = signalTime1 - duration;
524 auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
525 fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
526 mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
527
528 // traceFence called before fence signalled.
529 const nsecs_t signalTime2 = systemTime();
530 const nsecs_t startTime2 = signalTime2 - duration;
531 auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
532 mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
533 fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
534
535 // Create extra trace packet to trigger and finalize fence trace packets.
536 mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
537 tracingSession->StopBlocking();
538
539 std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
540 ASSERT_GT(raw_trace.size(), 0);
541
542 perfetto::protos::Trace trace;
543 ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
544 ASSERT_FALSE(trace.packet().empty());
545 EXPECT_EQ(trace.packet().size(), 2);
546
547 const auto& packet1 = trace.packet().Get(0);
548 ASSERT_TRUE(packet1.has_timestamp());
549 EXPECT_EQ(packet1.timestamp(), startTime1);
550 ASSERT_TRUE(packet1.has_graphics_frame_event());
551 ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
552 ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
553 const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
554 EXPECT_EQ(buffer_event1.duration_ns(), duration);
555
556 const auto& packet2 = trace.packet().Get(1);
557 ASSERT_TRUE(packet2.has_timestamp());
558 EXPECT_EQ(packet2.timestamp(), startTime2);
559 ASSERT_TRUE(packet2.has_graphics_frame_event());
560 ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
561 ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
562 const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
563 EXPECT_EQ(buffer_event2.duration_ns(), duration);
564}
565
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800566TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
567 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
568 ASSERT_TRUE(mTimeStats->isEnabled());
569
570 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
571 ASSERT_FALSE(mTimeStats->isEnabled());
572}
573
574TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
575 constexpr size_t TOTAL_FRAMES = 5;
576 constexpr size_t MISSED_FRAMES = 4;
577 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
578
579 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
580
581 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
582 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
583 }
584 for (size_t i = 0; i < MISSED_FRAMES; i++) {
585 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
586 }
587 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
588 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
589 }
590
591 SFTimeStatsGlobalProto globalProto;
592 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
593
594 ASSERT_TRUE(globalProto.has_total_frames());
595 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
596 ASSERT_TRUE(globalProto.has_missed_frames());
597 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
598 ASSERT_TRUE(globalProto.has_client_composition_frames());
599 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
600}
601
602TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
603 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
604
605 ASSERT_NO_FATAL_FAILURE(
606 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
607 ASSERT_NO_FATAL_FAILURE(
608 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
609
610 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
611 ASSERT_NO_FATAL_FAILURE(
612 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
613 ASSERT_NO_FATAL_FAILURE(
614 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
615
616 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_OFF));
617 ASSERT_NO_FATAL_FAILURE(
618 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
619 ASSERT_NO_FATAL_FAILURE(
620 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
621
622 SFTimeStatsGlobalProto globalProto;
623 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
624
625 ASSERT_EQ(1, globalProto.present_to_present_size());
626 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
627 EXPECT_EQ(1, histogramProto.frame_count());
628 EXPECT_EQ(2, histogramProto.time_millis());
629}
630
631TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
632 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
633
634 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
635 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
636
637 SFTimeStatsGlobalProto globalProto;
638 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
639
640 ASSERT_EQ(1, globalProto.stats_size());
641 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
642 ASSERT_TRUE(layerProto.has_layer_name());
643 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
644 ASSERT_TRUE(layerProto.has_total_frames());
645 EXPECT_EQ(1, layerProto.total_frames());
646 ASSERT_EQ(6, layerProto.deltas_size());
647 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
648 ASSERT_EQ(1, deltaProto.histograms_size());
649 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
650 EXPECT_EQ(1, histogramProto.frame_count());
651 if ("post2acquire" == deltaProto.delta_name()) {
652 EXPECT_EQ(1, histogramProto.time_millis());
653 } else if ("post2present" == deltaProto.delta_name()) {
654 EXPECT_EQ(4, histogramProto.time_millis());
655 } else if ("acquire2present" == deltaProto.delta_name()) {
656 EXPECT_EQ(3, histogramProto.time_millis());
657 } else if ("latch2present" == deltaProto.delta_name()) {
658 EXPECT_EQ(2, histogramProto.time_millis());
659 } else if ("desired2present" == deltaProto.delta_name()) {
660 EXPECT_EQ(1, histogramProto.time_millis());
661 } else if ("present2present" == deltaProto.delta_name()) {
662 EXPECT_EQ(1, histogramProto.time_millis());
663 } else {
664 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
665 }
666 }
667}
668
669TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
670 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
671
672 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
673 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
674
675 SFTimeStatsGlobalProto globalProto;
676 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
677
678 ASSERT_EQ(0, globalProto.stats_size());
679}
680
681TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
682 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
683
684 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
685 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
686 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
687 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
688
689 SFTimeStatsGlobalProto globalProto;
690 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
691
692 EXPECT_EQ(2, globalProto.stats_size());
693}
694
695TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
696 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
697
698 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
699 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
700
701 SFTimeStatsGlobalProto globalProto;
702 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
703
704 ASSERT_EQ(1, globalProto.stats_size());
705 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
706 ASSERT_TRUE(layerProto.has_layer_name());
707 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
708 ASSERT_TRUE(layerProto.has_total_frames());
709 EXPECT_EQ(1, layerProto.total_frames());
710 ASSERT_EQ(6, layerProto.deltas_size());
711 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
712 ASSERT_EQ(1, deltaProto.histograms_size());
713 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
714 EXPECT_EQ(1, histogramProto.frame_count());
715 if ("post2acquire" == deltaProto.delta_name()) {
716 EXPECT_EQ(0, histogramProto.time_millis());
717 } else if ("post2present" == deltaProto.delta_name()) {
718 EXPECT_EQ(2, histogramProto.time_millis());
719 } else if ("acquire2present" == deltaProto.delta_name()) {
720 EXPECT_EQ(2, histogramProto.time_millis());
721 } else if ("latch2present" == deltaProto.delta_name()) {
722 EXPECT_EQ(2, histogramProto.time_millis());
723 } else if ("desired2present" == deltaProto.delta_name()) {
724 EXPECT_EQ(1, histogramProto.time_millis());
725 } else if ("present2present" == deltaProto.delta_name()) {
726 EXPECT_EQ(1, histogramProto.time_millis());
727 } else {
728 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
729 }
730 }
731}
732
Alec Mourifb571ea2019-01-24 18:42:10 -0800733TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
734 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
735
736 uint32_t fpsOne = 30;
737 uint32_t fpsTwo = 90;
738 uint64_t millisOne = 5000;
739 uint64_t millisTwo = 7000;
740
741 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
742 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
743
744 SFTimeStatsGlobalProto globalProto;
745 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
746
747 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
748 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
749 expectedConfigOne->set_fps(fpsOne);
750 expectedBucketOne.set_duration_millis(millisOne);
751
752 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
753 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
754 expectedConfigTwo->set_fps(fpsTwo);
755 expectedBucketTwo.set_duration_millis(millisTwo);
756
757 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
758
759 std::unordered_set<uint32_t> seen_fps;
760 for (const auto& bucket : globalProto.display_config_stats()) {
761 seen_fps.emplace(bucket.config().fps());
762 if (fpsOne == bucket.config().fps()) {
763 EXPECT_EQ(millisOne, bucket.duration_millis());
764 } else if (fpsTwo == bucket.config().fps()) {
765 EXPECT_EQ(millisTwo, bucket.duration_millis());
766 } else {
767 FAIL() << "Unknown fps: " << bucket.config().fps();
768 }
769 }
770 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
771}
772
773TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
774 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
775
776 uint32_t fps = 30;
777 uint64_t millisOne = 5000;
778 uint64_t millisTwo = 7000;
779
780 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
781 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
782
783 SFTimeStatsGlobalProto globalProto;
784 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
785 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
786 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
787 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
788}
789
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800790TEST_F(TimeStatsTest, canRemoveTimeRecord) {
791 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
792
793 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
794 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
795 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
796 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
797
798 SFTimeStatsGlobalProto globalProto;
799 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
800
801 ASSERT_EQ(1, globalProto.stats_size());
802 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
803 ASSERT_TRUE(layerProto.has_total_frames());
804 EXPECT_EQ(1, layerProto.total_frames());
805}
806
807TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
808 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
809
810 uint64_t frameNumber = 1;
811 nsecs_t ts = 1000000;
812 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800813 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800814 frameNumber++;
815 ts += 1000000;
816 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
817 }
818
819 SFTimeStatsGlobalProto globalProto;
820 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
821
822 ASSERT_EQ(1, globalProto.stats_size());
823 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
824 ASSERT_TRUE(layerProto.has_total_frames());
825 EXPECT_EQ(1, layerProto.total_frames());
826}
827
828TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
829 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
830
831 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
832 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
833 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
834 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
835
836 SFTimeStatsGlobalProto globalProto;
837 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
838
839 ASSERT_EQ(1, globalProto.stats_size());
840 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
841 ASSERT_TRUE(layerProto.has_total_frames());
842 EXPECT_EQ(1, layerProto.total_frames());
843}
844
845TEST_F(TimeStatsTest, canClearTimeStats) {
846 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
847
848 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
849 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
850 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
851 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(HWC_POWER_MODE_NORMAL));
852 ASSERT_NO_FATAL_FAILURE(
853 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
854 ASSERT_NO_FATAL_FAILURE(
855 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
856 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
857 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
858
859 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
860
861 SFTimeStatsGlobalProto globalProto;
862 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
863
864 EXPECT_EQ(0, globalProto.total_frames());
865 EXPECT_EQ(0, globalProto.missed_frames());
866 EXPECT_EQ(0, globalProto.client_composition_frames());
867 EXPECT_EQ(0, globalProto.present_to_present_size());
868 EXPECT_EQ(0, globalProto.stats_size());
869}
870
871TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
872 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
873
874 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
875 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
876 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
877 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
878 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
879
880 SFTimeStatsGlobalProto globalProto;
881 ASSERT_TRUE(
882 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
883
884 ASSERT_EQ(1, globalProto.stats_size());
885 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
886 ASSERT_TRUE(layerProto.has_layer_name());
887 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
888 ASSERT_TRUE(layerProto.has_total_frames());
889 EXPECT_EQ(2, layerProto.total_frames());
890}
891
892TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
893 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
894
895 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
896 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
897
898 SFTimeStatsGlobalProto globalProto;
899 ASSERT_TRUE(globalProto.ParseFromString(
900 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
901
902 ASSERT_EQ(0, globalProto.stats_size());
903}
904
905TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -0800906 if (g_noSlowTests) {
907 GTEST_SKIP();
908 }
909
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800910 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
911
912 for (size_t i = 0; i < 10000000; ++i) {
913 const int32_t layerID = genRandomInt32(-1, 10);
914 const int32_t frameNumber = genRandomInt32(1, 10);
915 switch (genRandomInt32(0, 100)) {
916 case 0:
917 ALOGV("removeTimeRecord");
918 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber));
919 continue;
920 case 1:
921 ALOGV("onDestroy");
922 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID));
923 continue;
924 }
925 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
926 const int32_t ts = genRandomInt32(1, 1000000000);
927 ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts);
928 setTimeStamp(type, layerID, frameNumber, ts);
929 }
930}
931
932} // namespace
933} // namespace android