blob: 0aaefe3b9298cc911adfdd074d7d6df1822fa852 [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 }
Vishnu Nair9cf89262022-02-26 09:17:49 -0800271 TimeStats::ClientCompositionRecord record;
272 record.hadClientComposition = true;
273
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800274 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
Vishnu Nair9cf89262022-02-26 09:17:49 -0800275 ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState(record));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800276 }
277
278 SFTimeStatsGlobalProto globalProto;
279 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
280
281 ASSERT_TRUE(globalProto.has_total_frames());
282 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
283 ASSERT_TRUE(globalProto.has_missed_frames());
284 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
285 ASSERT_TRUE(globalProto.has_client_composition_frames());
286 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
287}
288
Alec Mouri91f6df32020-01-30 08:48:58 -0800289TEST_F(TimeStatsTest, canIncreaseLateAcquireFrames) {
290 // this stat is not in the proto so verify by checking the string dump
291 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
292
293 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
294
295 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
296 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
297 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
298 }
299 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
300
301 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
302 const std::string expectedResult = "lateAcquireFrames = " + std::to_string(LATE_ACQUIRE_FRAMES);
303 EXPECT_THAT(result, HasSubstr(expectedResult));
304}
305
306TEST_F(TimeStatsTest, canIncreaseBadDesiredPresent) {
307 // this stat is not in the proto so verify by checking the string dump
308 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 2;
309
310 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
311
312 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
313 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
314 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
315 }
316 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
317
318 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
319 const std::string expectedResult =
320 "badDesiredPresentFrames = " + std::to_string(BAD_DESIRED_PRESENT_FRAMES);
321 EXPECT_THAT(result, HasSubstr(expectedResult));
322}
323
Alec Mouri9a29e672020-09-14 12:39:14 -0700324TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
325 // this stat is not in the proto so verify by checking the string dump
326 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
327
328 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mouri363faf02021-01-29 16:34:55 -0800329 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000330 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000331 3});
332 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000333 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
334 3});
335 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
336 kGameMode, JankType::DisplayHAL, 1, 2, 3});
337 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
338 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
339 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
340 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
341 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
342 kGameMode, JankType::PredictionError, 1, 2, 3});
343 mTimeStats->incrementJankyFrames(
344 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
345 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
346 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
347 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700348
349 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
Alec Mouri7d436ec2021-01-27 20:40:50 -0800350 std::string expectedResult =
351 "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
352 EXPECT_THAT(result, HasSubstr(expectedResult));
353 expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
354 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000355 expectedResult = "totalTimelineFrames = " + std::to_string(8);
Alec Mouri9a29e672020-09-14 12:39:14 -0700356 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000357 expectedResult = "jankyFrames = " + std::to_string(7);
Alec Mouri9a29e672020-09-14 12:39:14 -0700358 EXPECT_THAT(result, HasSubstr(expectedResult));
359 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
360 EXPECT_THAT(result, HasSubstr(expectedResult));
361 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
362 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000363 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700364 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000365 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
366 EXPECT_THAT(result, HasSubstr(expectedResult));
367 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
368 EXPECT_THAT(result, HasSubstr(expectedResult));
369 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
370 EXPECT_THAT(result, HasSubstr(expectedResult));
371 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700372 EXPECT_THAT(result, HasSubstr(expectedResult));
373}
374
Ady Abraham8b9e6122021-01-26 19:11:45 -0800375TEST_F(TimeStatsTest, canCaptureSetFrameRateVote) {
376 // this stat is not in the proto so verify by checking the string dump
377 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
378
379 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
380
381 const auto frameRate60 = TimeStats::SetFrameRateVote{
382 .frameRate = 60.0f,
383 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
384 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
385 };
386 const auto frameRate90 = TimeStats::SetFrameRateVote{
387 .frameRate = 90.0f,
388 .frameRateCompatibility =
389 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
390 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
391 };
392 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
393 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
394 std::string expectedResult = "frameRate = 60.00";
395 EXPECT_THAT(result, HasSubstr(expectedResult));
396 expectedResult = "frameRateCompatibility = Default";
397 EXPECT_THAT(result, HasSubstr(expectedResult));
398 expectedResult = "seamlessness = ShouldBeSeamless";
399 EXPECT_THAT(result, HasSubstr(expectedResult));
400
401 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRate90);
402 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
403 expectedResult = "frameRate = 90.00";
404 EXPECT_THAT(result, HasSubstr(expectedResult));
405 expectedResult = "frameRateCompatibility = ExactOrMultiple";
406 EXPECT_THAT(result, HasSubstr(expectedResult));
407 expectedResult = "seamlessness = NotRequired";
408 EXPECT_THAT(result, HasSubstr(expectedResult));
409
410 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRate60);
411 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
412 expectedResult = "frameRate = 60.00";
413 EXPECT_THAT(result, HasSubstr(expectedResult));
414 expectedResult = "frameRateCompatibility = Default";
415 EXPECT_THAT(result, HasSubstr(expectedResult));
416 expectedResult = "seamlessness = ShouldBeSeamless";
417 EXPECT_THAT(result, HasSubstr(expectedResult));
418}
419
420TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) {
421 // this stat is not in the proto so verify by checking the string dump
422 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
423
424 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
425
426 const auto frameRate90 = TimeStats::SetFrameRateVote{
427 .frameRate = 90.0f,
428 .frameRateCompatibility =
429 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
430 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
431 };
432 const auto frameRateDefault = TimeStats::SetFrameRateVote{
433 .frameRate = 0.0f,
434 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
435 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
436 };
437 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate90);
438 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
439 std::string expectedResult = "frameRate = 90.00";
440 EXPECT_THAT(result, HasSubstr(expectedResult));
441 expectedResult = "frameRateCompatibility = ExactOrMultiple";
442 EXPECT_THAT(result, HasSubstr(expectedResult));
443 expectedResult = "seamlessness = NotRequired";
444 EXPECT_THAT(result, HasSubstr(expectedResult));
445
446 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRateDefault);
447 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
448 expectedResult = "frameRate = 90.00";
449 EXPECT_THAT(result, HasSubstr(expectedResult));
450 expectedResult = "frameRateCompatibility = ExactOrMultiple";
451 EXPECT_THAT(result, HasSubstr(expectedResult));
452 expectedResult = "seamlessness = NotRequired";
453 EXPECT_THAT(result, HasSubstr(expectedResult));
454
455 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRateDefault);
456 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
457 expectedResult = "frameRate = 90.00";
458 EXPECT_THAT(result, HasSubstr(expectedResult));
459 expectedResult = "frameRateCompatibility = ExactOrMultiple";
460 EXPECT_THAT(result, HasSubstr(expectedResult));
461 expectedResult = "seamlessness = NotRequired";
462 EXPECT_THAT(result, HasSubstr(expectedResult));
463}
464
Vishnu Nair9cf89262022-02-26 09:17:49 -0800465TEST_F(TimeStatsTest, canIncreaseClientCompositionStats) {
Vishnu Nair9b079a22020-01-21 14:36:08 -0800466 // this stat is not in the proto so verify by checking the string dump
Vishnu Nair9cf89262022-02-26 09:17:49 -0800467 constexpr size_t COMPOSITION_STRATEGY_CHANGED_FRAMES = 1;
468 constexpr size_t HAD_CLIENT_COMPOSITION_FRAMES = 2;
469 constexpr size_t REUSED_CLIENT_COMPOSITION_FRAMES = 3;
470 constexpr size_t COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES = 4;
471 constexpr size_t COMPOSITION_STRATEGY_PREDICTED_FRAMES = 5;
Vishnu Nair9b079a22020-01-21 14:36:08 -0800472
473 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Vishnu Nair9cf89262022-02-26 09:17:49 -0800474 for (size_t i = 0; i <= COMPOSITION_STRATEGY_PREDICTED_FRAMES; i++) {
475 TimeStats::ClientCompositionRecord record;
476 record.hadClientComposition = i < HAD_CLIENT_COMPOSITION_FRAMES;
477 record.changed = i < COMPOSITION_STRATEGY_CHANGED_FRAMES;
478 record.reused = i < REUSED_CLIENT_COMPOSITION_FRAMES;
479 record.predicted = i < COMPOSITION_STRATEGY_PREDICTED_FRAMES;
480 record.predictionSucceeded = i < COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES;
481 mTimeStats->pushCompositionStrategyState(record);
Vishnu Nair9b079a22020-01-21 14:36:08 -0800482 }
483
484 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
Vishnu Nair9cf89262022-02-26 09:17:49 -0800485 std::string expected =
486 "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGED_FRAMES);
487 EXPECT_THAT(result, HasSubstr(expected));
488
489 expected = "clientCompositionFrames = " + std::to_string(HAD_CLIENT_COMPOSITION_FRAMES);
490 EXPECT_THAT(result, HasSubstr(expected));
491
492 expected =
493 "clientCompositionReusedFrames = " + std::to_string(REUSED_CLIENT_COMPOSITION_FRAMES);
494 EXPECT_THAT(result, HasSubstr(expected));
495
496 expected = "compositionStrategyPredicted = " +
497 std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES);
498 EXPECT_THAT(result, HasSubstr(expected));
499
500 expected = "compositionStrategyPredictionSucceeded = " +
501 std::to_string(COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES);
502 EXPECT_THAT(result, HasSubstr(expected));
503
504 expected = "compositionStrategyPredictionFailed = " +
505 std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES -
506 COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES);
507 EXPECT_THAT(result, HasSubstr(expected));
Vishnu Nair9b079a22020-01-21 14:36:08 -0800508}
509
Alec Mouri8de697e2020-03-19 10:52:01 -0700510TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
511 // this stat is not in the proto so verify by checking the string dump
512 constexpr size_t REFRESH_RATE_SWITCHES = 2;
513
514 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
515 for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
516 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
517 }
518
519 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
520 const std::string expectedResult =
521 "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
522 EXPECT_THAT(result, HasSubstr(expectedResult));
523}
524
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800525TEST_F(TimeStatsTest, canAverageFrameDuration) {
526 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Peiyong Lin65248e02020-04-18 21:15:07 -0700527 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000528 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
529 std::chrono::nanoseconds(6ms).count());
530 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
531 std::chrono::nanoseconds(16ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800532
533 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
534 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 10.000 ms"));
535}
536
537TEST_F(TimeStatsTest, canAverageRenderEngineTimings) {
538 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Adithya Srinivasanead17162021-02-18 02:17:37 +0000539 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800540 std::make_shared<FenceTime>(
541 std::chrono::duration_cast<
542 std::chrono::nanoseconds>(3ms)
543 .count()));
544
Adithya Srinivasanead17162021-02-18 02:17:37 +0000545 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
546 std::chrono::nanoseconds(8ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800547
Peiyong Lind8460c82020-07-28 16:04:22 -0700548 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700549 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000550 mTimeStats->setPresentFenceGlobal(
551 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800552
553 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
554 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 3.000 ms"));
555}
556
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800557TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
558 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
559
560 ASSERT_NO_FATAL_FAILURE(
561 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
562 ASSERT_NO_FATAL_FAILURE(
563 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
564
Peiyong Lin65248e02020-04-18 21:15:07 -0700565 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800566 ASSERT_NO_FATAL_FAILURE(
567 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
568 ASSERT_NO_FATAL_FAILURE(
569 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
570
Peiyong Lin65248e02020-04-18 21:15:07 -0700571 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800572 ASSERT_NO_FATAL_FAILURE(
573 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
574 ASSERT_NO_FATAL_FAILURE(
575 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
576
577 SFTimeStatsGlobalProto globalProto;
578 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
579
580 ASSERT_EQ(1, globalProto.present_to_present_size());
581 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
582 EXPECT_EQ(1, histogramProto.frame_count());
583 EXPECT_EQ(2, histogramProto.time_millis());
584}
585
Alec Mouri9519bf12019-11-15 16:54:44 -0800586TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
587 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
588
Peiyong Lin65248e02020-04-18 21:15:07 -0700589 mTimeStats->setPowerMode(PowerMode::OFF);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000590 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
591 std::chrono::nanoseconds(5ms).count());
Peiyong Lin65248e02020-04-18 21:15:07 -0700592 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000593 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
594 std::chrono::nanoseconds(6ms).count());
Alec Mouri9519bf12019-11-15 16:54:44 -0800595
596 SFTimeStatsGlobalProto globalProto;
597 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
598
599 ASSERT_EQ(1, globalProto.frame_duration_size());
600 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.frame_duration().Get(0);
601 EXPECT_EQ(1, histogramProto.frame_count());
602 EXPECT_EQ(3, histogramProto.time_millis());
603}
604
Alec Mourie4034bb2019-11-19 12:45:54 -0800605TEST_F(TimeStatsTest, canInsertGlobalRenderEngineTiming) {
606 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
607
Adithya Srinivasanead17162021-02-18 02:17:37 +0000608 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Alec Mourie4034bb2019-11-19 12:45:54 -0800609 std::make_shared<FenceTime>(
610 std::chrono::duration_cast<
611 std::chrono::nanoseconds>(3ms)
612 .count()));
613
Adithya Srinivasanead17162021-02-18 02:17:37 +0000614 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
615 std::chrono::nanoseconds(6ms).count());
Alec Mourie4034bb2019-11-19 12:45:54 -0800616
617 // First verify that flushing RenderEngine durations did not occur yet.
618 SFTimeStatsGlobalProto preFlushProto;
619 ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
620 ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
621
Peiyong Lind8460c82020-07-28 16:04:22 -0700622 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700623 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000624 mTimeStats->setPresentFenceGlobal(
625 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mourie4034bb2019-11-19 12:45:54 -0800626
627 // Now we can verify that RenderEngine durations were flushed now.
628 SFTimeStatsGlobalProto postFlushProto;
629 ASSERT_TRUE(postFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
630
631 ASSERT_EQ(1, postFlushProto.render_engine_timing_size());
632 const SFTimeStatsHistogramBucketProto& histogramProto =
633 postFlushProto.render_engine_timing().Get(0);
634 EXPECT_EQ(2, histogramProto.frame_count());
635 EXPECT_EQ(2, histogramProto.time_millis());
636}
637
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800638TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
639 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
640
641 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
642 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
643
644 SFTimeStatsGlobalProto globalProto;
645 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
646
647 ASSERT_EQ(1, globalProto.stats_size());
648 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
649 ASSERT_TRUE(layerProto.has_layer_name());
650 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
651 ASSERT_TRUE(layerProto.has_total_frames());
652 EXPECT_EQ(1, layerProto.total_frames());
653 ASSERT_EQ(6, layerProto.deltas_size());
654 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
655 ASSERT_EQ(1, deltaProto.histograms_size());
656 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
657 EXPECT_EQ(1, histogramProto.frame_count());
658 if ("post2acquire" == deltaProto.delta_name()) {
659 EXPECT_EQ(1, histogramProto.time_millis());
660 } else if ("post2present" == deltaProto.delta_name()) {
661 EXPECT_EQ(4, histogramProto.time_millis());
662 } else if ("acquire2present" == deltaProto.delta_name()) {
663 EXPECT_EQ(3, histogramProto.time_millis());
664 } else if ("latch2present" == deltaProto.delta_name()) {
665 EXPECT_EQ(2, histogramProto.time_millis());
666 } else if ("desired2present" == deltaProto.delta_name()) {
667 EXPECT_EQ(1, histogramProto.time_millis());
668 } else if ("present2present" == deltaProto.delta_name()) {
669 EXPECT_EQ(1, histogramProto.time_millis());
670 } else {
671 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
672 }
673 }
674}
675
676TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
677 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
678
679 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
680 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
681
682 SFTimeStatsGlobalProto globalProto;
683 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
684
685 ASSERT_EQ(0, globalProto.stats_size());
686}
687
688TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
689 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
690
691 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
692 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
693 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
694 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
695
696 SFTimeStatsGlobalProto globalProto;
697 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
698
699 EXPECT_EQ(2, globalProto.stats_size());
700}
701
702TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
703 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
704
705 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
706 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
707
708 SFTimeStatsGlobalProto globalProto;
709 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
710
711 ASSERT_EQ(1, globalProto.stats_size());
712 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
713 ASSERT_TRUE(layerProto.has_layer_name());
714 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
715 ASSERT_TRUE(layerProto.has_total_frames());
716 EXPECT_EQ(1, layerProto.total_frames());
717 ASSERT_EQ(6, layerProto.deltas_size());
718 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
719 ASSERT_EQ(1, deltaProto.histograms_size());
720 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
721 EXPECT_EQ(1, histogramProto.frame_count());
722 if ("post2acquire" == deltaProto.delta_name()) {
723 EXPECT_EQ(0, histogramProto.time_millis());
724 } else if ("post2present" == deltaProto.delta_name()) {
725 EXPECT_EQ(2, histogramProto.time_millis());
726 } else if ("acquire2present" == deltaProto.delta_name()) {
727 EXPECT_EQ(2, histogramProto.time_millis());
728 } else if ("latch2present" == deltaProto.delta_name()) {
729 EXPECT_EQ(2, histogramProto.time_millis());
730 } else if ("desired2present" == deltaProto.delta_name()) {
731 EXPECT_EQ(1, histogramProto.time_millis());
732 } else if ("present2present" == deltaProto.delta_name()) {
733 EXPECT_EQ(1, histogramProto.time_millis());
734 } else {
735 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
736 }
737 }
738}
739
Alec Mourifb571ea2019-01-24 18:42:10 -0800740TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
741 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
742
743 uint32_t fpsOne = 30;
744 uint32_t fpsTwo = 90;
745 uint64_t millisOne = 5000;
746 uint64_t millisTwo = 7000;
747
748 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
749 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
750
751 SFTimeStatsGlobalProto globalProto;
752 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
753
754 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
755 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
756 expectedConfigOne->set_fps(fpsOne);
757 expectedBucketOne.set_duration_millis(millisOne);
758
759 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
760 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
761 expectedConfigTwo->set_fps(fpsTwo);
762 expectedBucketTwo.set_duration_millis(millisTwo);
763
764 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
765
766 std::unordered_set<uint32_t> seen_fps;
767 for (const auto& bucket : globalProto.display_config_stats()) {
768 seen_fps.emplace(bucket.config().fps());
769 if (fpsOne == bucket.config().fps()) {
770 EXPECT_EQ(millisOne, bucket.duration_millis());
771 } else if (fpsTwo == bucket.config().fps()) {
772 EXPECT_EQ(millisTwo, bucket.duration_millis());
773 } else {
774 FAIL() << "Unknown fps: " << bucket.config().fps();
775 }
776 }
777 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
778}
779
780TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
781 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
782
783 uint32_t fps = 30;
784 uint64_t millisOne = 5000;
785 uint64_t millisTwo = 7000;
786
787 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
788 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
789
790 SFTimeStatsGlobalProto globalProto;
791 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
792 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
793 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
794 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
795}
796
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800797TEST_F(TimeStatsTest, canRemoveTimeRecord) {
798 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
799
800 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
801 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
802 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
803 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
804
805 SFTimeStatsGlobalProto globalProto;
806 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
807
808 ASSERT_EQ(1, globalProto.stats_size());
809 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
810 ASSERT_TRUE(layerProto.has_total_frames());
811 EXPECT_EQ(1, layerProto.total_frames());
812}
813
814TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
815 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
816
817 uint64_t frameNumber = 1;
818 nsecs_t ts = 1000000;
819 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800820 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800821 frameNumber++;
822 ts += 1000000;
823 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
824 }
825
826 SFTimeStatsGlobalProto globalProto;
827 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
828
829 ASSERT_EQ(1, globalProto.stats_size());
830 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
831 ASSERT_TRUE(layerProto.has_total_frames());
832 EXPECT_EQ(1, layerProto.total_frames());
833}
834
835TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
836 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
837
838 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
839 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
840 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
841 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
842
843 SFTimeStatsGlobalProto globalProto;
844 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
845
846 ASSERT_EQ(1, globalProto.stats_size());
847 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
848 ASSERT_TRUE(layerProto.has_total_frames());
849 EXPECT_EQ(1, layerProto.total_frames());
850}
851
852TEST_F(TimeStatsTest, canClearTimeStats) {
853 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
854
855 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
856 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
Vishnu Nair9cf89262022-02-26 09:17:49 -0800857 ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({}));
Peiyong Lin65248e02020-04-18 21:15:07 -0700858 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Alec Mouri31ac64a2020-01-09 09:26:22 -0800859
Adithya Srinivasanead17162021-02-18 02:17:37 +0000860 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
861 std::chrono::nanoseconds(6ms).count());
862 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
863 std::chrono::nanoseconds(6ms).count());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800864 ASSERT_NO_FATAL_FAILURE(
865 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
866 ASSERT_NO_FATAL_FAILURE(
867 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
868 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
869 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
870
871 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
872
873 SFTimeStatsGlobalProto globalProto;
874 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
875
876 EXPECT_EQ(0, globalProto.total_frames());
877 EXPECT_EQ(0, globalProto.missed_frames());
878 EXPECT_EQ(0, globalProto.client_composition_frames());
879 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri31ac64a2020-01-09 09:26:22 -0800880 EXPECT_EQ(0, globalProto.frame_duration_size());
881 EXPECT_EQ(0, globalProto.render_engine_timing_size());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800882 EXPECT_EQ(0, globalProto.stats_size());
883}
884
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800885TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) {
886 // These stats are not in the proto so verify by checking the string dump.
Vishnu Nair9b079a22020-01-21 14:36:08 -0800887 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Vishnu Nair9cf89262022-02-26 09:17:49 -0800888 ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({}));
Alec Mouri8de697e2020-03-19 10:52:01 -0700889 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
Peiyong Lin65248e02020-04-18 21:15:07 -0700890 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000891 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
892 std::chrono::nanoseconds(5ms).count());
893 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
894 std::chrono::nanoseconds(6ms).count());
895 mTimeStats->setPresentFenceGlobal(
896 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mouri9a29e672020-09-14 12:39:14 -0700897
Alec Mouri363faf02021-01-29 16:34:55 -0800898 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000899 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000900 3});
901 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000902 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
903 3});
904 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
905 kGameMode, JankType::DisplayHAL, 1, 2, 3});
906 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
907 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
908 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
909 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
910 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
911 kGameMode, JankType::PredictionError, 1, 2, 3});
912 mTimeStats->incrementJankyFrames(
913 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
914 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
915 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
916 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700917
Vishnu Nair9b079a22020-01-21 14:36:08 -0800918 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
919
920 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
921 EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
Alec Mouri8de697e2020-03-19 10:52:01 -0700922 EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
Alec Mouri8f7a0102020-04-15 12:11:10 -0700923 EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800924 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
925 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
Ady Abraham3403a3f2021-04-27 16:58:40 -0700926 std::string expectedResult = "totalTimelineFrames = ";
927 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
928 expectedResult = "jankyFrames = ";
929 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
930 expectedResult = "sfLongCpuJankyFrames = ";
931 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
932 expectedResult = "sfLongGpuJankyFrames = ";
933 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
934 expectedResult = "sfUnattributedJankyFrames = ";
935 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
936 expectedResult = "appUnattributedJankyFrames = ";
937 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
938 expectedResult = "sfSchedulingJankyFrames = ";
939 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
940 expectedResult = "sfPredictionErrorJankyFrames = ";
941 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
942 expectedResult = "appBufferStuffingJankyFrames = ";
943 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
Vishnu Nair9b079a22020-01-21 14:36:08 -0800944}
945
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800946TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
947 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
948
949 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
950 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
951 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
952 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
953 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
954
955 SFTimeStatsGlobalProto globalProto;
956 ASSERT_TRUE(
957 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
958
959 ASSERT_EQ(1, globalProto.stats_size());
960 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
961 ASSERT_TRUE(layerProto.has_layer_name());
962 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
963 ASSERT_TRUE(layerProto.has_total_frames());
964 EXPECT_EQ(2, layerProto.total_frames());
965}
966
967TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
968 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
969
970 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
971 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
972
973 SFTimeStatsGlobalProto globalProto;
974 ASSERT_TRUE(globalProto.ParseFromString(
975 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
976
977 ASSERT_EQ(0, globalProto.stats_size());
978}
979
Yiwei Zhangdd221b22020-06-12 11:06:19 -0700980TEST_F(TimeStatsTest, noInfInAverageFPS) {
981 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
982 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
983 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 1000000);
984
985 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
986 EXPECT_THAT(result, HasSubstr("averageFPS = 0.000"));
987}
988
Alec Mouri37384342020-01-02 17:23:37 -0800989namespace {
Tej Singhe2751772021-04-06 22:05:29 -0700990FrameTimingHistogram buildExpectedHistogram(const std::vector<int32_t>& times,
991 const std::vector<int32_t>& frameCounts) {
992 FrameTimingHistogram histogram;
Alec Mouri37384342020-01-02 17:23:37 -0800993 for (int i = 0; i < times.size(); i++) {
994 ALOGE("Writing time: %d", times[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700995 histogram.add_time_millis_buckets(times[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800996 ALOGE("Writing count: %d", frameCounts[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700997 histogram.add_frame_counts((int64_t)frameCounts[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800998 }
Tej Singhe2751772021-04-06 22:05:29 -0700999 return histogram;
Alec Mouri37384342020-01-02 17:23:37 -08001000}
Alec Mouri37384342020-01-02 17:23:37 -08001001} // namespace
1002
Tej Singhe2751772021-04-06 22:05:29 -07001003MATCHER_P(HistogramEq, expected, "") {
1004 *result_listener << "Histograms are not equal! \n";
Alec Mouri37384342020-01-02 17:23:37 -08001005
Tej Singhe2751772021-04-06 22:05:29 -07001006 if (arg.time_millis_buckets_size() != expected.time_millis_buckets_size()) {
1007 *result_listener << "Time millis bucket are different sizes. Expected: "
1008 << expected.time_millis_buckets_size() << ". Actual "
1009 << arg.time_millis_buckets_size();
1010 return false;
1011 }
1012 if (arg.frame_counts_size() != expected.frame_counts_size()) {
1013 *result_listener << "Frame counts are different sizes. Expected: "
1014 << expected.frame_counts_size() << ". Actual " << arg.frame_counts_size();
1015 return false;
1016 }
Alec Mouri37384342020-01-02 17:23:37 -08001017
Tej Singhe2751772021-04-06 22:05:29 -07001018 for (int i = 0; i < expected.time_millis_buckets_size(); i++) {
1019 if (arg.time_millis_buckets(i) != expected.time_millis_buckets(i)) {
1020 *result_listener << "time_millis_bucket[" << i
1021 << "] is different. Expected: " << expected.time_millis_buckets(i)
1022 << ". Actual: " << arg.time_millis_buckets(i);
1023 return false;
1024 }
1025 if (arg.frame_counts(i) != expected.frame_counts(i)) {
1026 *result_listener << "frame_counts[" << i
1027 << "] is different. Expected: " << expected.frame_counts(i)
1028 << ". Actual: " << arg.frame_counts(i);
1029 return false;
1030 }
1031 }
1032 return true;
Alec Mouri37384342020-01-02 17:23:37 -08001033}
1034
Alec Mouridfad9002020-02-12 17:49:09 -08001035TEST_F(TimeStatsTest, globalStatsCallback) {
1036 constexpr size_t TOTAL_FRAMES = 5;
1037 constexpr size_t MISSED_FRAMES = 4;
1038 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
1039 constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001040 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1041 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1042 constexpr nsecs_t APP_DEADLINE_DELTA = 3'000'000;
Alec Mouridfad9002020-02-12 17:49:09 -08001043
Alec Mouridfad9002020-02-12 17:49:09 -08001044 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1045
1046 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
1047 mTimeStats->incrementTotalFrames();
1048 }
1049 for (size_t i = 0; i < MISSED_FRAMES; i++) {
1050 mTimeStats->incrementMissedFrames();
1051 }
Vishnu Nair9cf89262022-02-26 09:17:49 -08001052 TimeStats::ClientCompositionRecord record;
1053 record.hadClientComposition = true;
Alec Mouridfad9002020-02-12 17:49:09 -08001054 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
Vishnu Nair9cf89262022-02-26 09:17:49 -08001055 mTimeStats->pushCompositionStrategyState(record);
Alec Mouridfad9002020-02-12 17:49:09 -08001056 }
1057
Alec Mouri9a29e672020-09-14 12:39:14 -07001058 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1059
Alec Mouridfad9002020-02-12 17:49:09 -08001060 mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
Peiyong Lin65248e02020-04-18 21:15:07 -07001061 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouridfad9002020-02-12 17:49:09 -08001062 mTimeStats->recordFrameDuration(1000000, 3000000);
1063 mTimeStats->recordRenderEngineDuration(2000000, 4000000);
1064 mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
1065
1066 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1067 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1068
Alec Mouri363faf02021-01-29 16:34:55 -08001069 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001070 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001071 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1072 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001073 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001074 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001075 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1076 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001077 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001078 kGameMode, JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001079 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001080 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001081 kGameMode, JankType::AppDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001082 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1083 APP_DEADLINE_DELTA});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001084 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001085 kGameMode, JankType::SurfaceFlingerScheduling,
1086 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1087 APP_DEADLINE_DELTA});
1088 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1089 kGameMode, JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
1090 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1091 mTimeStats->incrementJankyFrames(
1092 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
1093 JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1094 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1095 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1096 kGameMode, JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001097 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001098 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001099 kGameMode, JankType::None, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001100 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri9a29e672020-09-14 12:39:14 -07001101
Huihong Luo30aa4372022-10-03 14:54:12 -07001102 std::vector<uint8_t> pulledBytes;
1103 EXPECT_TRUE(mTimeStats->onPullAtom(10062 /*SURFACEFLINGER_STATS_GLOBAL_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001104 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001105 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Alec Mouridfad9002020-02-12 17:49:09 -08001106
Tej Singhe2751772021-04-06 22:05:29 -07001107 android::surfaceflinger::SurfaceflingerStatsGlobalInfoWrapper atomList;
1108 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1109 ASSERT_EQ(atomList.atom_size(), 1);
1110 const android::surfaceflinger::SurfaceflingerStatsGlobalInfo& atom = atomList.atom(0);
Alec Mouridfad9002020-02-12 17:49:09 -08001111
Tej Singhe2751772021-04-06 22:05:29 -07001112 EXPECT_EQ(atom.total_frames(), TOTAL_FRAMES);
1113 EXPECT_EQ(atom.missed_frames(), MISSED_FRAMES);
1114 EXPECT_EQ(atom.client_composition_frames(), CLIENT_COMPOSITION_FRAMES);
1115 // Display on millis is not checked.
1116 EXPECT_EQ(atom.animation_millis(), 2);
1117 EXPECT_EQ(atom.event_connection_count(), DISPLAY_EVENT_CONNECTIONS);
1118 EXPECT_THAT(atom.frame_duration(), HistogramEq(buildExpectedHistogram({2}, {1})));
1119 EXPECT_THAT(atom.render_engine_timing(), HistogramEq(buildExpectedHistogram({1, 2}, {1, 1})));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001120 EXPECT_EQ(atom.total_timeline_frames(), 9);
Tej Singhe2751772021-04-06 22:05:29 -07001121 EXPECT_EQ(atom.total_janky_frames(), 7);
1122 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1123 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1124 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1125 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1126 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1127 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001128 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 2);
Tej Singhe2751772021-04-06 22:05:29 -07001129 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1130 EXPECT_THAT(atom.sf_deadline_misses(), HistogramEq(buildExpectedHistogram({1}, {7})));
1131 EXPECT_THAT(atom.sf_prediction_errors(), HistogramEq(buildExpectedHistogram({2}, {7})));
1132 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
Alec Mouridfad9002020-02-12 17:49:09 -08001133
1134 SFTimeStatsGlobalProto globalProto;
1135 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1136
1137 EXPECT_EQ(0, globalProto.total_frames());
1138 EXPECT_EQ(0, globalProto.missed_frames());
1139 EXPECT_EQ(0, globalProto.client_composition_frames());
1140 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001141
1142 // also check dump-only stats: expect that global stats are indeed dropped but there should
1143 // still be stats for the layer
1144 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1145 std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
1146 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001147 expectedResult = "totalTimelineFrames = " + std::to_string(9);
Alec Mouri56e63852021-03-09 18:17:25 -08001148 EXPECT_THAT(result, HasSubstr(expectedResult));
1149 expectedResult = "jankyFrames = " + std::to_string(0);
1150 EXPECT_THAT(result, HasSubstr(expectedResult));
1151 expectedResult = "jankyFrames = " + std::to_string(7);
1152 EXPECT_THAT(result, HasSubstr(expectedResult));
1153 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
1154 EXPECT_THAT(result, HasSubstr(expectedResult));
1155 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1156 EXPECT_THAT(result, HasSubstr(expectedResult));
1157 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
1158 EXPECT_THAT(result, HasSubstr(expectedResult));
1159 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1160 EXPECT_THAT(result, HasSubstr(expectedResult));
1161 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
1162 EXPECT_THAT(result, HasSubstr(expectedResult));
1163 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1164 EXPECT_THAT(result, HasSubstr(expectedResult));
1165 expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
1166 EXPECT_THAT(result, HasSubstr(expectedResult));
1167 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1168 EXPECT_THAT(result, HasSubstr(expectedResult));
1169 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
1170 EXPECT_THAT(result, HasSubstr(expectedResult));
1171 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1172 EXPECT_THAT(result, HasSubstr(expectedResult));
1173 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
1174 EXPECT_THAT(result, HasSubstr(expectedResult));
1175 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1176 EXPECT_THAT(result, HasSubstr(expectedResult));
1177 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
1178 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001179 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(2);
Alec Mouri56e63852021-03-09 18:17:25 -08001180 EXPECT_THAT(result, HasSubstr(expectedResult));
Alec Mouridfad9002020-02-12 17:49:09 -08001181}
1182
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001183TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
1184 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1185 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001186 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1187 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1188 constexpr nsecs_t APP_DEADLINE_DELTA_2MS = 2'000'000;
1189 constexpr nsecs_t APP_DEADLINE_DELTA_3MS = 3'000'000;
Alec Mouri37384342020-01-02 17:23:37 -08001190 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1191
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001192 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {}, GameMode::Standard);
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001193 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1194 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1195 }
1196 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1197 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1198 }
Ady Abraham8b9e6122021-01-26 19:11:45 -08001199 const auto frameRate60 = TimeStats::SetFrameRateVote{
1200 .frameRate = 60.0f,
1201 .frameRateCompatibility =
1202 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1203 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1204 };
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001205 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60, GameMode::Standard);
Alec Mouri37384342020-01-02 17:23:37 -08001206
Alec Mouri363faf02021-01-29 16:34:55 -08001207 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001208 GameMode::Standard, JankType::SurfaceFlingerCpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001209 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1210 APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001211 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001212 GameMode::Standard, JankType::SurfaceFlingerGpuDeadlineMissed,
1213 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1214 APP_DEADLINE_DELTA_3MS});
1215 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1216 GameMode::Standard, JankType::DisplayHAL,
1217 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1218 APP_DEADLINE_DELTA_3MS});
1219 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1220 GameMode::Standard, JankType::AppDeadlineMissed,
1221 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1222 APP_DEADLINE_DELTA_3MS});
1223 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1224 GameMode::Standard, JankType::SurfaceFlingerScheduling,
1225 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1226 APP_DEADLINE_DELTA_2MS});
1227 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1228 GameMode::Standard, JankType::PredictionError,
1229 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1230 APP_DEADLINE_DELTA_2MS});
1231 mTimeStats->incrementJankyFrames(
1232 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), GameMode::Standard,
1233 JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1234 APP_DEADLINE_DELTA_2MS, APP_DEADLINE_DELTA_2MS});
1235 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1236 GameMode::Standard, JankType::None, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001237 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri9a29e672020-09-14 12:39:14 -07001238
Huihong Luo30aa4372022-10-03 14:54:12 -07001239 std::vector<uint8_t> pulledBytes;
1240 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001241 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001242 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Alec Mouri37384342020-01-02 17:23:37 -08001243
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001244 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001245 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1246 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001247 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Alec Mouri9a29e672020-09-14 12:39:14 -07001248
Tej Singhe2751772021-04-06 22:05:29 -07001249 EXPECT_EQ(atom.layer_name(), genLayerName(LAYER_ID_0));
1250 EXPECT_EQ(atom.total_frames(), 1);
1251 EXPECT_EQ(atom.dropped_frames(), 0);
1252 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1253 EXPECT_THAT(atom.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1254 EXPECT_THAT(atom.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1255 EXPECT_THAT(atom.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1256 EXPECT_THAT(atom.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1257 EXPECT_THAT(atom.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1258 EXPECT_EQ(atom.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1259 EXPECT_EQ(atom.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1260 EXPECT_EQ(atom.uid(), UID_0);
1261 EXPECT_EQ(atom.total_timeline_frames(), 8);
1262 EXPECT_EQ(atom.total_janky_frames(), 7);
1263 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1264 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1265 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1266 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1267 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1268 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1269 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 1);
1270 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1271 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1272 EXPECT_THAT(atom.set_frame_rate_vote().frame_rate(), testing::FloatEq(frameRate60.frameRate));
1273 EXPECT_EQ((int)atom.set_frame_rate_vote().frame_rate_compatibility(),
1274 (int)frameRate60.frameRateCompatibility);
1275 EXPECT_EQ((int)atom.set_frame_rate_vote().seamlessness(), (int)frameRate60.seamlessness);
1276 EXPECT_THAT(atom.app_deadline_misses(), HistogramEq(buildExpectedHistogram({3, 2}, {4, 3})));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001277 EXPECT_EQ(atom.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
Alec Mouri37384342020-01-02 17:23:37 -08001278
1279 SFTimeStatsGlobalProto globalProto;
1280 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1281
1282 EXPECT_EQ(0, globalProto.stats_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001283
1284 // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1285 // be global stats
1286 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1287 std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1288 EXPECT_THAT(result, HasSubstr(expectedResult));
1289 expectedResult = "jankyFrames = " + std::to_string(7);
1290 EXPECT_THAT(result, HasSubstr(expectedResult));
1291 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1292 EXPECT_THAT(result, HasSubstr(expectedResult));
1293 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1294 EXPECT_THAT(result, HasSubstr(expectedResult));
1295 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1296 EXPECT_THAT(result, HasSubstr(expectedResult));
1297 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1298 EXPECT_THAT(result, HasSubstr(expectedResult));
1299 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1300 EXPECT_THAT(result, HasSubstr(expectedResult));
1301 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1302 EXPECT_THAT(result, HasSubstr(expectedResult));
1303 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1304 EXPECT_THAT(result, HasSubstr(expectedResult));
1305
1306 std::string expectedMissing = "uid = " + std::to_string(UID_0);
1307 EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
Alec Mouri37384342020-01-02 17:23:37 -08001308}
1309
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001310TEST_F(TimeStatsTest, layerStatsCallback_multipleGameModes) {
1311 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1312 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1313 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1314
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001315 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {}, GameMode::Standard);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001316 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1317 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1318 }
1319 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1320 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1321 }
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001322
Dominik Laskowskif5d0ea52021-09-26 17:27:01 -07001323 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, {}, GameMode::Standard);
1324 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, {}, GameMode::Performance);
1325 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 4000000, {}, GameMode::Battery);
1326 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 5, 4000000, {}, GameMode::Battery);
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001327 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 6, 5000000, {}, GameMode::Custom);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001328
Huihong Luo30aa4372022-10-03 14:54:12 -07001329 std::vector<uint8_t> pulledBytes;
1330 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001331 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001332 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001333
1334 SurfaceflingerStatsLayerInfoWrapper atomList;
1335 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1336 // The first time record is never uploaded to stats.
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001337 ASSERT_EQ(atomList.atom_size(), 4);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001338 // Layers are ordered based on the hash in LayerStatsKey. For this test, the order happens to
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001339 // be: 0 - Battery 1 - Custom 2 - Performance 3 - Standard
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001340 const SurfaceflingerStatsLayerInfo& atom0 = atomList.atom(0);
1341
1342 EXPECT_EQ(atom0.layer_name(), genLayerName(LAYER_ID_0));
1343 EXPECT_EQ(atom0.total_frames(), 2);
1344 EXPECT_EQ(atom0.dropped_frames(), 0);
1345 EXPECT_THAT(atom0.present_to_present(), HistogramEq(buildExpectedHistogram({0, 1}, {1, 1})));
1346 EXPECT_THAT(atom0.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {2})));
1347 EXPECT_THAT(atom0.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {2})));
1348 EXPECT_THAT(atom0.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {2})));
1349 EXPECT_THAT(atom0.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1350 EXPECT_THAT(atom0.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {2})));
1351 EXPECT_EQ(atom0.late_acquire_frames(), 0);
1352 EXPECT_EQ(atom0.bad_desired_present_frames(), 0);
1353 EXPECT_EQ(atom0.uid(), UID_0);
1354 EXPECT_EQ(atom0.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1355 EXPECT_EQ(atom0.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1356 EXPECT_EQ(atom0.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_BATTERY);
1357
1358 const SurfaceflingerStatsLayerInfo& atom1 = atomList.atom(1);
1359
1360 EXPECT_EQ(atom1.layer_name(), genLayerName(LAYER_ID_0));
1361 EXPECT_EQ(atom1.total_frames(), 1);
1362 EXPECT_EQ(atom1.dropped_frames(), 0);
1363 EXPECT_THAT(atom1.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1364 EXPECT_THAT(atom1.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1365 EXPECT_THAT(atom1.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1366 EXPECT_THAT(atom1.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1367 EXPECT_THAT(atom1.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1368 EXPECT_THAT(atom1.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1369 EXPECT_EQ(atom1.late_acquire_frames(), 0);
1370 EXPECT_EQ(atom1.bad_desired_present_frames(), 0);
1371 EXPECT_EQ(atom1.uid(), UID_0);
1372 EXPECT_EQ(atom1.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1373 EXPECT_EQ(atom1.render_rate_bucket(), RENDER_RATE_BUCKET_0);
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001374 EXPECT_EQ(atom1.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_CUSTOM);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001375
1376 const SurfaceflingerStatsLayerInfo& atom2 = atomList.atom(2);
1377
1378 EXPECT_EQ(atom2.layer_name(), genLayerName(LAYER_ID_0));
1379 EXPECT_EQ(atom2.total_frames(), 1);
1380 EXPECT_EQ(atom2.dropped_frames(), 0);
1381 EXPECT_THAT(atom2.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1382 EXPECT_THAT(atom2.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1383 EXPECT_THAT(atom2.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1384 EXPECT_THAT(atom2.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1385 EXPECT_THAT(atom2.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1386 EXPECT_THAT(atom2.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001387 EXPECT_EQ(atom2.late_acquire_frames(), 0);
1388 EXPECT_EQ(atom2.bad_desired_present_frames(), 0);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001389 EXPECT_EQ(atom2.uid(), UID_0);
1390 EXPECT_EQ(atom2.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1391 EXPECT_EQ(atom2.render_rate_bucket(), RENDER_RATE_BUCKET_0);
Xiang Wangf0c5cca2022-11-09 18:03:09 -08001392 EXPECT_EQ(atom2.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_PERFORMANCE);
1393
1394 const SurfaceflingerStatsLayerInfo& atom3 = atomList.atom(3);
1395
1396 EXPECT_EQ(atom3.layer_name(), genLayerName(LAYER_ID_0));
1397 EXPECT_EQ(atom3.total_frames(), 1);
1398 EXPECT_EQ(atom3.dropped_frames(), 0);
1399 EXPECT_THAT(atom3.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1400 EXPECT_THAT(atom3.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1401 EXPECT_THAT(atom3.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1402 EXPECT_THAT(atom3.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1403 EXPECT_THAT(atom3.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1404 EXPECT_THAT(atom3.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1405 EXPECT_EQ(atom3.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1406 EXPECT_EQ(atom3.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1407 EXPECT_EQ(atom3.uid(), UID_0);
1408 EXPECT_EQ(atom3.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1409 EXPECT_EQ(atom3.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1410 EXPECT_EQ(atom3.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001411}
1412
Alec Mouri37384342020-01-02 17:23:37 -08001413TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1414 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_1, 1, 2000000);
1419 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1420
Huihong Luo30aa4372022-10-03 14:54:12 -07001421 std::vector<uint8_t> pulledBytes;
1422 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001423 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001424 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Alec Mouri37384342020-01-02 17:23:37 -08001425
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001426 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001427 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1428 ASSERT_EQ(atomList.atom_size(), 2);
1429 std::vector<std::string> actualLayerNames = {atomList.atom(0).layer_name(),
1430 atomList.atom(1).layer_name()};
1431 EXPECT_THAT(actualLayerNames,
1432 UnorderedElementsAre(genLayerName(LAYER_ID_0), genLayerName(LAYER_ID_1)));
Alec Mouri37384342020-01-02 17:23:37 -08001433}
1434
1435TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1436 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1437
Alec Mouri37384342020-01-02 17:23:37 -08001438 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1439 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1440 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1441 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1442
Tej Singh38a4b212020-03-13 19:04:51 -07001443 // Now make sure that TimeStats flushes global stats to set the callback.
Peiyong Lin65248e02020-04-18 21:15:07 -07001444 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouri37384342020-01-02 17:23:37 -08001445 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1446 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
Alec Mouri37384342020-01-02 17:23:37 -08001447
Huihong Luo30aa4372022-10-03 14:54:12 -07001448 std::vector<uint8_t> pulledBytes;
1449 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001450 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001451 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Tej Singhe2751772021-04-06 22:05:29 -07001452
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001453 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001454 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1455 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001456 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001457 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1, 2}, {2, 1})));
Alec Mouri37384342020-01-02 17:23:37 -08001458}
1459
1460TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
Tej Singhe2751772021-04-06 22:05:29 -07001461 mTimeStats = std::make_unique<impl::TimeStats>(std::nullopt, 1);
Alec Mouri37384342020-01-02 17:23:37 -08001462 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1463
Alec Mouri37384342020-01-02 17:23:37 -08001464 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1465 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1466 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1467 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1468
Huihong Luo30aa4372022-10-03 14:54:12 -07001469 std::vector<uint8_t> pulledBytes;
1470 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001471 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001472 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Alec Mouri37384342020-01-02 17:23:37 -08001473
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001474 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001475 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1476 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001477 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001478 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
Alec Mouri37384342020-01-02 17:23:37 -08001479}
1480
1481TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
Tej Singhe2751772021-04-06 22:05:29 -07001482 mTimeStats = std::make_unique<impl::TimeStats>(1, std::nullopt);
Alec Mouri37384342020-01-02 17:23:37 -08001483 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1484
Alec Mouri37384342020-01-02 17:23:37 -08001485 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1486 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1487 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1488 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1489 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1490
Huihong Luo30aa4372022-10-03 14:54:12 -07001491 std::vector<uint8_t> pulledBytes;
1492 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledBytes));
Tej Singhe2751772021-04-06 22:05:29 -07001493 std::string pulledData;
Huihong Luo30aa4372022-10-03 14:54:12 -07001494 pulledData.assign(pulledBytes.begin(), pulledBytes.end());
Alec Mouri37384342020-01-02 17:23:37 -08001495
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001496 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001497 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1498 ASSERT_EQ(atomList.atom_size(), 1);
1499 EXPECT_EQ(atomList.atom(0).layer_name(), genLayerName(LAYER_ID_1));
Alec Mouri37384342020-01-02 17:23:37 -08001500}
1501
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001502TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -08001503 if (g_noSlowTests) {
1504 GTEST_SKIP();
1505 }
1506
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001507 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1508
1509 for (size_t i = 0; i < 10000000; ++i) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001510 const int32_t layerId = genRandomInt32(-1, 10);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001511 const int32_t frameNumber = genRandomInt32(1, 10);
1512 switch (genRandomInt32(0, 100)) {
1513 case 0:
1514 ALOGV("removeTimeRecord");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001515 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001516 continue;
1517 case 1:
1518 ALOGV("onDestroy");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001519 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001520 continue;
1521 }
1522 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1523 const int32_t ts = genRandomInt32(1, 1000000000);
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001524 ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001525 setTimeStamp(type, layerId, frameNumber, ts, {}, kGameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001526 }
1527}
1528
Ady Abraham3403a3f2021-04-27 16:58:40 -07001529TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) {
1530 // this stat is not in the proto so verify by checking the string dump
1531 const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) {
1532 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
1533 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1534
1535 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001536 mTimeStats->incrementJankyFrames({fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0),
1537 kGameMode, JankType::None, 0, 0, 0});
Ady Abraham3403a3f2021-04-27 16:58:40 -07001538 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1539 std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps";
1540 EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps;
1541 };
1542
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001543 verifyRefreshRateBucket(91_Hz, 90);
1544 verifyRefreshRateBucket(89_Hz, 90);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001545
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001546 verifyRefreshRateBucket(61_Hz, 60);
1547 verifyRefreshRateBucket(59_Hz, 60);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001548
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001549 verifyRefreshRateBucket(31_Hz, 30);
1550 verifyRefreshRateBucket(29_Hz, 30);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001551}
1552
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001553} // namespace
1554} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001555
1556// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +01001557#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"