blob: 1487a962f9d41d37169e5678ae2b61103661b8d7 [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 Laskowski6eab42d2021-09-13 14:34:13 -070073const constexpr Fps kRefreshRate0 = 61_Hz;
74const constexpr Fps kRenderRate0 = 31_Hz;
Adithya Srinivasan58069dc2021-06-04 20:37:02 +000075static constexpr int32_t kGameMode = TimeStatsHelper::GameModeUnsupported;
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,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000148 TimeStats::SetFrameRateVote frameRateVote, int32_t 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 = {},
155 int32_t 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,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000206 TimeStats::SetFrameRateVote frameRateVote, int32_t 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
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001171 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1172 TimeStatsHelper::GameModeStandard);
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001173 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1174 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1175 }
1176 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1177 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1178 }
Ady Abraham8b9e6122021-01-26 19:11:45 -08001179 const auto frameRate60 = TimeStats::SetFrameRateVote{
1180 .frameRate = 60.0f,
1181 .frameRateCompatibility =
1182 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1183 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1184 };
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001185 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60,
1186 TimeStatsHelper::GameModeStandard);
Alec Mouri37384342020-01-02 17:23:37 -08001187
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001188 mTimeStats->incrementJankyFrames(
1189 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1190 TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerCpuDeadlineMissed,
1191 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
1192 mTimeStats->incrementJankyFrames(
1193 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1194 TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerGpuDeadlineMissed,
1195 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001196 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001197 TimeStatsHelper::GameModeStandard, JankType::DisplayHAL,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001198 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1199 APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001200 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001201 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001202 JankType::AppDeadlineMissed, DISPLAY_DEADLINE_DELTA,
1203 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001204 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001205 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001206 JankType::SurfaceFlingerScheduling, DISPLAY_DEADLINE_DELTA,
1207 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001208 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001209 TimeStatsHelper::GameModeStandard, JankType::PredictionError,
1210 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1211 APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001212 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001213 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001214 JankType::AppDeadlineMissed | JankType::BufferStuffing,
1215 DISPLAY_DEADLINE_DELTA, APP_DEADLINE_DELTA_2MS,
1216 APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001217 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001218 TimeStatsHelper::GameModeStandard, JankType::None,
1219 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1220 APP_DEADLINE_DELTA_3MS});
Alec Mouri9a29e672020-09-14 12:39:14 -07001221
Tej Singhe2751772021-04-06 22:05:29 -07001222 std::string pulledData;
1223 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001224
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001225 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001226 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1227 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001228 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Alec Mouri9a29e672020-09-14 12:39:14 -07001229
Tej Singhe2751772021-04-06 22:05:29 -07001230 EXPECT_EQ(atom.layer_name(), genLayerName(LAYER_ID_0));
1231 EXPECT_EQ(atom.total_frames(), 1);
1232 EXPECT_EQ(atom.dropped_frames(), 0);
1233 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1234 EXPECT_THAT(atom.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1235 EXPECT_THAT(atom.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1236 EXPECT_THAT(atom.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1237 EXPECT_THAT(atom.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1238 EXPECT_THAT(atom.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1239 EXPECT_EQ(atom.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1240 EXPECT_EQ(atom.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1241 EXPECT_EQ(atom.uid(), UID_0);
1242 EXPECT_EQ(atom.total_timeline_frames(), 8);
1243 EXPECT_EQ(atom.total_janky_frames(), 7);
1244 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1245 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1246 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1247 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1248 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1249 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1250 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 1);
1251 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1252 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1253 EXPECT_THAT(atom.set_frame_rate_vote().frame_rate(), testing::FloatEq(frameRate60.frameRate));
1254 EXPECT_EQ((int)atom.set_frame_rate_vote().frame_rate_compatibility(),
1255 (int)frameRate60.frameRateCompatibility);
1256 EXPECT_EQ((int)atom.set_frame_rate_vote().seamlessness(), (int)frameRate60.seamlessness);
1257 EXPECT_THAT(atom.app_deadline_misses(), HistogramEq(buildExpectedHistogram({3, 2}, {4, 3})));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001258 EXPECT_EQ(atom.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
Alec Mouri37384342020-01-02 17:23:37 -08001259
1260 SFTimeStatsGlobalProto globalProto;
1261 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1262
1263 EXPECT_EQ(0, globalProto.stats_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001264
1265 // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1266 // be global stats
1267 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1268 std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1269 EXPECT_THAT(result, HasSubstr(expectedResult));
1270 expectedResult = "jankyFrames = " + std::to_string(7);
1271 EXPECT_THAT(result, HasSubstr(expectedResult));
1272 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1273 EXPECT_THAT(result, HasSubstr(expectedResult));
1274 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1275 EXPECT_THAT(result, HasSubstr(expectedResult));
1276 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1277 EXPECT_THAT(result, HasSubstr(expectedResult));
1278 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1279 EXPECT_THAT(result, HasSubstr(expectedResult));
1280 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1281 EXPECT_THAT(result, HasSubstr(expectedResult));
1282 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1283 EXPECT_THAT(result, HasSubstr(expectedResult));
1284 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1285 EXPECT_THAT(result, HasSubstr(expectedResult));
1286
1287 std::string expectedMissing = "uid = " + std::to_string(UID_0);
1288 EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
Alec Mouri37384342020-01-02 17:23:37 -08001289}
1290
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001291TEST_F(TimeStatsTest, layerStatsCallback_multipleGameModes) {
1292 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1293 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1294 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1295
1296 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1297 TimeStatsHelper::GameModeStandard);
1298 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1299 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1300 }
1301 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1302 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1303 }
1304 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, {},
1305 TimeStatsHelper::GameModeStandard);
1306
1307 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, {},
1308 TimeStatsHelper::GameModePerformance);
1309
1310 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 4000000, {}, TimeStatsHelper::GameModeBattery);
1311 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 5, 4000000, {}, TimeStatsHelper::GameModeBattery);
1312
1313 std::string pulledData;
1314 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1315
1316 SurfaceflingerStatsLayerInfoWrapper atomList;
1317 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1318 // The first time record is never uploaded to stats.
1319 ASSERT_EQ(atomList.atom_size(), 3);
1320 // Layers are ordered based on the hash in LayerStatsKey. For this test, the order happens to
1321 // be: 0 - Battery 1 - Performance 2 - Standard
1322 const SurfaceflingerStatsLayerInfo& atom0 = atomList.atom(0);
1323
1324 EXPECT_EQ(atom0.layer_name(), genLayerName(LAYER_ID_0));
1325 EXPECT_EQ(atom0.total_frames(), 2);
1326 EXPECT_EQ(atom0.dropped_frames(), 0);
1327 EXPECT_THAT(atom0.present_to_present(), HistogramEq(buildExpectedHistogram({0, 1}, {1, 1})));
1328 EXPECT_THAT(atom0.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {2})));
1329 EXPECT_THAT(atom0.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {2})));
1330 EXPECT_THAT(atom0.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {2})));
1331 EXPECT_THAT(atom0.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1332 EXPECT_THAT(atom0.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {2})));
1333 EXPECT_EQ(atom0.late_acquire_frames(), 0);
1334 EXPECT_EQ(atom0.bad_desired_present_frames(), 0);
1335 EXPECT_EQ(atom0.uid(), UID_0);
1336 EXPECT_EQ(atom0.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1337 EXPECT_EQ(atom0.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1338 EXPECT_EQ(atom0.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_BATTERY);
1339
1340 const SurfaceflingerStatsLayerInfo& atom1 = atomList.atom(1);
1341
1342 EXPECT_EQ(atom1.layer_name(), genLayerName(LAYER_ID_0));
1343 EXPECT_EQ(atom1.total_frames(), 1);
1344 EXPECT_EQ(atom1.dropped_frames(), 0);
1345 EXPECT_THAT(atom1.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1346 EXPECT_THAT(atom1.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1347 EXPECT_THAT(atom1.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1348 EXPECT_THAT(atom1.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1349 EXPECT_THAT(atom1.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1350 EXPECT_THAT(atom1.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1351 EXPECT_EQ(atom1.late_acquire_frames(), 0);
1352 EXPECT_EQ(atom1.bad_desired_present_frames(), 0);
1353 EXPECT_EQ(atom1.uid(), UID_0);
1354 EXPECT_EQ(atom1.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1355 EXPECT_EQ(atom1.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1356 EXPECT_EQ(atom1.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_PERFORMANCE);
1357
1358 const SurfaceflingerStatsLayerInfo& atom2 = atomList.atom(2);
1359
1360 EXPECT_EQ(atom2.layer_name(), genLayerName(LAYER_ID_0));
1361 EXPECT_EQ(atom2.total_frames(), 1);
1362 EXPECT_EQ(atom2.dropped_frames(), 0);
1363 EXPECT_THAT(atom2.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1364 EXPECT_THAT(atom2.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1365 EXPECT_THAT(atom2.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1366 EXPECT_THAT(atom2.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1367 EXPECT_THAT(atom2.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1368 EXPECT_THAT(atom2.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1369 EXPECT_EQ(atom2.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1370 EXPECT_EQ(atom2.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1371 EXPECT_EQ(atom2.uid(), UID_0);
1372 EXPECT_EQ(atom2.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1373 EXPECT_EQ(atom2.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1374 EXPECT_EQ(atom2.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
1375}
1376
Alec Mouri37384342020-01-02 17:23:37 -08001377TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1378 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1379
Alec Mouri37384342020-01-02 17:23:37 -08001380 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1381 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1382 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1383 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1384
Tej Singhe2751772021-04-06 22:05:29 -07001385 std::string pulledData;
1386 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001387
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001388 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001389 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1390 ASSERT_EQ(atomList.atom_size(), 2);
1391 std::vector<std::string> actualLayerNames = {atomList.atom(0).layer_name(),
1392 atomList.atom(1).layer_name()};
1393 EXPECT_THAT(actualLayerNames,
1394 UnorderedElementsAre(genLayerName(LAYER_ID_0), genLayerName(LAYER_ID_1)));
Alec Mouri37384342020-01-02 17:23:37 -08001395}
1396
1397TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1398 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1399
Alec Mouri37384342020-01-02 17:23:37 -08001400 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1401 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1402 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1403 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1404
Tej Singh38a4b212020-03-13 19:04:51 -07001405 // Now make sure that TimeStats flushes global stats to set the callback.
Peiyong Lin65248e02020-04-18 21:15:07 -07001406 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouri37384342020-01-02 17:23:37 -08001407 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1408 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
Alec Mouri37384342020-01-02 17:23:37 -08001409
Tej Singhe2751772021-04-06 22:05:29 -07001410 std::string pulledData;
1411 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1412
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001413 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001414 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1415 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001416 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001417 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1, 2}, {2, 1})));
Alec Mouri37384342020-01-02 17:23:37 -08001418}
1419
1420TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
Tej Singhe2751772021-04-06 22:05:29 -07001421 mTimeStats = std::make_unique<impl::TimeStats>(std::nullopt, 1);
Alec Mouri37384342020-01-02 17:23:37 -08001422 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1423
Alec Mouri37384342020-01-02 17:23:37 -08001424 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1425 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1426 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1427 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1428
Tej Singhe2751772021-04-06 22:05:29 -07001429 std::string pulledData;
1430 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001431
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001432 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001433 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1434 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001435 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001436 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
Alec Mouri37384342020-01-02 17:23:37 -08001437}
1438
1439TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
Tej Singhe2751772021-04-06 22:05:29 -07001440 mTimeStats = std::make_unique<impl::TimeStats>(1, std::nullopt);
Alec Mouri37384342020-01-02 17:23:37 -08001441 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1442
Alec Mouri37384342020-01-02 17:23:37 -08001443 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1444 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1445 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1446 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1447 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1448
Tej Singhe2751772021-04-06 22:05:29 -07001449 std::string pulledData;
1450 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001451
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001452 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001453 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1454 ASSERT_EQ(atomList.atom_size(), 1);
1455 EXPECT_EQ(atomList.atom(0).layer_name(), genLayerName(LAYER_ID_1));
Alec Mouri37384342020-01-02 17:23:37 -08001456}
1457
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001458TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -08001459 if (g_noSlowTests) {
1460 GTEST_SKIP();
1461 }
1462
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001463 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1464
1465 for (size_t i = 0; i < 10000000; ++i) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001466 const int32_t layerId = genRandomInt32(-1, 10);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001467 const int32_t frameNumber = genRandomInt32(1, 10);
1468 switch (genRandomInt32(0, 100)) {
1469 case 0:
1470 ALOGV("removeTimeRecord");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001471 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001472 continue;
1473 case 1:
1474 ALOGV("onDestroy");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001475 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001476 continue;
1477 }
1478 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1479 const int32_t ts = genRandomInt32(1, 1000000000);
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001480 ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001481 setTimeStamp(type, layerId, frameNumber, ts, {}, kGameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001482 }
1483}
1484
Ady Abraham3403a3f2021-04-27 16:58:40 -07001485TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) {
1486 // this stat is not in the proto so verify by checking the string dump
1487 const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) {
1488 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
1489 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1490
1491 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001492 mTimeStats->incrementJankyFrames({fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0),
1493 kGameMode, JankType::None, 0, 0, 0});
Ady Abraham3403a3f2021-04-27 16:58:40 -07001494 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1495 std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps";
1496 EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps;
1497 };
1498
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001499 verifyRefreshRateBucket(91_Hz, 90);
1500 verifyRefreshRateBucket(89_Hz, 90);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001501
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001502 verifyRefreshRateBucket(61_Hz, 60);
1503 verifyRefreshRateBucket(59_Hz, 60);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001504
Dominik Laskowski6eab42d2021-09-13 14:34:13 -07001505 verifyRefreshRateBucket(31_Hz, 30);
1506 verifyRefreshRateBucket(29_Hz, 30);
Ady Abraham3403a3f2021-04-27 16:58:40 -07001507}
1508
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001509} // namespace
1510} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001511
1512// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +01001513#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"