blob: 0ef845673955462ae926ef4107f31a1480b83cb5 [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
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
Marin Shalamanovbed7fd32020-12-21 20:02:20 +010020#pragma clang diagnostic ignored "-Wextra"
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080021
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080022#undef LOG_TAG
23#define LOG_TAG "LibSurfaceFlingerUnittests"
24
Mikael Pessa2e1608f2019-07-19 11:25:35 -070025#include <TimeStats/TimeStats.h>
Alec Mourifb571ea2019-01-24 18:42:10 -080026#include <gmock/gmock.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080027#include <gtest/gtest.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080028#include <log/log.h>
Tej Singhe2751772021-04-06 22:05:29 -070029#include <timestatsatomsproto/TimeStatsAtomsProtoHeader.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080030#include <utils/String16.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080031#include <utils/Vector.h>
32
Alec Mouri9519bf12019-11-15 16:54:44 -080033#include <chrono>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080034#include <random>
Alec Mourifb571ea2019-01-24 18:42:10 -080035#include <unordered_set>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080036
Lloyd Pique067fe1e2018-12-06 19:44:13 -080037#include "libsurfaceflinger_unittest_main.h"
38
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080039using namespace android::surfaceflinger;
40using namespace google::protobuf;
Vishnu Nairabf97fd2020-02-03 13:51:16 -080041using namespace std::chrono_literals;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080042
43namespace android {
44namespace {
45
Alec Mouri8e2f31b2020-01-16 22:04:35 +000046using testing::_;
Alec Mouri37384342020-01-02 17:23:37 -080047using testing::AnyNumber;
Alec Mourifb571ea2019-01-24 18:42:10 -080048using testing::Contains;
Vishnu Nair9b079a22020-01-21 14:36:08 -080049using testing::HasSubstr;
Alec Mouri8e2f31b2020-01-16 22:04:35 +000050using testing::InSequence;
Alec Mouri56e63852021-03-09 18:17:25 -080051using testing::Not;
Alec Mourifb571ea2019-01-24 18:42:10 -080052using testing::SizeIs;
Alec Mouri37384342020-01-02 17:23:37 -080053using testing::StrEq;
Alec Mourifb571ea2019-01-24 18:42:10 -080054using testing::UnorderedElementsAre;
55
Peiyong Lin65248e02020-04-18 21:15:07 -070056using PowerMode = hardware::graphics::composer::V2_4::IComposerClient::PowerMode;
Adithya Srinivasan58069dc2021-06-04 20:37:02 +000057using SurfaceflingerStatsLayerInfo = android::surfaceflinger::SurfaceflingerStatsLayerInfo;
58using SurfaceflingerStatsLayerInfoWrapper =
59 android::surfaceflinger::SurfaceflingerStatsLayerInfoWrapper;
Peiyong Lin65248e02020-04-18 21:15:07 -070060
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080061// clang-format off
Alec Mouri7d436ec2021-01-27 20:40:50 -080062#define FMT_PROTO true
63#define FMT_STRING false
64#define LAYER_ID_0 0
65#define LAYER_ID_1 1
66#define UID_0 123
Alec Mouri7d436ec2021-01-27 20:40:50 -080067#define REFRESH_RATE_BUCKET_0 60
68#define RENDER_RATE_BUCKET_0 30
69#define LAYER_ID_INVALID -1
70#define NUM_LAYERS 1
71#define NUM_LAYERS_INVALID "INVALID"
72
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -070073constexpr Fps kRefreshRate0 = 61_Hz;
74constexpr Fps kRenderRate0 = 31_Hz;
75constexpr GameMode kGameMode = GameMode::Unsupported;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080076
77enum InputCommand : int32_t {
78 ENABLE = 0,
79 DISABLE = 1,
80 CLEAR = 2,
81 DUMP_ALL = 3,
82 DUMP_MAXLAYERS_1 = 4,
83 DUMP_MAXLAYERS_INVALID = 5,
84 INPUT_COMMAND_BEGIN = ENABLE,
85 INPUT_COMMAND_END = DUMP_MAXLAYERS_INVALID,
86 INPUT_COMMAND_RANGE = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
87};
88
89enum TimeStamp : int32_t {
90 POST = 0,
91 ACQUIRE = 1,
92 ACQUIRE_FENCE = 2,
93 LATCH = 3,
94 DESIRED = 4,
95 PRESENT = 5,
96 PRESENT_FENCE = 6,
97 TIME_STAMP_BEGIN = POST,
98 TIME_STAMP_END = PRESENT,
99 TIME_STAMP_RANGE = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
100};
101
102static const TimeStamp NORMAL_SEQUENCE[] = {
103 TimeStamp::POST,
104 TimeStamp::ACQUIRE,
105 TimeStamp::LATCH,
106 TimeStamp::DESIRED,
107 TimeStamp::PRESENT,
108};
109
110static const TimeStamp NORMAL_SEQUENCE_2[] = {
111 TimeStamp::POST,
112 TimeStamp::ACQUIRE_FENCE,
113 TimeStamp::LATCH,
114 TimeStamp::DESIRED,
115 TimeStamp::PRESENT_FENCE,
116};
117
118static const TimeStamp UNORDERED_SEQUENCE[] = {
119 TimeStamp::ACQUIRE,
120 TimeStamp::LATCH,
121 TimeStamp::POST,
122 TimeStamp::DESIRED,
123 TimeStamp::PRESENT,
124};
125
126static const TimeStamp INCOMPLETE_SEQUENCE[] = {
127 TimeStamp::POST,
128};
129// clang-format on
130
131class TimeStatsTest : public testing::Test {
132public:
133 TimeStatsTest() {
134 const ::testing::TestInfo* const test_info =
135 ::testing::UnitTest::GetInstance()->current_test_info();
136 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
137 }
138
139 ~TimeStatsTest() {
140 const ::testing::TestInfo* const test_info =
141 ::testing::UnitTest::GetInstance()->current_test_info();
142 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
143 }
144
145 std::string inputCommand(InputCommand cmd, bool useProto);
146
Ady Abraham8b9e6122021-01-26 19:11:45 -0800147 void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700148 TimeStats::SetFrameRateVote, GameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800149
150 int32_t genRandomInt32(int32_t begin, int32_t end);
151
152 template <size_t N>
153 void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000154 nsecs_t ts, TimeStats::SetFrameRateVote frameRateVote = {},
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700155 GameMode gameMode = kGameMode) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800156 for (size_t i = 0; i < N; i++, ts += 1000000) {
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000157 setTimeStamp(sequence[i], id, frameNumber, ts, frameRateVote, gameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800158 }
159 }
160
161 std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000162 std::unique_ptr<TimeStats> mTimeStats =
Tej Singhe2751772021-04-06 22:05:29 -0700163 std::make_unique<impl::TimeStats>(std::nullopt, std::nullopt);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800164};
165
166std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
Yiwei Zhang5434a782018-12-05 18:06:32 -0800167 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800168 Vector<String16> args;
169
170 switch (cmd) {
171 case InputCommand::ENABLE:
172 args.push_back(String16("-enable"));
173 break;
174 case InputCommand::DISABLE:
175 args.push_back(String16("-disable"));
176 break;
177 case InputCommand::CLEAR:
178 args.push_back(String16("-clear"));
179 break;
180 case InputCommand::DUMP_ALL:
181 args.push_back(String16("-dump"));
182 break;
183 case InputCommand::DUMP_MAXLAYERS_1:
184 args.push_back(String16("-dump"));
185 args.push_back(String16("-maxlayers"));
186 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
187 break;
188 case InputCommand::DUMP_MAXLAYERS_INVALID:
189 args.push_back(String16("-dump"));
190 args.push_back(String16("-maxlayers"));
191 args.push_back(String16(NUM_LAYERS_INVALID));
192 break;
193 default:
194 ALOGD("Invalid control command");
195 }
196
Dominik Laskowskic2867142019-01-21 11:33:38 -0800197 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800198 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800199}
200
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800201static std::string genLayerName(int32_t layerId) {
Peiyong Lind8460c82020-07-28 16:04:22 -0700202 return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.example.fake#") + std::to_string(layerId);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800203}
204
Ady Abraham8b9e6122021-01-26 19:11:45 -0800205void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -0700206 TimeStats::SetFrameRateVote frameRateVote, GameMode gameMode) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800207 switch (type) {
208 case TimeStamp::POST:
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000209 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id),
210 UID_0, ts, gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800211 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:
Ady Abraham8b9e6122021-01-26 19:11:45 -0800226 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts, kRefreshRate0,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000227 kRenderRate0, frameRateVote,
228 gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800229 break;
230 case TimeStamp::PRESENT_FENCE:
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000231 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentFence(id, frameNumber,
232 std::make_shared<FenceTime>(ts),
233 kRefreshRate0, kRenderRate0,
234 frameRateVote, gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800235 break;
236 default:
237 ALOGD("Invalid timestamp type");
238 }
239}
240
241int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
242 std::uniform_int_distribution<int32_t> distr(begin, end);
243 return distr(mRandomEngine);
244}
245
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000246TEST_F(TimeStatsTest, disabledByDefault) {
247 ASSERT_FALSE(mTimeStats->isEnabled());
248}
249
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800250TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
251 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
252 ASSERT_TRUE(mTimeStats->isEnabled());
253
254 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
255 ASSERT_FALSE(mTimeStats->isEnabled());
256}
257
258TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
259 constexpr size_t TOTAL_FRAMES = 5;
260 constexpr size_t MISSED_FRAMES = 4;
261 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
262
263 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
264
265 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
266 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
267 }
268 for (size_t i = 0; i < MISSED_FRAMES; i++) {
269 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
270 }
271 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
272 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
273 }
274
275 SFTimeStatsGlobalProto globalProto;
276 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
277
278 ASSERT_TRUE(globalProto.has_total_frames());
279 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
280 ASSERT_TRUE(globalProto.has_missed_frames());
281 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
282 ASSERT_TRUE(globalProto.has_client_composition_frames());
283 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
284}
285
Alec Mouri91f6df32020-01-30 08:48:58 -0800286TEST_F(TimeStatsTest, canIncreaseLateAcquireFrames) {
287 // this stat is not in the proto so verify by checking the string dump
288 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
289
290 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
291
292 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
293 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
294 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
295 }
296 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
297
298 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
299 const std::string expectedResult = "lateAcquireFrames = " + std::to_string(LATE_ACQUIRE_FRAMES);
300 EXPECT_THAT(result, HasSubstr(expectedResult));
301}
302
303TEST_F(TimeStatsTest, canIncreaseBadDesiredPresent) {
304 // this stat is not in the proto so verify by checking the string dump
305 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 2;
306
307 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
308
309 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
310 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
311 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
312 }
313 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
314
315 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
316 const std::string expectedResult =
317 "badDesiredPresentFrames = " + std::to_string(BAD_DESIRED_PRESENT_FRAMES);
318 EXPECT_THAT(result, HasSubstr(expectedResult));
319}
320
Alec Mouri9a29e672020-09-14 12:39:14 -0700321TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
322 // this stat is not in the proto so verify by checking the string dump
323 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
324
325 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mouri363faf02021-01-29 16:34:55 -0800326 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000327 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000328 3});
329 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000330 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
331 3});
332 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
333 kGameMode, JankType::DisplayHAL, 1, 2, 3});
334 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
335 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
336 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
337 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
338 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
339 kGameMode, JankType::PredictionError, 1, 2, 3});
340 mTimeStats->incrementJankyFrames(
341 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
342 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
343 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
344 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700345
346 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
Alec Mouri7d436ec2021-01-27 20:40:50 -0800347 std::string expectedResult =
348 "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
349 EXPECT_THAT(result, HasSubstr(expectedResult));
350 expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
351 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000352 expectedResult = "totalTimelineFrames = " + std::to_string(8);
Alec Mouri9a29e672020-09-14 12:39:14 -0700353 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000354 expectedResult = "jankyFrames = " + std::to_string(7);
Alec Mouri9a29e672020-09-14 12:39:14 -0700355 EXPECT_THAT(result, HasSubstr(expectedResult));
356 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
357 EXPECT_THAT(result, HasSubstr(expectedResult));
358 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
359 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000360 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700361 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000362 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
363 EXPECT_THAT(result, HasSubstr(expectedResult));
364 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
365 EXPECT_THAT(result, HasSubstr(expectedResult));
366 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
367 EXPECT_THAT(result, HasSubstr(expectedResult));
368 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700369 EXPECT_THAT(result, HasSubstr(expectedResult));
370}
371
Ady Abraham8b9e6122021-01-26 19:11:45 -0800372TEST_F(TimeStatsTest, canCaptureSetFrameRateVote) {
373 // this stat is not in the proto so verify by checking the string dump
374 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
375
376 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
377
378 const auto frameRate60 = TimeStats::SetFrameRateVote{
379 .frameRate = 60.0f,
380 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
381 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
382 };
383 const auto frameRate90 = TimeStats::SetFrameRateVote{
384 .frameRate = 90.0f,
385 .frameRateCompatibility =
386 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
387 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
388 };
389 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
390 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
391 std::string expectedResult = "frameRate = 60.00";
392 EXPECT_THAT(result, HasSubstr(expectedResult));
393 expectedResult = "frameRateCompatibility = Default";
394 EXPECT_THAT(result, HasSubstr(expectedResult));
395 expectedResult = "seamlessness = ShouldBeSeamless";
396 EXPECT_THAT(result, HasSubstr(expectedResult));
397
398 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRate90);
399 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
400 expectedResult = "frameRate = 90.00";
401 EXPECT_THAT(result, HasSubstr(expectedResult));
402 expectedResult = "frameRateCompatibility = ExactOrMultiple";
403 EXPECT_THAT(result, HasSubstr(expectedResult));
404 expectedResult = "seamlessness = NotRequired";
405 EXPECT_THAT(result, HasSubstr(expectedResult));
406
407 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRate60);
408 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
409 expectedResult = "frameRate = 60.00";
410 EXPECT_THAT(result, HasSubstr(expectedResult));
411 expectedResult = "frameRateCompatibility = Default";
412 EXPECT_THAT(result, HasSubstr(expectedResult));
413 expectedResult = "seamlessness = ShouldBeSeamless";
414 EXPECT_THAT(result, HasSubstr(expectedResult));
415}
416
417TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) {
418 // this stat is not in the proto so verify by checking the string dump
419 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
420
421 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
422
423 const auto frameRate90 = TimeStats::SetFrameRateVote{
424 .frameRate = 90.0f,
425 .frameRateCompatibility =
426 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
427 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
428 };
429 const auto frameRateDefault = TimeStats::SetFrameRateVote{
430 .frameRate = 0.0f,
431 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
432 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
433 };
434 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate90);
435 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
436 std::string expectedResult = "frameRate = 90.00";
437 EXPECT_THAT(result, HasSubstr(expectedResult));
438 expectedResult = "frameRateCompatibility = ExactOrMultiple";
439 EXPECT_THAT(result, HasSubstr(expectedResult));
440 expectedResult = "seamlessness = NotRequired";
441 EXPECT_THAT(result, HasSubstr(expectedResult));
442
443 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRateDefault);
444 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
445 expectedResult = "frameRate = 90.00";
446 EXPECT_THAT(result, HasSubstr(expectedResult));
447 expectedResult = "frameRateCompatibility = ExactOrMultiple";
448 EXPECT_THAT(result, HasSubstr(expectedResult));
449 expectedResult = "seamlessness = NotRequired";
450 EXPECT_THAT(result, HasSubstr(expectedResult));
451
452 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRateDefault);
453 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
454 expectedResult = "frameRate = 90.00";
455 EXPECT_THAT(result, HasSubstr(expectedResult));
456 expectedResult = "frameRateCompatibility = ExactOrMultiple";
457 EXPECT_THAT(result, HasSubstr(expectedResult));
458 expectedResult = "seamlessness = NotRequired";
459 EXPECT_THAT(result, HasSubstr(expectedResult));
460}
461
Vishnu Nair9b079a22020-01-21 14:36:08 -0800462TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) {
463 // this stat is not in the proto so verify by checking the string dump
464 constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2;
465
466 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
467 for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) {
468 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
469 }
470
471 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
472 const std::string expectedResult =
473 "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES);
474 EXPECT_THAT(result, HasSubstr(expectedResult));
475}
476
Alec Mouri8de697e2020-03-19 10:52:01 -0700477TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
478 // this stat is not in the proto so verify by checking the string dump
479 constexpr size_t REFRESH_RATE_SWITCHES = 2;
480
481 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
482 for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
483 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
484 }
485
486 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
487 const std::string expectedResult =
488 "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
489 EXPECT_THAT(result, HasSubstr(expectedResult));
490}
491
Alec Mouri8f7a0102020-04-15 12:11:10 -0700492TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) {
493 // this stat is not in the proto so verify by checking the string dump
494 constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2;
495
496 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
497 for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) {
498 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
499 }
500
501 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
502 const std::string expectedResult =
503 "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES);
504 EXPECT_THAT(result, HasSubstr(expectedResult));
505}
506
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800507TEST_F(TimeStatsTest, canAverageFrameDuration) {
508 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Peiyong Lin65248e02020-04-18 21:15:07 -0700509 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000510 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
511 std::chrono::nanoseconds(6ms).count());
512 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
513 std::chrono::nanoseconds(16ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800514
515 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
516 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 10.000 ms"));
517}
518
519TEST_F(TimeStatsTest, canAverageRenderEngineTimings) {
520 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Adithya Srinivasanead17162021-02-18 02:17:37 +0000521 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800522 std::make_shared<FenceTime>(
523 std::chrono::duration_cast<
524 std::chrono::nanoseconds>(3ms)
525 .count()));
526
Adithya Srinivasanead17162021-02-18 02:17:37 +0000527 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
528 std::chrono::nanoseconds(8ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800529
Peiyong Lind8460c82020-07-28 16:04:22 -0700530 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700531 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000532 mTimeStats->setPresentFenceGlobal(
533 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800534
535 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
536 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 3.000 ms"));
537}
538
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800539TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
540 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
541
542 ASSERT_NO_FATAL_FAILURE(
543 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
544 ASSERT_NO_FATAL_FAILURE(
545 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
546
Peiyong Lin65248e02020-04-18 21:15:07 -0700547 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800548 ASSERT_NO_FATAL_FAILURE(
549 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
550 ASSERT_NO_FATAL_FAILURE(
551 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
552
Peiyong Lin65248e02020-04-18 21:15:07 -0700553 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800554 ASSERT_NO_FATAL_FAILURE(
555 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
556 ASSERT_NO_FATAL_FAILURE(
557 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
558
559 SFTimeStatsGlobalProto globalProto;
560 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
561
562 ASSERT_EQ(1, globalProto.present_to_present_size());
563 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
564 EXPECT_EQ(1, histogramProto.frame_count());
565 EXPECT_EQ(2, histogramProto.time_millis());
566}
567
Alec Mouri9519bf12019-11-15 16:54:44 -0800568TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
569 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
570
Peiyong Lin65248e02020-04-18 21:15:07 -0700571 mTimeStats->setPowerMode(PowerMode::OFF);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000572 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
573 std::chrono::nanoseconds(5ms).count());
Peiyong Lin65248e02020-04-18 21:15:07 -0700574 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000575 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
576 std::chrono::nanoseconds(6ms).count());
Alec Mouri9519bf12019-11-15 16:54:44 -0800577
578 SFTimeStatsGlobalProto globalProto;
579 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
580
581 ASSERT_EQ(1, globalProto.frame_duration_size());
582 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.frame_duration().Get(0);
583 EXPECT_EQ(1, histogramProto.frame_count());
584 EXPECT_EQ(3, histogramProto.time_millis());
585}
586
Alec Mourie4034bb2019-11-19 12:45:54 -0800587TEST_F(TimeStatsTest, canInsertGlobalRenderEngineTiming) {
588 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
589
Adithya Srinivasanead17162021-02-18 02:17:37 +0000590 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Alec Mourie4034bb2019-11-19 12:45:54 -0800591 std::make_shared<FenceTime>(
592 std::chrono::duration_cast<
593 std::chrono::nanoseconds>(3ms)
594 .count()));
595
Adithya Srinivasanead17162021-02-18 02:17:37 +0000596 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
597 std::chrono::nanoseconds(6ms).count());
Alec Mourie4034bb2019-11-19 12:45:54 -0800598
599 // First verify that flushing RenderEngine durations did not occur yet.
600 SFTimeStatsGlobalProto preFlushProto;
601 ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
602 ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
603
Peiyong Lind8460c82020-07-28 16:04:22 -0700604 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700605 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000606 mTimeStats->setPresentFenceGlobal(
607 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mourie4034bb2019-11-19 12:45:54 -0800608
609 // Now we can verify that RenderEngine durations were flushed now.
610 SFTimeStatsGlobalProto postFlushProto;
611 ASSERT_TRUE(postFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
612
613 ASSERT_EQ(1, postFlushProto.render_engine_timing_size());
614 const SFTimeStatsHistogramBucketProto& histogramProto =
615 postFlushProto.render_engine_timing().Get(0);
616 EXPECT_EQ(2, histogramProto.frame_count());
617 EXPECT_EQ(2, histogramProto.time_millis());
618}
619
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800620TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
621 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
622
623 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
624 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
625
626 SFTimeStatsGlobalProto globalProto;
627 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
628
629 ASSERT_EQ(1, globalProto.stats_size());
630 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
631 ASSERT_TRUE(layerProto.has_layer_name());
632 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
633 ASSERT_TRUE(layerProto.has_total_frames());
634 EXPECT_EQ(1, layerProto.total_frames());
635 ASSERT_EQ(6, layerProto.deltas_size());
636 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
637 ASSERT_EQ(1, deltaProto.histograms_size());
638 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
639 EXPECT_EQ(1, histogramProto.frame_count());
640 if ("post2acquire" == deltaProto.delta_name()) {
641 EXPECT_EQ(1, histogramProto.time_millis());
642 } else if ("post2present" == deltaProto.delta_name()) {
643 EXPECT_EQ(4, histogramProto.time_millis());
644 } else if ("acquire2present" == deltaProto.delta_name()) {
645 EXPECT_EQ(3, histogramProto.time_millis());
646 } else if ("latch2present" == deltaProto.delta_name()) {
647 EXPECT_EQ(2, histogramProto.time_millis());
648 } else if ("desired2present" == deltaProto.delta_name()) {
649 EXPECT_EQ(1, histogramProto.time_millis());
650 } else if ("present2present" == deltaProto.delta_name()) {
651 EXPECT_EQ(1, histogramProto.time_millis());
652 } else {
653 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
654 }
655 }
656}
657
658TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
659 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
660
661 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
662 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
663
664 SFTimeStatsGlobalProto globalProto;
665 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
666
667 ASSERT_EQ(0, globalProto.stats_size());
668}
669
670TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
671 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
672
673 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
674 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
675 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
676 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
677
678 SFTimeStatsGlobalProto globalProto;
679 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
680
681 EXPECT_EQ(2, globalProto.stats_size());
682}
683
684TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
685 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
686
687 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
688 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
689
690 SFTimeStatsGlobalProto globalProto;
691 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
692
693 ASSERT_EQ(1, globalProto.stats_size());
694 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
695 ASSERT_TRUE(layerProto.has_layer_name());
696 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
697 ASSERT_TRUE(layerProto.has_total_frames());
698 EXPECT_EQ(1, layerProto.total_frames());
699 ASSERT_EQ(6, layerProto.deltas_size());
700 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
701 ASSERT_EQ(1, deltaProto.histograms_size());
702 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
703 EXPECT_EQ(1, histogramProto.frame_count());
704 if ("post2acquire" == deltaProto.delta_name()) {
705 EXPECT_EQ(0, histogramProto.time_millis());
706 } else if ("post2present" == deltaProto.delta_name()) {
707 EXPECT_EQ(2, histogramProto.time_millis());
708 } else if ("acquire2present" == deltaProto.delta_name()) {
709 EXPECT_EQ(2, histogramProto.time_millis());
710 } else if ("latch2present" == deltaProto.delta_name()) {
711 EXPECT_EQ(2, histogramProto.time_millis());
712 } else if ("desired2present" == deltaProto.delta_name()) {
713 EXPECT_EQ(1, histogramProto.time_millis());
714 } else if ("present2present" == deltaProto.delta_name()) {
715 EXPECT_EQ(1, histogramProto.time_millis());
716 } else {
717 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
718 }
719 }
720}
721
Alec Mourifb571ea2019-01-24 18:42:10 -0800722TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
723 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
724
725 uint32_t fpsOne = 30;
726 uint32_t fpsTwo = 90;
727 uint64_t millisOne = 5000;
728 uint64_t millisTwo = 7000;
729
730 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
731 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
732
733 SFTimeStatsGlobalProto globalProto;
734 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
735
736 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
737 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
738 expectedConfigOne->set_fps(fpsOne);
739 expectedBucketOne.set_duration_millis(millisOne);
740
741 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
742 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
743 expectedConfigTwo->set_fps(fpsTwo);
744 expectedBucketTwo.set_duration_millis(millisTwo);
745
746 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
747
748 std::unordered_set<uint32_t> seen_fps;
749 for (const auto& bucket : globalProto.display_config_stats()) {
750 seen_fps.emplace(bucket.config().fps());
751 if (fpsOne == bucket.config().fps()) {
752 EXPECT_EQ(millisOne, bucket.duration_millis());
753 } else if (fpsTwo == bucket.config().fps()) {
754 EXPECT_EQ(millisTwo, bucket.duration_millis());
755 } else {
756 FAIL() << "Unknown fps: " << bucket.config().fps();
757 }
758 }
759 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
760}
761
762TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
763 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
764
765 uint32_t fps = 30;
766 uint64_t millisOne = 5000;
767 uint64_t millisTwo = 7000;
768
769 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
770 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
771
772 SFTimeStatsGlobalProto globalProto;
773 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
774 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
775 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
776 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
777}
778
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800779TEST_F(TimeStatsTest, canRemoveTimeRecord) {
780 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
781
782 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
783 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
784 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
785 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
786
787 SFTimeStatsGlobalProto globalProto;
788 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
789
790 ASSERT_EQ(1, globalProto.stats_size());
791 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
792 ASSERT_TRUE(layerProto.has_total_frames());
793 EXPECT_EQ(1, layerProto.total_frames());
794}
795
796TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
797 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
798
799 uint64_t frameNumber = 1;
800 nsecs_t ts = 1000000;
801 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800802 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800803 frameNumber++;
804 ts += 1000000;
805 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
806 }
807
808 SFTimeStatsGlobalProto globalProto;
809 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
810
811 ASSERT_EQ(1, globalProto.stats_size());
812 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
813 ASSERT_TRUE(layerProto.has_total_frames());
814 EXPECT_EQ(1, layerProto.total_frames());
815}
816
817TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
818 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
819
820 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
821 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
822 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
823 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
824
825 SFTimeStatsGlobalProto globalProto;
826 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
827
828 ASSERT_EQ(1, globalProto.stats_size());
829 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
830 ASSERT_TRUE(layerProto.has_total_frames());
831 EXPECT_EQ(1, layerProto.total_frames());
832}
833
834TEST_F(TimeStatsTest, canClearTimeStats) {
835 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
836
837 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
838 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
839 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
Peiyong Lin65248e02020-04-18 21:15:07 -0700840 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Alec Mouri31ac64a2020-01-09 09:26:22 -0800841
Adithya Srinivasanead17162021-02-18 02:17:37 +0000842 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
843 std::chrono::nanoseconds(6ms).count());
844 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
845 std::chrono::nanoseconds(6ms).count());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800846 ASSERT_NO_FATAL_FAILURE(
847 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
848 ASSERT_NO_FATAL_FAILURE(
849 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
850 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
851 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
852
853 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
854
855 SFTimeStatsGlobalProto globalProto;
856 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
857
858 EXPECT_EQ(0, globalProto.total_frames());
859 EXPECT_EQ(0, globalProto.missed_frames());
860 EXPECT_EQ(0, globalProto.client_composition_frames());
861 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri31ac64a2020-01-09 09:26:22 -0800862 EXPECT_EQ(0, globalProto.frame_duration_size());
863 EXPECT_EQ(0, globalProto.render_engine_timing_size());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800864 EXPECT_EQ(0, globalProto.stats_size());
865}
866
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800867TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) {
868 // These stats are not in the proto so verify by checking the string dump.
Vishnu Nair9b079a22020-01-21 14:36:08 -0800869 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
870 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
Alec Mouri8de697e2020-03-19 10:52:01 -0700871 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
Alec Mouri8f7a0102020-04-15 12:11:10 -0700872 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
Peiyong Lin65248e02020-04-18 21:15:07 -0700873 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000874 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
875 std::chrono::nanoseconds(5ms).count());
876 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
877 std::chrono::nanoseconds(6ms).count());
878 mTimeStats->setPresentFenceGlobal(
879 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mouri9a29e672020-09-14 12:39:14 -0700880
Alec Mouri363faf02021-01-29 16:34:55 -0800881 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000882 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000883 3});
884 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000885 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
886 3});
887 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
888 kGameMode, JankType::DisplayHAL, 1, 2, 3});
889 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
890 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
891 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
892 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
893 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
894 kGameMode, JankType::PredictionError, 1, 2, 3});
895 mTimeStats->incrementJankyFrames(
896 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
897 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
898 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
899 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700900
Vishnu Nair9b079a22020-01-21 14:36:08 -0800901 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
902
903 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
904 EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
Alec Mouri8de697e2020-03-19 10:52:01 -0700905 EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
Alec Mouri8f7a0102020-04-15 12:11:10 -0700906 EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800907 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
908 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
Ady Abraham3403a3f2021-04-27 16:58:40 -0700909 std::string expectedResult = "totalTimelineFrames = ";
910 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
911 expectedResult = "jankyFrames = ";
912 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
913 expectedResult = "sfLongCpuJankyFrames = ";
914 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
915 expectedResult = "sfLongGpuJankyFrames = ";
916 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
917 expectedResult = "sfUnattributedJankyFrames = ";
918 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
919 expectedResult = "appUnattributedJankyFrames = ";
920 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
921 expectedResult = "sfSchedulingJankyFrames = ";
922 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
923 expectedResult = "sfPredictionErrorJankyFrames = ";
924 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
925 expectedResult = "appBufferStuffingJankyFrames = ";
926 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
Vishnu Nair9b079a22020-01-21 14:36:08 -0800927}
928
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800929TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
930 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
931
932 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
933 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
934 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
935 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
936 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
937
938 SFTimeStatsGlobalProto globalProto;
939 ASSERT_TRUE(
940 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
941
942 ASSERT_EQ(1, globalProto.stats_size());
943 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
944 ASSERT_TRUE(layerProto.has_layer_name());
945 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
946 ASSERT_TRUE(layerProto.has_total_frames());
947 EXPECT_EQ(2, layerProto.total_frames());
948}
949
950TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
951 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
952
953 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
954 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
955
956 SFTimeStatsGlobalProto globalProto;
957 ASSERT_TRUE(globalProto.ParseFromString(
958 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
959
960 ASSERT_EQ(0, globalProto.stats_size());
961}
962
Yiwei Zhangdd221b22020-06-12 11:06:19 -0700963TEST_F(TimeStatsTest, noInfInAverageFPS) {
964 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
965 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
966 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 1000000);
967
968 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
969 EXPECT_THAT(result, HasSubstr("averageFPS = 0.000"));
970}
971
Alec Mouri37384342020-01-02 17:23:37 -0800972namespace {
Tej Singhe2751772021-04-06 22:05:29 -0700973FrameTimingHistogram buildExpectedHistogram(const std::vector<int32_t>& times,
974 const std::vector<int32_t>& frameCounts) {
975 FrameTimingHistogram histogram;
Alec Mouri37384342020-01-02 17:23:37 -0800976 for (int i = 0; i < times.size(); i++) {
977 ALOGE("Writing time: %d", times[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700978 histogram.add_time_millis_buckets(times[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800979 ALOGE("Writing count: %d", frameCounts[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700980 histogram.add_frame_counts((int64_t)frameCounts[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800981 }
Tej Singhe2751772021-04-06 22:05:29 -0700982 return histogram;
Alec Mouri37384342020-01-02 17:23:37 -0800983}
Alec Mouri37384342020-01-02 17:23:37 -0800984} // namespace
985
Tej Singhe2751772021-04-06 22:05:29 -0700986MATCHER_P(HistogramEq, expected, "") {
987 *result_listener << "Histograms are not equal! \n";
Alec Mouri37384342020-01-02 17:23:37 -0800988
Tej Singhe2751772021-04-06 22:05:29 -0700989 if (arg.time_millis_buckets_size() != expected.time_millis_buckets_size()) {
990 *result_listener << "Time millis bucket are different sizes. Expected: "
991 << expected.time_millis_buckets_size() << ". Actual "
992 << arg.time_millis_buckets_size();
993 return false;
994 }
995 if (arg.frame_counts_size() != expected.frame_counts_size()) {
996 *result_listener << "Frame counts are different sizes. Expected: "
997 << expected.frame_counts_size() << ". Actual " << arg.frame_counts_size();
998 return false;
999 }
Alec Mouri37384342020-01-02 17:23:37 -08001000
Tej Singhe2751772021-04-06 22:05:29 -07001001 for (int i = 0; i < expected.time_millis_buckets_size(); i++) {
1002 if (arg.time_millis_buckets(i) != expected.time_millis_buckets(i)) {
1003 *result_listener << "time_millis_bucket[" << i
1004 << "] is different. Expected: " << expected.time_millis_buckets(i)
1005 << ". Actual: " << arg.time_millis_buckets(i);
1006 return false;
1007 }
1008 if (arg.frame_counts(i) != expected.frame_counts(i)) {
1009 *result_listener << "frame_counts[" << i
1010 << "] is different. Expected: " << expected.frame_counts(i)
1011 << ". Actual: " << arg.frame_counts(i);
1012 return false;
1013 }
1014 }
1015 return true;
Alec Mouri37384342020-01-02 17:23:37 -08001016}
1017
Alec Mouridfad9002020-02-12 17:49:09 -08001018TEST_F(TimeStatsTest, globalStatsCallback) {
1019 constexpr size_t TOTAL_FRAMES = 5;
1020 constexpr size_t MISSED_FRAMES = 4;
1021 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
1022 constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001023 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1024 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1025 constexpr nsecs_t APP_DEADLINE_DELTA = 3'000'000;
Alec Mouridfad9002020-02-12 17:49:09 -08001026
Alec Mouridfad9002020-02-12 17:49:09 -08001027 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1028
1029 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
1030 mTimeStats->incrementTotalFrames();
1031 }
1032 for (size_t i = 0; i < MISSED_FRAMES; i++) {
1033 mTimeStats->incrementMissedFrames();
1034 }
1035 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
1036 mTimeStats->incrementClientCompositionFrames();
1037 }
1038
Alec Mouri9a29e672020-09-14 12:39:14 -07001039 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1040
Alec Mouridfad9002020-02-12 17:49:09 -08001041 mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
Peiyong Lin65248e02020-04-18 21:15:07 -07001042 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouridfad9002020-02-12 17:49:09 -08001043 mTimeStats->recordFrameDuration(1000000, 3000000);
1044 mTimeStats->recordRenderEngineDuration(2000000, 4000000);
1045 mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
1046
1047 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1048 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1049
Alec Mouri363faf02021-01-29 16:34:55 -08001050 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001051 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001052 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1053 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001054 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001055 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001056 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1057 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001058 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001059 kGameMode, JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001060 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001061 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001062 kGameMode, JankType::AppDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001063 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1064 APP_DEADLINE_DELTA});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001065 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001066 kGameMode, JankType::SurfaceFlingerScheduling,
1067 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1068 APP_DEADLINE_DELTA});
1069 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1070 kGameMode, JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
1071 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1072 mTimeStats->incrementJankyFrames(
1073 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
1074 JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1075 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1076 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1077 kGameMode, JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001078 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001079 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001080 kGameMode, JankType::None, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001081 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri9a29e672020-09-14 12:39:14 -07001082
Tej Singhe2751772021-04-06 22:05:29 -07001083 std::string pulledData;
1084 EXPECT_TRUE(mTimeStats->onPullAtom(10062 /*SURFACEFLINGER_STATS_GLOBAL_INFO*/, &pulledData));
Alec Mouridfad9002020-02-12 17:49:09 -08001085
Tej Singhe2751772021-04-06 22:05:29 -07001086 android::surfaceflinger::SurfaceflingerStatsGlobalInfoWrapper atomList;
1087 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1088 ASSERT_EQ(atomList.atom_size(), 1);
1089 const android::surfaceflinger::SurfaceflingerStatsGlobalInfo& atom = atomList.atom(0);
Alec Mouridfad9002020-02-12 17:49:09 -08001090
Tej Singhe2751772021-04-06 22:05:29 -07001091 EXPECT_EQ(atom.total_frames(), TOTAL_FRAMES);
1092 EXPECT_EQ(atom.missed_frames(), MISSED_FRAMES);
1093 EXPECT_EQ(atom.client_composition_frames(), CLIENT_COMPOSITION_FRAMES);
1094 // Display on millis is not checked.
1095 EXPECT_EQ(atom.animation_millis(), 2);
1096 EXPECT_EQ(atom.event_connection_count(), DISPLAY_EVENT_CONNECTIONS);
1097 EXPECT_THAT(atom.frame_duration(), HistogramEq(buildExpectedHistogram({2}, {1})));
1098 EXPECT_THAT(atom.render_engine_timing(), HistogramEq(buildExpectedHistogram({1, 2}, {1, 1})));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001099 EXPECT_EQ(atom.total_timeline_frames(), 9);
Tej Singhe2751772021-04-06 22:05:29 -07001100 EXPECT_EQ(atom.total_janky_frames(), 7);
1101 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1102 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1103 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1104 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1105 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1106 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001107 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 2);
Tej Singhe2751772021-04-06 22:05:29 -07001108 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1109 EXPECT_THAT(atom.sf_deadline_misses(), HistogramEq(buildExpectedHistogram({1}, {7})));
1110 EXPECT_THAT(atom.sf_prediction_errors(), HistogramEq(buildExpectedHistogram({2}, {7})));
1111 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
Alec Mouridfad9002020-02-12 17:49:09 -08001112
1113 SFTimeStatsGlobalProto globalProto;
1114 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1115
1116 EXPECT_EQ(0, globalProto.total_frames());
1117 EXPECT_EQ(0, globalProto.missed_frames());
1118 EXPECT_EQ(0, globalProto.client_composition_frames());
1119 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001120
1121 // also check dump-only stats: expect that global stats are indeed dropped but there should
1122 // still be stats for the layer
1123 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1124 std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
1125 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001126 expectedResult = "totalTimelineFrames = " + std::to_string(9);
Alec Mouri56e63852021-03-09 18:17:25 -08001127 EXPECT_THAT(result, HasSubstr(expectedResult));
1128 expectedResult = "jankyFrames = " + std::to_string(0);
1129 EXPECT_THAT(result, HasSubstr(expectedResult));
1130 expectedResult = "jankyFrames = " + std::to_string(7);
1131 EXPECT_THAT(result, HasSubstr(expectedResult));
1132 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
1133 EXPECT_THAT(result, HasSubstr(expectedResult));
1134 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1135 EXPECT_THAT(result, HasSubstr(expectedResult));
1136 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
1137 EXPECT_THAT(result, HasSubstr(expectedResult));
1138 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1139 EXPECT_THAT(result, HasSubstr(expectedResult));
1140 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
1141 EXPECT_THAT(result, HasSubstr(expectedResult));
1142 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1143 EXPECT_THAT(result, HasSubstr(expectedResult));
1144 expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
1145 EXPECT_THAT(result, HasSubstr(expectedResult));
1146 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1147 EXPECT_THAT(result, HasSubstr(expectedResult));
1148 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
1149 EXPECT_THAT(result, HasSubstr(expectedResult));
1150 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1151 EXPECT_THAT(result, HasSubstr(expectedResult));
1152 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
1153 EXPECT_THAT(result, HasSubstr(expectedResult));
1154 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1155 EXPECT_THAT(result, HasSubstr(expectedResult));
1156 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
1157 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001158 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(2);
Alec Mouri56e63852021-03-09 18:17:25 -08001159 EXPECT_THAT(result, HasSubstr(expectedResult));
Alec Mouridfad9002020-02-12 17:49:09 -08001160}
1161
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001162TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
1163 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1164 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001165 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1166 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1167 constexpr nsecs_t APP_DEADLINE_DELTA_2MS = 2'000'000;
1168 constexpr nsecs_t APP_DEADLINE_DELTA_3MS = 3'000'000;
Alec Mouri37384342020-01-02 17:23:37 -08001169 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1170
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001171 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {}, GameMode::Standard);
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001172 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1173 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1174 }
1175 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1176 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1177 }
Ady Abraham8b9e6122021-01-26 19:11:45 -08001178 const auto frameRate60 = TimeStats::SetFrameRateVote{
1179 .frameRate = 60.0f,
1180 .frameRateCompatibility =
1181 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1182 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1183 };
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001184 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60, GameMode::Standard);
Alec Mouri37384342020-01-02 17:23:37 -08001185
Alec Mouri363faf02021-01-29 16:34:55 -08001186 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001187 GameMode::Standard, JankType::SurfaceFlingerCpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001188 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1189 APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001190 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001191 GameMode::Standard, JankType::SurfaceFlingerGpuDeadlineMissed,
1192 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1193 APP_DEADLINE_DELTA_3MS});
1194 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1195 GameMode::Standard, JankType::DisplayHAL,
1196 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1197 APP_DEADLINE_DELTA_3MS});
1198 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1199 GameMode::Standard, JankType::AppDeadlineMissed,
1200 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1201 APP_DEADLINE_DELTA_3MS});
1202 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1203 GameMode::Standard, JankType::SurfaceFlingerScheduling,
1204 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1205 APP_DEADLINE_DELTA_2MS});
1206 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1207 GameMode::Standard, JankType::PredictionError,
1208 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1209 APP_DEADLINE_DELTA_2MS});
1210 mTimeStats->incrementJankyFrames(
1211 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), GameMode::Standard,
1212 JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1213 APP_DEADLINE_DELTA_2MS, APP_DEADLINE_DELTA_2MS});
1214 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1215 GameMode::Standard, JankType::None, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001216 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri9a29e672020-09-14 12:39:14 -07001217
Tej Singhe2751772021-04-06 22:05:29 -07001218 std::string pulledData;
1219 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001220
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001221 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001222 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1223 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001224 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Alec Mouri9a29e672020-09-14 12:39:14 -07001225
Tej Singhe2751772021-04-06 22:05:29 -07001226 EXPECT_EQ(atom.layer_name(), genLayerName(LAYER_ID_0));
1227 EXPECT_EQ(atom.total_frames(), 1);
1228 EXPECT_EQ(atom.dropped_frames(), 0);
1229 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1230 EXPECT_THAT(atom.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1231 EXPECT_THAT(atom.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1232 EXPECT_THAT(atom.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1233 EXPECT_THAT(atom.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1234 EXPECT_THAT(atom.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1235 EXPECT_EQ(atom.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1236 EXPECT_EQ(atom.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1237 EXPECT_EQ(atom.uid(), UID_0);
1238 EXPECT_EQ(atom.total_timeline_frames(), 8);
1239 EXPECT_EQ(atom.total_janky_frames(), 7);
1240 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1241 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1242 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1243 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1244 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1245 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1246 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 1);
1247 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1248 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1249 EXPECT_THAT(atom.set_frame_rate_vote().frame_rate(), testing::FloatEq(frameRate60.frameRate));
1250 EXPECT_EQ((int)atom.set_frame_rate_vote().frame_rate_compatibility(),
1251 (int)frameRate60.frameRateCompatibility);
1252 EXPECT_EQ((int)atom.set_frame_rate_vote().seamlessness(), (int)frameRate60.seamlessness);
1253 EXPECT_THAT(atom.app_deadline_misses(), HistogramEq(buildExpectedHistogram({3, 2}, {4, 3})));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001254 EXPECT_EQ(atom.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
Alec Mouri37384342020-01-02 17:23:37 -08001255
1256 SFTimeStatsGlobalProto globalProto;
1257 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1258
1259 EXPECT_EQ(0, globalProto.stats_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001260
1261 // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1262 // be global stats
1263 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1264 std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1265 EXPECT_THAT(result, HasSubstr(expectedResult));
1266 expectedResult = "jankyFrames = " + std::to_string(7);
1267 EXPECT_THAT(result, HasSubstr(expectedResult));
1268 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1269 EXPECT_THAT(result, HasSubstr(expectedResult));
1270 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1271 EXPECT_THAT(result, HasSubstr(expectedResult));
1272 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1273 EXPECT_THAT(result, HasSubstr(expectedResult));
1274 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1275 EXPECT_THAT(result, HasSubstr(expectedResult));
1276 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1277 EXPECT_THAT(result, HasSubstr(expectedResult));
1278 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1279 EXPECT_THAT(result, HasSubstr(expectedResult));
1280 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1281 EXPECT_THAT(result, HasSubstr(expectedResult));
1282
1283 std::string expectedMissing = "uid = " + std::to_string(UID_0);
1284 EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
Alec Mouri37384342020-01-02 17:23:37 -08001285}
1286
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001287TEST_F(TimeStatsTest, layerStatsCallback_multipleGameModes) {
1288 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1289 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1290 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1291
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001292 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {}, GameMode::Standard);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001293 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1294 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1295 }
1296 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1297 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1298 }
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001299
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001300 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, {}, GameMode::Standard);
1301 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, {}, GameMode::Performance);
1302 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 4000000, {}, GameMode::Battery);
1303 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 5, 4000000, {}, GameMode::Battery);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001304
1305 std::string pulledData;
1306 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1307
1308 SurfaceflingerStatsLayerInfoWrapper atomList;
1309 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1310 // The first time record is never uploaded to stats.
1311 ASSERT_EQ(atomList.atom_size(), 3);
1312 // Layers are ordered based on the hash in LayerStatsKey. For this test, the order happens to
1313 // be: 0 - Battery 1 - Performance 2 - Standard
1314 const SurfaceflingerStatsLayerInfo& atom0 = atomList.atom(0);
1315
1316 EXPECT_EQ(atom0.layer_name(), genLayerName(LAYER_ID_0));
1317 EXPECT_EQ(atom0.total_frames(), 2);
1318 EXPECT_EQ(atom0.dropped_frames(), 0);
1319 EXPECT_THAT(atom0.present_to_present(), HistogramEq(buildExpectedHistogram({0, 1}, {1, 1})));
1320 EXPECT_THAT(atom0.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {2})));
1321 EXPECT_THAT(atom0.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {2})));
1322 EXPECT_THAT(atom0.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {2})));
1323 EXPECT_THAT(atom0.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1324 EXPECT_THAT(atom0.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {2})));
1325 EXPECT_EQ(atom0.late_acquire_frames(), 0);
1326 EXPECT_EQ(atom0.bad_desired_present_frames(), 0);
1327 EXPECT_EQ(atom0.uid(), UID_0);
1328 EXPECT_EQ(atom0.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1329 EXPECT_EQ(atom0.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1330 EXPECT_EQ(atom0.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_BATTERY);
1331
1332 const SurfaceflingerStatsLayerInfo& atom1 = atomList.atom(1);
1333
1334 EXPECT_EQ(atom1.layer_name(), genLayerName(LAYER_ID_0));
1335 EXPECT_EQ(atom1.total_frames(), 1);
1336 EXPECT_EQ(atom1.dropped_frames(), 0);
1337 EXPECT_THAT(atom1.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1338 EXPECT_THAT(atom1.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1339 EXPECT_THAT(atom1.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1340 EXPECT_THAT(atom1.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1341 EXPECT_THAT(atom1.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1342 EXPECT_THAT(atom1.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1343 EXPECT_EQ(atom1.late_acquire_frames(), 0);
1344 EXPECT_EQ(atom1.bad_desired_present_frames(), 0);
1345 EXPECT_EQ(atom1.uid(), UID_0);
1346 EXPECT_EQ(atom1.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1347 EXPECT_EQ(atom1.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1348 EXPECT_EQ(atom1.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_PERFORMANCE);
1349
1350 const SurfaceflingerStatsLayerInfo& atom2 = atomList.atom(2);
1351
1352 EXPECT_EQ(atom2.layer_name(), genLayerName(LAYER_ID_0));
1353 EXPECT_EQ(atom2.total_frames(), 1);
1354 EXPECT_EQ(atom2.dropped_frames(), 0);
1355 EXPECT_THAT(atom2.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1356 EXPECT_THAT(atom2.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1357 EXPECT_THAT(atom2.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1358 EXPECT_THAT(atom2.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1359 EXPECT_THAT(atom2.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1360 EXPECT_THAT(atom2.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1361 EXPECT_EQ(atom2.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1362 EXPECT_EQ(atom2.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1363 EXPECT_EQ(atom2.uid(), UID_0);
1364 EXPECT_EQ(atom2.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1365 EXPECT_EQ(atom2.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1366 EXPECT_EQ(atom2.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
1367}
1368
Alec Mouri37384342020-01-02 17:23:37 -08001369TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1370 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1371
Alec Mouri37384342020-01-02 17:23:37 -08001372 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1373 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1374 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1375 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1376
Tej Singhe2751772021-04-06 22:05:29 -07001377 std::string pulledData;
1378 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001379
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001380 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001381 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1382 ASSERT_EQ(atomList.atom_size(), 2);
1383 std::vector<std::string> actualLayerNames = {atomList.atom(0).layer_name(),
1384 atomList.atom(1).layer_name()};
1385 EXPECT_THAT(actualLayerNames,
1386 UnorderedElementsAre(genLayerName(LAYER_ID_0), genLayerName(LAYER_ID_1)));
Alec Mouri37384342020-01-02 17:23:37 -08001387}
1388
1389TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1390 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1391
Alec Mouri37384342020-01-02 17:23:37 -08001392 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1393 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1394 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1395 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1396
Tej Singh38a4b212020-03-13 19:04:51 -07001397 // Now make sure that TimeStats flushes global stats to set the callback.
Peiyong Lin65248e02020-04-18 21:15:07 -07001398 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouri37384342020-01-02 17:23:37 -08001399 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1400 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
Alec Mouri37384342020-01-02 17:23:37 -08001401
Tej Singhe2751772021-04-06 22:05:29 -07001402 std::string pulledData;
1403 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1404
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001405 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001406 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1407 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001408 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001409 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1, 2}, {2, 1})));
Alec Mouri37384342020-01-02 17:23:37 -08001410}
1411
1412TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
Tej Singhe2751772021-04-06 22:05:29 -07001413 mTimeStats = std::make_unique<impl::TimeStats>(std::nullopt, 1);
Alec Mouri37384342020-01-02 17:23:37 -08001414 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1415
Alec Mouri37384342020-01-02 17:23:37 -08001416 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1417 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1418 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1419 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1420
Tej Singhe2751772021-04-06 22:05:29 -07001421 std::string pulledData;
1422 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001423
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001424 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001425 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1426 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001427 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001428 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
Alec Mouri37384342020-01-02 17:23:37 -08001429}
1430
1431TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
Tej Singhe2751772021-04-06 22:05:29 -07001432 mTimeStats = std::make_unique<impl::TimeStats>(1, std::nullopt);
Alec Mouri37384342020-01-02 17:23:37 -08001433 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1434
Alec Mouri37384342020-01-02 17:23:37 -08001435 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1436 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1437 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1438 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1439 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1440
Tej Singhe2751772021-04-06 22:05:29 -07001441 std::string pulledData;
1442 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001443
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001444 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001445 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1446 ASSERT_EQ(atomList.atom_size(), 1);
1447 EXPECT_EQ(atomList.atom(0).layer_name(), genLayerName(LAYER_ID_1));
Alec Mouri37384342020-01-02 17:23:37 -08001448}
1449
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001450TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -08001451 if (g_noSlowTests) {
1452 GTEST_SKIP();
1453 }
1454
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001455 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1456
1457 for (size_t i = 0; i < 10000000; ++i) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001458 const int32_t layerId = genRandomInt32(-1, 10);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001459 const int32_t frameNumber = genRandomInt32(1, 10);
1460 switch (genRandomInt32(0, 100)) {
1461 case 0:
1462 ALOGV("removeTimeRecord");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001463 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001464 continue;
1465 case 1:
1466 ALOGV("onDestroy");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001467 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001468 continue;
1469 }
1470 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1471 const int32_t ts = genRandomInt32(1, 1000000000);
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001472 ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001473 setTimeStamp(type, layerId, frameNumber, ts, {}, kGameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001474 }
1475}
1476
Ady Abraham3403a3f2021-04-27 16:58:40 -07001477TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) {
1478 // this stat is not in the proto so verify by checking the string dump
1479 const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) {
1480 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
1481 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1482
1483 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001484 mTimeStats->incrementJankyFrames({fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0),
1485 kGameMode, JankType::None, 0, 0, 0});
Ady Abraham3403a3f2021-04-27 16:58:40 -07001486 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1487 std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps";
1488 EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps;
1489 };
1490
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001491 verifyRefreshRateBucket(91_Hz, 90);
1492 verifyRefreshRateBucket(89_Hz, 90);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001493
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001494 verifyRefreshRateBucket(61_Hz, 60);
1495 verifyRefreshRateBucket(59_Hz, 60);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001496
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001497 verifyRefreshRateBucket(31_Hz, 30);
1498 verifyRefreshRateBucket(29_Hz, 30);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001499}
1500
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001501} // namespace
1502} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001503
1504// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +01001505#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"