blob: 317cdf1592565ca07b206afd7e491165d2bcf3ae [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
67#define REFRESH_RATE_0 61
68#define RENDER_RATE_0 31
69#define REFRESH_RATE_BUCKET_0 60
70#define RENDER_RATE_BUCKET_0 30
71#define LAYER_ID_INVALID -1
72#define NUM_LAYERS 1
73#define NUM_LAYERS_INVALID "INVALID"
74
75const constexpr Fps kRefreshRate0 = Fps(static_cast<float>(REFRESH_RATE_0));
76const constexpr Fps kRenderRate0 = Fps(static_cast<float>(RENDER_RATE_0));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +000077static constexpr int32_t kGameMode = TimeStatsHelper::GameModeUnsupported;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080078
79enum InputCommand : int32_t {
80 ENABLE = 0,
81 DISABLE = 1,
82 CLEAR = 2,
83 DUMP_ALL = 3,
84 DUMP_MAXLAYERS_1 = 4,
85 DUMP_MAXLAYERS_INVALID = 5,
86 INPUT_COMMAND_BEGIN = ENABLE,
87 INPUT_COMMAND_END = DUMP_MAXLAYERS_INVALID,
88 INPUT_COMMAND_RANGE = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
89};
90
91enum TimeStamp : int32_t {
92 POST = 0,
93 ACQUIRE = 1,
94 ACQUIRE_FENCE = 2,
95 LATCH = 3,
96 DESIRED = 4,
97 PRESENT = 5,
98 PRESENT_FENCE = 6,
99 TIME_STAMP_BEGIN = POST,
100 TIME_STAMP_END = PRESENT,
101 TIME_STAMP_RANGE = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
102};
103
104static const TimeStamp NORMAL_SEQUENCE[] = {
105 TimeStamp::POST,
106 TimeStamp::ACQUIRE,
107 TimeStamp::LATCH,
108 TimeStamp::DESIRED,
109 TimeStamp::PRESENT,
110};
111
112static const TimeStamp NORMAL_SEQUENCE_2[] = {
113 TimeStamp::POST,
114 TimeStamp::ACQUIRE_FENCE,
115 TimeStamp::LATCH,
116 TimeStamp::DESIRED,
117 TimeStamp::PRESENT_FENCE,
118};
119
120static const TimeStamp UNORDERED_SEQUENCE[] = {
121 TimeStamp::ACQUIRE,
122 TimeStamp::LATCH,
123 TimeStamp::POST,
124 TimeStamp::DESIRED,
125 TimeStamp::PRESENT,
126};
127
128static const TimeStamp INCOMPLETE_SEQUENCE[] = {
129 TimeStamp::POST,
130};
131// clang-format on
132
133class TimeStatsTest : public testing::Test {
134public:
135 TimeStatsTest() {
136 const ::testing::TestInfo* const test_info =
137 ::testing::UnitTest::GetInstance()->current_test_info();
138 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
139 }
140
141 ~TimeStatsTest() {
142 const ::testing::TestInfo* const test_info =
143 ::testing::UnitTest::GetInstance()->current_test_info();
144 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
145 }
146
147 std::string inputCommand(InputCommand cmd, bool useProto);
148
Ady Abraham8b9e6122021-01-26 19:11:45 -0800149 void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000150 TimeStats::SetFrameRateVote frameRateVote, int32_t gameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800151
152 int32_t genRandomInt32(int32_t begin, int32_t end);
153
154 template <size_t N>
155 void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000156 nsecs_t ts, TimeStats::SetFrameRateVote frameRateVote = {},
157 int32_t gameMode = kGameMode) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800158 for (size_t i = 0; i < N; i++, ts += 1000000) {
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000159 setTimeStamp(sequence[i], id, frameNumber, ts, frameRateVote, gameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800160 }
161 }
162
163 std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000164 std::unique_ptr<TimeStats> mTimeStats =
Tej Singhe2751772021-04-06 22:05:29 -0700165 std::make_unique<impl::TimeStats>(std::nullopt, std::nullopt);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800166};
167
168std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
Yiwei Zhang5434a782018-12-05 18:06:32 -0800169 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800170 Vector<String16> args;
171
172 switch (cmd) {
173 case InputCommand::ENABLE:
174 args.push_back(String16("-enable"));
175 break;
176 case InputCommand::DISABLE:
177 args.push_back(String16("-disable"));
178 break;
179 case InputCommand::CLEAR:
180 args.push_back(String16("-clear"));
181 break;
182 case InputCommand::DUMP_ALL:
183 args.push_back(String16("-dump"));
184 break;
185 case InputCommand::DUMP_MAXLAYERS_1:
186 args.push_back(String16("-dump"));
187 args.push_back(String16("-maxlayers"));
188 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
189 break;
190 case InputCommand::DUMP_MAXLAYERS_INVALID:
191 args.push_back(String16("-dump"));
192 args.push_back(String16("-maxlayers"));
193 args.push_back(String16(NUM_LAYERS_INVALID));
194 break;
195 default:
196 ALOGD("Invalid control command");
197 }
198
Dominik Laskowskic2867142019-01-21 11:33:38 -0800199 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800200 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800201}
202
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800203static std::string genLayerName(int32_t layerId) {
Peiyong Lind8460c82020-07-28 16:04:22 -0700204 return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.example.fake#") + std::to_string(layerId);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800205}
206
Ady Abraham8b9e6122021-01-26 19:11:45 -0800207void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000208 TimeStats::SetFrameRateVote frameRateVote, int32_t gameMode) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800209 switch (type) {
210 case TimeStamp::POST:
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000211 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPostTime(id, frameNumber, genLayerName(id),
212 UID_0, ts, gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800213 break;
214 case TimeStamp::ACQUIRE:
215 ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
216 break;
217 case TimeStamp::ACQUIRE_FENCE:
218 ASSERT_NO_FATAL_FAILURE(
219 mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
220 break;
221 case TimeStamp::LATCH:
222 ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
223 break;
224 case TimeStamp::DESIRED:
225 ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
226 break;
227 case TimeStamp::PRESENT:
Ady Abraham8b9e6122021-01-26 19:11:45 -0800228 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts, kRefreshRate0,
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000229 kRenderRate0, frameRateVote,
230 gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800231 break;
232 case TimeStamp::PRESENT_FENCE:
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000233 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentFence(id, frameNumber,
234 std::make_shared<FenceTime>(ts),
235 kRefreshRate0, kRenderRate0,
236 frameRateVote, gameMode));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800237 break;
238 default:
239 ALOGD("Invalid timestamp type");
240 }
241}
242
243int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
244 std::uniform_int_distribution<int32_t> distr(begin, end);
245 return distr(mRandomEngine);
246}
247
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000248TEST_F(TimeStatsTest, disabledByDefault) {
249 ASSERT_FALSE(mTimeStats->isEnabled());
250}
251
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800252TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
253 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
254 ASSERT_TRUE(mTimeStats->isEnabled());
255
256 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
257 ASSERT_FALSE(mTimeStats->isEnabled());
258}
259
260TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
261 constexpr size_t TOTAL_FRAMES = 5;
262 constexpr size_t MISSED_FRAMES = 4;
263 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
264
265 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
266
267 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
268 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
269 }
270 for (size_t i = 0; i < MISSED_FRAMES; i++) {
271 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
272 }
273 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
274 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
275 }
276
277 SFTimeStatsGlobalProto globalProto;
278 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
279
280 ASSERT_TRUE(globalProto.has_total_frames());
281 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
282 ASSERT_TRUE(globalProto.has_missed_frames());
283 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
284 ASSERT_TRUE(globalProto.has_client_composition_frames());
285 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
286}
287
Alec Mouri91f6df32020-01-30 08:48:58 -0800288TEST_F(TimeStatsTest, canIncreaseLateAcquireFrames) {
289 // this stat is not in the proto so verify by checking the string dump
290 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
291
292 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
293
294 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
295 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
296 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
297 }
298 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
299
300 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
301 const std::string expectedResult = "lateAcquireFrames = " + std::to_string(LATE_ACQUIRE_FRAMES);
302 EXPECT_THAT(result, HasSubstr(expectedResult));
303}
304
305TEST_F(TimeStatsTest, canIncreaseBadDesiredPresent) {
306 // this stat is not in the proto so verify by checking the string dump
307 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 2;
308
309 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
310
311 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
312 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
313 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
314 }
315 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
316
317 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
318 const std::string expectedResult =
319 "badDesiredPresentFrames = " + std::to_string(BAD_DESIRED_PRESENT_FRAMES);
320 EXPECT_THAT(result, HasSubstr(expectedResult));
321}
322
Alec Mouri9a29e672020-09-14 12:39:14 -0700323TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
324 // this stat is not in the proto so verify by checking the string dump
325 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
326
327 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mouri363faf02021-01-29 16:34:55 -0800328 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000329 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000330 3});
331 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000332 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
333 3});
334 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
335 kGameMode, JankType::DisplayHAL, 1, 2, 3});
336 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
337 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
338 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
339 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
340 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
341 kGameMode, JankType::PredictionError, 1, 2, 3});
342 mTimeStats->incrementJankyFrames(
343 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
344 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
345 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
346 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700347
348 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
Alec Mouri7d436ec2021-01-27 20:40:50 -0800349 std::string expectedResult =
350 "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
351 EXPECT_THAT(result, HasSubstr(expectedResult));
352 expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
353 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000354 expectedResult = "totalTimelineFrames = " + std::to_string(8);
Alec Mouri9a29e672020-09-14 12:39:14 -0700355 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000356 expectedResult = "jankyFrames = " + std::to_string(7);
Alec Mouri9a29e672020-09-14 12:39:14 -0700357 EXPECT_THAT(result, HasSubstr(expectedResult));
358 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
359 EXPECT_THAT(result, HasSubstr(expectedResult));
360 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
361 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000362 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700363 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000364 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
365 EXPECT_THAT(result, HasSubstr(expectedResult));
366 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
367 EXPECT_THAT(result, HasSubstr(expectedResult));
368 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
369 EXPECT_THAT(result, HasSubstr(expectedResult));
370 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700371 EXPECT_THAT(result, HasSubstr(expectedResult));
372}
373
Ady Abraham8b9e6122021-01-26 19:11:45 -0800374TEST_F(TimeStatsTest, canCaptureSetFrameRateVote) {
375 // this stat is not in the proto so verify by checking the string dump
376 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
377
378 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
379
380 const auto frameRate60 = TimeStats::SetFrameRateVote{
381 .frameRate = 60.0f,
382 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
383 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
384 };
385 const auto frameRate90 = TimeStats::SetFrameRateVote{
386 .frameRate = 90.0f,
387 .frameRateCompatibility =
388 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
389 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
390 };
391 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
392 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
393 std::string expectedResult = "frameRate = 60.00";
394 EXPECT_THAT(result, HasSubstr(expectedResult));
395 expectedResult = "frameRateCompatibility = Default";
396 EXPECT_THAT(result, HasSubstr(expectedResult));
397 expectedResult = "seamlessness = ShouldBeSeamless";
398 EXPECT_THAT(result, HasSubstr(expectedResult));
399
400 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRate90);
401 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
402 expectedResult = "frameRate = 90.00";
403 EXPECT_THAT(result, HasSubstr(expectedResult));
404 expectedResult = "frameRateCompatibility = ExactOrMultiple";
405 EXPECT_THAT(result, HasSubstr(expectedResult));
406 expectedResult = "seamlessness = NotRequired";
407 EXPECT_THAT(result, HasSubstr(expectedResult));
408
409 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRate60);
410 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
411 expectedResult = "frameRate = 60.00";
412 EXPECT_THAT(result, HasSubstr(expectedResult));
413 expectedResult = "frameRateCompatibility = Default";
414 EXPECT_THAT(result, HasSubstr(expectedResult));
415 expectedResult = "seamlessness = ShouldBeSeamless";
416 EXPECT_THAT(result, HasSubstr(expectedResult));
417}
418
419TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) {
420 // this stat is not in the proto so verify by checking the string dump
421 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
422
423 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
424
425 const auto frameRate90 = TimeStats::SetFrameRateVote{
426 .frameRate = 90.0f,
427 .frameRateCompatibility =
428 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
429 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
430 };
431 const auto frameRateDefault = TimeStats::SetFrameRateVote{
432 .frameRate = 0.0f,
433 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
434 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
435 };
436 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate90);
437 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
438 std::string expectedResult = "frameRate = 90.00";
439 EXPECT_THAT(result, HasSubstr(expectedResult));
440 expectedResult = "frameRateCompatibility = ExactOrMultiple";
441 EXPECT_THAT(result, HasSubstr(expectedResult));
442 expectedResult = "seamlessness = NotRequired";
443 EXPECT_THAT(result, HasSubstr(expectedResult));
444
445 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRateDefault);
446 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
447 expectedResult = "frameRate = 90.00";
448 EXPECT_THAT(result, HasSubstr(expectedResult));
449 expectedResult = "frameRateCompatibility = ExactOrMultiple";
450 EXPECT_THAT(result, HasSubstr(expectedResult));
451 expectedResult = "seamlessness = NotRequired";
452 EXPECT_THAT(result, HasSubstr(expectedResult));
453
454 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRateDefault);
455 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
456 expectedResult = "frameRate = 90.00";
457 EXPECT_THAT(result, HasSubstr(expectedResult));
458 expectedResult = "frameRateCompatibility = ExactOrMultiple";
459 EXPECT_THAT(result, HasSubstr(expectedResult));
460 expectedResult = "seamlessness = NotRequired";
461 EXPECT_THAT(result, HasSubstr(expectedResult));
462}
463
Vishnu Nair9b079a22020-01-21 14:36:08 -0800464TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) {
465 // this stat is not in the proto so verify by checking the string dump
466 constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2;
467
468 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
469 for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) {
470 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
471 }
472
473 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
474 const std::string expectedResult =
475 "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES);
476 EXPECT_THAT(result, HasSubstr(expectedResult));
477}
478
Alec Mouri8de697e2020-03-19 10:52:01 -0700479TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
480 // this stat is not in the proto so verify by checking the string dump
481 constexpr size_t REFRESH_RATE_SWITCHES = 2;
482
483 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
484 for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
485 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
486 }
487
488 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
489 const std::string expectedResult =
490 "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
491 EXPECT_THAT(result, HasSubstr(expectedResult));
492}
493
Alec Mouri8f7a0102020-04-15 12:11:10 -0700494TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) {
495 // this stat is not in the proto so verify by checking the string dump
496 constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2;
497
498 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
499 for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) {
500 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
501 }
502
503 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
504 const std::string expectedResult =
505 "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES);
506 EXPECT_THAT(result, HasSubstr(expectedResult));
507}
508
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800509TEST_F(TimeStatsTest, canAverageFrameDuration) {
510 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Peiyong Lin65248e02020-04-18 21:15:07 -0700511 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000512 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
513 std::chrono::nanoseconds(6ms).count());
514 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
515 std::chrono::nanoseconds(16ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800516
517 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
518 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 10.000 ms"));
519}
520
521TEST_F(TimeStatsTest, canAverageRenderEngineTimings) {
522 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Adithya Srinivasanead17162021-02-18 02:17:37 +0000523 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800524 std::make_shared<FenceTime>(
525 std::chrono::duration_cast<
526 std::chrono::nanoseconds>(3ms)
527 .count()));
528
Adithya Srinivasanead17162021-02-18 02:17:37 +0000529 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
530 std::chrono::nanoseconds(8ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800531
Peiyong Lind8460c82020-07-28 16:04:22 -0700532 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700533 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000534 mTimeStats->setPresentFenceGlobal(
535 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800536
537 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
538 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 3.000 ms"));
539}
540
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800541TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
542 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
543
544 ASSERT_NO_FATAL_FAILURE(
545 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
546 ASSERT_NO_FATAL_FAILURE(
547 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
548
Peiyong Lin65248e02020-04-18 21:15:07 -0700549 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800550 ASSERT_NO_FATAL_FAILURE(
551 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
552 ASSERT_NO_FATAL_FAILURE(
553 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
554
Peiyong Lin65248e02020-04-18 21:15:07 -0700555 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800556 ASSERT_NO_FATAL_FAILURE(
557 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
558 ASSERT_NO_FATAL_FAILURE(
559 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
560
561 SFTimeStatsGlobalProto globalProto;
562 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
563
564 ASSERT_EQ(1, globalProto.present_to_present_size());
565 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
566 EXPECT_EQ(1, histogramProto.frame_count());
567 EXPECT_EQ(2, histogramProto.time_millis());
568}
569
Alec Mouri9519bf12019-11-15 16:54:44 -0800570TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
571 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
572
Peiyong Lin65248e02020-04-18 21:15:07 -0700573 mTimeStats->setPowerMode(PowerMode::OFF);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000574 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
575 std::chrono::nanoseconds(5ms).count());
Peiyong Lin65248e02020-04-18 21:15:07 -0700576 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000577 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
578 std::chrono::nanoseconds(6ms).count());
Alec Mouri9519bf12019-11-15 16:54:44 -0800579
580 SFTimeStatsGlobalProto globalProto;
581 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
582
583 ASSERT_EQ(1, globalProto.frame_duration_size());
584 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.frame_duration().Get(0);
585 EXPECT_EQ(1, histogramProto.frame_count());
586 EXPECT_EQ(3, histogramProto.time_millis());
587}
588
Alec Mourie4034bb2019-11-19 12:45:54 -0800589TEST_F(TimeStatsTest, canInsertGlobalRenderEngineTiming) {
590 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
591
Adithya Srinivasanead17162021-02-18 02:17:37 +0000592 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Alec Mourie4034bb2019-11-19 12:45:54 -0800593 std::make_shared<FenceTime>(
594 std::chrono::duration_cast<
595 std::chrono::nanoseconds>(3ms)
596 .count()));
597
Adithya Srinivasanead17162021-02-18 02:17:37 +0000598 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
599 std::chrono::nanoseconds(6ms).count());
Alec Mourie4034bb2019-11-19 12:45:54 -0800600
601 // First verify that flushing RenderEngine durations did not occur yet.
602 SFTimeStatsGlobalProto preFlushProto;
603 ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
604 ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
605
Peiyong Lind8460c82020-07-28 16:04:22 -0700606 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700607 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000608 mTimeStats->setPresentFenceGlobal(
609 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mourie4034bb2019-11-19 12:45:54 -0800610
611 // Now we can verify that RenderEngine durations were flushed now.
612 SFTimeStatsGlobalProto postFlushProto;
613 ASSERT_TRUE(postFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
614
615 ASSERT_EQ(1, postFlushProto.render_engine_timing_size());
616 const SFTimeStatsHistogramBucketProto& histogramProto =
617 postFlushProto.render_engine_timing().Get(0);
618 EXPECT_EQ(2, histogramProto.frame_count());
619 EXPECT_EQ(2, histogramProto.time_millis());
620}
621
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800622TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
623 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
624
625 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
626 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
627
628 SFTimeStatsGlobalProto globalProto;
629 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
630
631 ASSERT_EQ(1, globalProto.stats_size());
632 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
633 ASSERT_TRUE(layerProto.has_layer_name());
634 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
635 ASSERT_TRUE(layerProto.has_total_frames());
636 EXPECT_EQ(1, layerProto.total_frames());
637 ASSERT_EQ(6, layerProto.deltas_size());
638 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
639 ASSERT_EQ(1, deltaProto.histograms_size());
640 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
641 EXPECT_EQ(1, histogramProto.frame_count());
642 if ("post2acquire" == deltaProto.delta_name()) {
643 EXPECT_EQ(1, histogramProto.time_millis());
644 } else if ("post2present" == deltaProto.delta_name()) {
645 EXPECT_EQ(4, histogramProto.time_millis());
646 } else if ("acquire2present" == deltaProto.delta_name()) {
647 EXPECT_EQ(3, histogramProto.time_millis());
648 } else if ("latch2present" == deltaProto.delta_name()) {
649 EXPECT_EQ(2, histogramProto.time_millis());
650 } else if ("desired2present" == deltaProto.delta_name()) {
651 EXPECT_EQ(1, histogramProto.time_millis());
652 } else if ("present2present" == deltaProto.delta_name()) {
653 EXPECT_EQ(1, histogramProto.time_millis());
654 } else {
655 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
656 }
657 }
658}
659
660TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
661 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
662
663 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
664 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
665
666 SFTimeStatsGlobalProto globalProto;
667 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
668
669 ASSERT_EQ(0, globalProto.stats_size());
670}
671
672TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
673 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
674
675 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
676 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
677 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
678 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
679
680 SFTimeStatsGlobalProto globalProto;
681 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
682
683 EXPECT_EQ(2, globalProto.stats_size());
684}
685
686TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
687 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
688
689 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
690 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
691
692 SFTimeStatsGlobalProto globalProto;
693 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
694
695 ASSERT_EQ(1, globalProto.stats_size());
696 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
697 ASSERT_TRUE(layerProto.has_layer_name());
698 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
699 ASSERT_TRUE(layerProto.has_total_frames());
700 EXPECT_EQ(1, layerProto.total_frames());
701 ASSERT_EQ(6, layerProto.deltas_size());
702 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
703 ASSERT_EQ(1, deltaProto.histograms_size());
704 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
705 EXPECT_EQ(1, histogramProto.frame_count());
706 if ("post2acquire" == deltaProto.delta_name()) {
707 EXPECT_EQ(0, histogramProto.time_millis());
708 } else if ("post2present" == deltaProto.delta_name()) {
709 EXPECT_EQ(2, histogramProto.time_millis());
710 } else if ("acquire2present" == deltaProto.delta_name()) {
711 EXPECT_EQ(2, histogramProto.time_millis());
712 } else if ("latch2present" == deltaProto.delta_name()) {
713 EXPECT_EQ(2, histogramProto.time_millis());
714 } else if ("desired2present" == deltaProto.delta_name()) {
715 EXPECT_EQ(1, histogramProto.time_millis());
716 } else if ("present2present" == deltaProto.delta_name()) {
717 EXPECT_EQ(1, histogramProto.time_millis());
718 } else {
719 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
720 }
721 }
722}
723
Alec Mourifb571ea2019-01-24 18:42:10 -0800724TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
725 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
726
727 uint32_t fpsOne = 30;
728 uint32_t fpsTwo = 90;
729 uint64_t millisOne = 5000;
730 uint64_t millisTwo = 7000;
731
732 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
733 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
734
735 SFTimeStatsGlobalProto globalProto;
736 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
737
738 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
739 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
740 expectedConfigOne->set_fps(fpsOne);
741 expectedBucketOne.set_duration_millis(millisOne);
742
743 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
744 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
745 expectedConfigTwo->set_fps(fpsTwo);
746 expectedBucketTwo.set_duration_millis(millisTwo);
747
748 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
749
750 std::unordered_set<uint32_t> seen_fps;
751 for (const auto& bucket : globalProto.display_config_stats()) {
752 seen_fps.emplace(bucket.config().fps());
753 if (fpsOne == bucket.config().fps()) {
754 EXPECT_EQ(millisOne, bucket.duration_millis());
755 } else if (fpsTwo == bucket.config().fps()) {
756 EXPECT_EQ(millisTwo, bucket.duration_millis());
757 } else {
758 FAIL() << "Unknown fps: " << bucket.config().fps();
759 }
760 }
761 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
762}
763
764TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
765 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
766
767 uint32_t fps = 30;
768 uint64_t millisOne = 5000;
769 uint64_t millisTwo = 7000;
770
771 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
772 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
773
774 SFTimeStatsGlobalProto globalProto;
775 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
776 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
777 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
778 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
779}
780
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800781TEST_F(TimeStatsTest, canRemoveTimeRecord) {
782 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
783
784 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
785 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
786 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
787 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
788
789 SFTimeStatsGlobalProto globalProto;
790 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
791
792 ASSERT_EQ(1, globalProto.stats_size());
793 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
794 ASSERT_TRUE(layerProto.has_total_frames());
795 EXPECT_EQ(1, layerProto.total_frames());
796}
797
798TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
799 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
800
801 uint64_t frameNumber = 1;
802 nsecs_t ts = 1000000;
803 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800804 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800805 frameNumber++;
806 ts += 1000000;
807 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
808 }
809
810 SFTimeStatsGlobalProto globalProto;
811 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
812
813 ASSERT_EQ(1, globalProto.stats_size());
814 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
815 ASSERT_TRUE(layerProto.has_total_frames());
816 EXPECT_EQ(1, layerProto.total_frames());
817}
818
819TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
820 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
821
822 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
823 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
824 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
825 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
826
827 SFTimeStatsGlobalProto globalProto;
828 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
829
830 ASSERT_EQ(1, globalProto.stats_size());
831 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
832 ASSERT_TRUE(layerProto.has_total_frames());
833 EXPECT_EQ(1, layerProto.total_frames());
834}
835
836TEST_F(TimeStatsTest, canClearTimeStats) {
837 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
838
839 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
840 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
841 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
Peiyong Lin65248e02020-04-18 21:15:07 -0700842 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Alec Mouri31ac64a2020-01-09 09:26:22 -0800843
Adithya Srinivasanead17162021-02-18 02:17:37 +0000844 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
845 std::chrono::nanoseconds(6ms).count());
846 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
847 std::chrono::nanoseconds(6ms).count());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800848 ASSERT_NO_FATAL_FAILURE(
849 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
850 ASSERT_NO_FATAL_FAILURE(
851 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
852 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
853 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
854
855 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
856
857 SFTimeStatsGlobalProto globalProto;
858 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
859
860 EXPECT_EQ(0, globalProto.total_frames());
861 EXPECT_EQ(0, globalProto.missed_frames());
862 EXPECT_EQ(0, globalProto.client_composition_frames());
863 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri31ac64a2020-01-09 09:26:22 -0800864 EXPECT_EQ(0, globalProto.frame_duration_size());
865 EXPECT_EQ(0, globalProto.render_engine_timing_size());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800866 EXPECT_EQ(0, globalProto.stats_size());
867}
868
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800869TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) {
870 // These stats are not in the proto so verify by checking the string dump.
Vishnu Nair9b079a22020-01-21 14:36:08 -0800871 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
872 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
Alec Mouri8de697e2020-03-19 10:52:01 -0700873 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
Alec Mouri8f7a0102020-04-15 12:11:10 -0700874 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
Peiyong Lin65248e02020-04-18 21:15:07 -0700875 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000876 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
877 std::chrono::nanoseconds(5ms).count());
878 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
879 std::chrono::nanoseconds(6ms).count());
880 mTimeStats->setPresentFenceGlobal(
881 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mouri9a29e672020-09-14 12:39:14 -0700882
Alec Mouri363faf02021-01-29 16:34:55 -0800883 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000884 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2,
Adithya Srinivasanead17162021-02-18 02:17:37 +0000885 3});
886 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +0000887 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2,
888 3});
889 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
890 kGameMode, JankType::DisplayHAL, 1, 2, 3});
891 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
892 kGameMode, JankType::AppDeadlineMissed, 1, 2, 3});
893 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
894 kGameMode, JankType::SurfaceFlingerScheduling, 1, 2, 3});
895 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
896 kGameMode, JankType::PredictionError, 1, 2, 3});
897 mTimeStats->incrementJankyFrames(
898 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
899 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2, 3});
900 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
901 kGameMode, JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700902
Vishnu Nair9b079a22020-01-21 14:36:08 -0800903 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
904
905 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
906 EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
Alec Mouri8de697e2020-03-19 10:52:01 -0700907 EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
Alec Mouri8f7a0102020-04-15 12:11:10 -0700908 EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800909 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
910 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
Ady Abraham3403a3f2021-04-27 16:58:40 -0700911 std::string expectedResult = "totalTimelineFrames = ";
912 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
913 expectedResult = "jankyFrames = ";
914 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
915 expectedResult = "sfLongCpuJankyFrames = ";
916 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
917 expectedResult = "sfLongGpuJankyFrames = ";
918 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
919 expectedResult = "sfUnattributedJankyFrames = ";
920 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
921 expectedResult = "appUnattributedJankyFrames = ";
922 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
923 expectedResult = "sfSchedulingJankyFrames = ";
924 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
925 expectedResult = "sfPredictionErrorJankyFrames = ";
926 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
927 expectedResult = "appBufferStuffingJankyFrames = ";
928 EXPECT_THAT(result, Not(HasSubstr(expectedResult)));
Vishnu Nair9b079a22020-01-21 14:36:08 -0800929}
930
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800931TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
932 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
933
934 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
935 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
936 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
937 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
938 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
939
940 SFTimeStatsGlobalProto globalProto;
941 ASSERT_TRUE(
942 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
943
944 ASSERT_EQ(1, globalProto.stats_size());
945 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
946 ASSERT_TRUE(layerProto.has_layer_name());
947 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
948 ASSERT_TRUE(layerProto.has_total_frames());
949 EXPECT_EQ(2, layerProto.total_frames());
950}
951
952TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
953 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
954
955 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
956 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
957
958 SFTimeStatsGlobalProto globalProto;
959 ASSERT_TRUE(globalProto.ParseFromString(
960 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
961
962 ASSERT_EQ(0, globalProto.stats_size());
963}
964
Yiwei Zhangdd221b22020-06-12 11:06:19 -0700965TEST_F(TimeStatsTest, noInfInAverageFPS) {
966 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
967 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
968 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 1000000);
969
970 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
971 EXPECT_THAT(result, HasSubstr("averageFPS = 0.000"));
972}
973
Alec Mouri37384342020-01-02 17:23:37 -0800974namespace {
Tej Singhe2751772021-04-06 22:05:29 -0700975FrameTimingHistogram buildExpectedHistogram(const std::vector<int32_t>& times,
976 const std::vector<int32_t>& frameCounts) {
977 FrameTimingHistogram histogram;
Alec Mouri37384342020-01-02 17:23:37 -0800978 for (int i = 0; i < times.size(); i++) {
979 ALOGE("Writing time: %d", times[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700980 histogram.add_time_millis_buckets(times[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800981 ALOGE("Writing count: %d", frameCounts[i]);
Tej Singhe2751772021-04-06 22:05:29 -0700982 histogram.add_frame_counts((int64_t)frameCounts[i]);
Alec Mouri37384342020-01-02 17:23:37 -0800983 }
Tej Singhe2751772021-04-06 22:05:29 -0700984 return histogram;
Alec Mouri37384342020-01-02 17:23:37 -0800985}
Alec Mouri37384342020-01-02 17:23:37 -0800986} // namespace
987
Tej Singhe2751772021-04-06 22:05:29 -0700988MATCHER_P(HistogramEq, expected, "") {
989 *result_listener << "Histograms are not equal! \n";
Alec Mouri37384342020-01-02 17:23:37 -0800990
Tej Singhe2751772021-04-06 22:05:29 -0700991 if (arg.time_millis_buckets_size() != expected.time_millis_buckets_size()) {
992 *result_listener << "Time millis bucket are different sizes. Expected: "
993 << expected.time_millis_buckets_size() << ". Actual "
994 << arg.time_millis_buckets_size();
995 return false;
996 }
997 if (arg.frame_counts_size() != expected.frame_counts_size()) {
998 *result_listener << "Frame counts are different sizes. Expected: "
999 << expected.frame_counts_size() << ". Actual " << arg.frame_counts_size();
1000 return false;
1001 }
Alec Mouri37384342020-01-02 17:23:37 -08001002
Tej Singhe2751772021-04-06 22:05:29 -07001003 for (int i = 0; i < expected.time_millis_buckets_size(); i++) {
1004 if (arg.time_millis_buckets(i) != expected.time_millis_buckets(i)) {
1005 *result_listener << "time_millis_bucket[" << i
1006 << "] is different. Expected: " << expected.time_millis_buckets(i)
1007 << ". Actual: " << arg.time_millis_buckets(i);
1008 return false;
1009 }
1010 if (arg.frame_counts(i) != expected.frame_counts(i)) {
1011 *result_listener << "frame_counts[" << i
1012 << "] is different. Expected: " << expected.frame_counts(i)
1013 << ". Actual: " << arg.frame_counts(i);
1014 return false;
1015 }
1016 }
1017 return true;
Alec Mouri37384342020-01-02 17:23:37 -08001018}
1019
Alec Mouridfad9002020-02-12 17:49:09 -08001020TEST_F(TimeStatsTest, globalStatsCallback) {
1021 constexpr size_t TOTAL_FRAMES = 5;
1022 constexpr size_t MISSED_FRAMES = 4;
1023 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
1024 constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001025 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1026 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1027 constexpr nsecs_t APP_DEADLINE_DELTA = 3'000'000;
Alec Mouridfad9002020-02-12 17:49:09 -08001028
Alec Mouridfad9002020-02-12 17:49:09 -08001029 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1030
1031 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
1032 mTimeStats->incrementTotalFrames();
1033 }
1034 for (size_t i = 0; i < MISSED_FRAMES; i++) {
1035 mTimeStats->incrementMissedFrames();
1036 }
1037 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
1038 mTimeStats->incrementClientCompositionFrames();
1039 }
1040
Alec Mouri9a29e672020-09-14 12:39:14 -07001041 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1042
Alec Mouridfad9002020-02-12 17:49:09 -08001043 mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
Peiyong Lin65248e02020-04-18 21:15:07 -07001044 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouridfad9002020-02-12 17:49:09 -08001045 mTimeStats->recordFrameDuration(1000000, 3000000);
1046 mTimeStats->recordRenderEngineDuration(2000000, 4000000);
1047 mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
1048
1049 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1050 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1051
Alec Mouri363faf02021-01-29 16:34:55 -08001052 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001053 kGameMode, JankType::SurfaceFlingerCpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001054 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1055 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001056 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001057 kGameMode, JankType::SurfaceFlingerGpuDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001058 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1059 APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001060 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001061 kGameMode, JankType::DisplayHAL, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001062 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri363faf02021-01-29 16:34:55 -08001063 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001064 kGameMode, JankType::AppDeadlineMissed,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001065 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1066 APP_DEADLINE_DELTA});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001067 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001068 kGameMode, JankType::SurfaceFlingerScheduling,
1069 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1070 APP_DEADLINE_DELTA});
1071 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1072 kGameMode, JankType::PredictionError, DISPLAY_DEADLINE_DELTA,
1073 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1074 mTimeStats->incrementJankyFrames(
1075 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0), kGameMode,
1076 JankType::AppDeadlineMissed | JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
1077 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
1078 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1079 kGameMode, JankType::BufferStuffing, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001080 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001081 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001082 kGameMode, JankType::None, DISPLAY_DEADLINE_DELTA,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001083 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA});
Alec Mouri9a29e672020-09-14 12:39:14 -07001084
Tej Singhe2751772021-04-06 22:05:29 -07001085 std::string pulledData;
1086 EXPECT_TRUE(mTimeStats->onPullAtom(10062 /*SURFACEFLINGER_STATS_GLOBAL_INFO*/, &pulledData));
Alec Mouridfad9002020-02-12 17:49:09 -08001087
Tej Singhe2751772021-04-06 22:05:29 -07001088 android::surfaceflinger::SurfaceflingerStatsGlobalInfoWrapper atomList;
1089 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1090 ASSERT_EQ(atomList.atom_size(), 1);
1091 const android::surfaceflinger::SurfaceflingerStatsGlobalInfo& atom = atomList.atom(0);
Alec Mouridfad9002020-02-12 17:49:09 -08001092
Tej Singhe2751772021-04-06 22:05:29 -07001093 EXPECT_EQ(atom.total_frames(), TOTAL_FRAMES);
1094 EXPECT_EQ(atom.missed_frames(), MISSED_FRAMES);
1095 EXPECT_EQ(atom.client_composition_frames(), CLIENT_COMPOSITION_FRAMES);
1096 // Display on millis is not checked.
1097 EXPECT_EQ(atom.animation_millis(), 2);
1098 EXPECT_EQ(atom.event_connection_count(), DISPLAY_EVENT_CONNECTIONS);
1099 EXPECT_THAT(atom.frame_duration(), HistogramEq(buildExpectedHistogram({2}, {1})));
1100 EXPECT_THAT(atom.render_engine_timing(), HistogramEq(buildExpectedHistogram({1, 2}, {1, 1})));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001101 EXPECT_EQ(atom.total_timeline_frames(), 9);
Tej Singhe2751772021-04-06 22:05:29 -07001102 EXPECT_EQ(atom.total_janky_frames(), 7);
1103 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1104 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1105 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1106 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1107 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1108 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001109 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 2);
Tej Singhe2751772021-04-06 22:05:29 -07001110 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1111 EXPECT_THAT(atom.sf_deadline_misses(), HistogramEq(buildExpectedHistogram({1}, {7})));
1112 EXPECT_THAT(atom.sf_prediction_errors(), HistogramEq(buildExpectedHistogram({2}, {7})));
1113 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
Alec Mouridfad9002020-02-12 17:49:09 -08001114
1115 SFTimeStatsGlobalProto globalProto;
1116 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1117
1118 EXPECT_EQ(0, globalProto.total_frames());
1119 EXPECT_EQ(0, globalProto.missed_frames());
1120 EXPECT_EQ(0, globalProto.client_composition_frames());
1121 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001122
1123 // also check dump-only stats: expect that global stats are indeed dropped but there should
1124 // still be stats for the layer
1125 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1126 std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
1127 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001128 expectedResult = "totalTimelineFrames = " + std::to_string(9);
Alec Mouri56e63852021-03-09 18:17:25 -08001129 EXPECT_THAT(result, HasSubstr(expectedResult));
1130 expectedResult = "jankyFrames = " + std::to_string(0);
1131 EXPECT_THAT(result, HasSubstr(expectedResult));
1132 expectedResult = "jankyFrames = " + std::to_string(7);
1133 EXPECT_THAT(result, HasSubstr(expectedResult));
1134 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
1135 EXPECT_THAT(result, HasSubstr(expectedResult));
1136 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1137 EXPECT_THAT(result, HasSubstr(expectedResult));
1138 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
1139 EXPECT_THAT(result, HasSubstr(expectedResult));
1140 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1141 EXPECT_THAT(result, HasSubstr(expectedResult));
1142 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
1143 EXPECT_THAT(result, HasSubstr(expectedResult));
1144 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1145 EXPECT_THAT(result, HasSubstr(expectedResult));
1146 expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
1147 EXPECT_THAT(result, HasSubstr(expectedResult));
1148 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1149 EXPECT_THAT(result, HasSubstr(expectedResult));
1150 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
1151 EXPECT_THAT(result, HasSubstr(expectedResult));
1152 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1153 EXPECT_THAT(result, HasSubstr(expectedResult));
1154 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
1155 EXPECT_THAT(result, HasSubstr(expectedResult));
1156 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1157 EXPECT_THAT(result, HasSubstr(expectedResult));
1158 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
1159 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasan53e5c402021-04-16 17:34:30 +00001160 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(2);
Alec Mouri56e63852021-03-09 18:17:25 -08001161 EXPECT_THAT(result, HasSubstr(expectedResult));
Alec Mouridfad9002020-02-12 17:49:09 -08001162}
1163
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001164TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
1165 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1166 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
Ady Abraham3e8cc072021-05-11 16:29:54 -07001167 constexpr nsecs_t DISPLAY_DEADLINE_DELTA = 1'000'000;
1168 constexpr nsecs_t DISPLAY_PRESENT_JITTER = 2'000'000;
1169 constexpr nsecs_t APP_DEADLINE_DELTA_2MS = 2'000'000;
1170 constexpr nsecs_t APP_DEADLINE_DELTA_3MS = 3'000'000;
Alec Mouri37384342020-01-02 17:23:37 -08001171 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1172
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001173 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1174 TimeStatsHelper::GameModeStandard);
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001175 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1176 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1177 }
1178 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1179 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1180 }
Ady Abraham8b9e6122021-01-26 19:11:45 -08001181 const auto frameRate60 = TimeStats::SetFrameRateVote{
1182 .frameRate = 60.0f,
1183 .frameRateCompatibility =
1184 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1185 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1186 };
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001187 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60,
1188 TimeStatsHelper::GameModeStandard);
Alec Mouri37384342020-01-02 17:23:37 -08001189
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001190 mTimeStats->incrementJankyFrames(
1191 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1192 TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerCpuDeadlineMissed,
1193 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
1194 mTimeStats->incrementJankyFrames(
1195 {kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1196 TimeStatsHelper::GameModeStandard, JankType::SurfaceFlingerGpuDeadlineMissed,
1197 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001198 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001199 TimeStatsHelper::GameModeStandard, JankType::DisplayHAL,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001200 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1201 APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001202 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001203 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001204 JankType::AppDeadlineMissed, DISPLAY_DEADLINE_DELTA,
1205 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_3MS});
Alec Mouri363faf02021-01-29 16:34:55 -08001206 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001207 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001208 JankType::SurfaceFlingerScheduling, DISPLAY_DEADLINE_DELTA,
1209 DISPLAY_PRESENT_JITTER, APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001210 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001211 TimeStatsHelper::GameModeStandard, JankType::PredictionError,
1212 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1213 APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001214 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001215 TimeStatsHelper::GameModeStandard,
Ady Abraham3e8cc072021-05-11 16:29:54 -07001216 JankType::AppDeadlineMissed | JankType::BufferStuffing,
1217 DISPLAY_DEADLINE_DELTA, APP_DEADLINE_DELTA_2MS,
1218 APP_DEADLINE_DELTA_2MS});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001219 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001220 TimeStatsHelper::GameModeStandard, JankType::None,
1221 DISPLAY_DEADLINE_DELTA, DISPLAY_PRESENT_JITTER,
1222 APP_DEADLINE_DELTA_3MS});
Alec Mouri9a29e672020-09-14 12:39:14 -07001223
Tej Singhe2751772021-04-06 22:05:29 -07001224 std::string pulledData;
1225 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001226
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001227 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001228 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1229 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001230 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Alec Mouri9a29e672020-09-14 12:39:14 -07001231
Tej Singhe2751772021-04-06 22:05:29 -07001232 EXPECT_EQ(atom.layer_name(), genLayerName(LAYER_ID_0));
1233 EXPECT_EQ(atom.total_frames(), 1);
1234 EXPECT_EQ(atom.dropped_frames(), 0);
1235 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1236 EXPECT_THAT(atom.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1237 EXPECT_THAT(atom.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1238 EXPECT_THAT(atom.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1239 EXPECT_THAT(atom.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1240 EXPECT_THAT(atom.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1241 EXPECT_EQ(atom.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1242 EXPECT_EQ(atom.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1243 EXPECT_EQ(atom.uid(), UID_0);
1244 EXPECT_EQ(atom.total_timeline_frames(), 8);
1245 EXPECT_EQ(atom.total_janky_frames(), 7);
1246 EXPECT_EQ(atom.total_janky_frames_with_long_cpu(), 1);
1247 EXPECT_EQ(atom.total_janky_frames_with_long_gpu(), 1);
1248 EXPECT_EQ(atom.total_janky_frames_sf_unattributed(), 1);
1249 EXPECT_EQ(atom.total_janky_frames_app_unattributed(), 2);
1250 EXPECT_EQ(atom.total_janky_frames_sf_scheduling(), 1);
1251 EXPECT_EQ(atom.total_jank_frames_sf_prediction_error(), 1);
1252 EXPECT_EQ(atom.total_jank_frames_app_buffer_stuffing(), 1);
1253 EXPECT_EQ(atom.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1254 EXPECT_EQ(atom.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1255 EXPECT_THAT(atom.set_frame_rate_vote().frame_rate(), testing::FloatEq(frameRate60.frameRate));
1256 EXPECT_EQ((int)atom.set_frame_rate_vote().frame_rate_compatibility(),
1257 (int)frameRate60.frameRateCompatibility);
1258 EXPECT_EQ((int)atom.set_frame_rate_vote().seamlessness(), (int)frameRate60.seamlessness);
1259 EXPECT_THAT(atom.app_deadline_misses(), HistogramEq(buildExpectedHistogram({3, 2}, {4, 3})));
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001260 EXPECT_EQ(atom.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
Alec Mouri37384342020-01-02 17:23:37 -08001261
1262 SFTimeStatsGlobalProto globalProto;
1263 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1264
1265 EXPECT_EQ(0, globalProto.stats_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001266
1267 // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1268 // be global stats
1269 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1270 std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1271 EXPECT_THAT(result, HasSubstr(expectedResult));
1272 expectedResult = "jankyFrames = " + std::to_string(7);
1273 EXPECT_THAT(result, HasSubstr(expectedResult));
1274 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1275 EXPECT_THAT(result, HasSubstr(expectedResult));
1276 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1277 EXPECT_THAT(result, HasSubstr(expectedResult));
1278 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1279 EXPECT_THAT(result, HasSubstr(expectedResult));
1280 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1281 EXPECT_THAT(result, HasSubstr(expectedResult));
1282 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1283 EXPECT_THAT(result, HasSubstr(expectedResult));
1284 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1285 EXPECT_THAT(result, HasSubstr(expectedResult));
1286 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1287 EXPECT_THAT(result, HasSubstr(expectedResult));
1288
1289 std::string expectedMissing = "uid = " + std::to_string(UID_0);
1290 EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
Alec Mouri37384342020-01-02 17:23:37 -08001291}
1292
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001293TEST_F(TimeStatsTest, layerStatsCallback_multipleGameModes) {
1294 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1295 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
1296 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1297
1298 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000, {},
1299 TimeStatsHelper::GameModeStandard);
1300 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1301 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1302 }
1303 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1304 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1305 }
1306 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, {},
1307 TimeStatsHelper::GameModeStandard);
1308
1309 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, {},
1310 TimeStatsHelper::GameModePerformance);
1311
1312 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 4000000, {}, TimeStatsHelper::GameModeBattery);
1313 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 5, 4000000, {}, TimeStatsHelper::GameModeBattery);
1314
1315 std::string pulledData;
1316 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1317
1318 SurfaceflingerStatsLayerInfoWrapper atomList;
1319 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1320 // The first time record is never uploaded to stats.
1321 ASSERT_EQ(atomList.atom_size(), 3);
1322 // Layers are ordered based on the hash in LayerStatsKey. For this test, the order happens to
1323 // be: 0 - Battery 1 - Performance 2 - Standard
1324 const SurfaceflingerStatsLayerInfo& atom0 = atomList.atom(0);
1325
1326 EXPECT_EQ(atom0.layer_name(), genLayerName(LAYER_ID_0));
1327 EXPECT_EQ(atom0.total_frames(), 2);
1328 EXPECT_EQ(atom0.dropped_frames(), 0);
1329 EXPECT_THAT(atom0.present_to_present(), HistogramEq(buildExpectedHistogram({0, 1}, {1, 1})));
1330 EXPECT_THAT(atom0.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {2})));
1331 EXPECT_THAT(atom0.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {2})));
1332 EXPECT_THAT(atom0.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {2})));
1333 EXPECT_THAT(atom0.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
1334 EXPECT_THAT(atom0.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {2})));
1335 EXPECT_EQ(atom0.late_acquire_frames(), 0);
1336 EXPECT_EQ(atom0.bad_desired_present_frames(), 0);
1337 EXPECT_EQ(atom0.uid(), UID_0);
1338 EXPECT_EQ(atom0.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1339 EXPECT_EQ(atom0.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1340 EXPECT_EQ(atom0.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_BATTERY);
1341
1342 const SurfaceflingerStatsLayerInfo& atom1 = atomList.atom(1);
1343
1344 EXPECT_EQ(atom1.layer_name(), genLayerName(LAYER_ID_0));
1345 EXPECT_EQ(atom1.total_frames(), 1);
1346 EXPECT_EQ(atom1.dropped_frames(), 0);
1347 EXPECT_THAT(atom1.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1348 EXPECT_THAT(atom1.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1349 EXPECT_THAT(atom1.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1350 EXPECT_THAT(atom1.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1351 EXPECT_THAT(atom1.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1352 EXPECT_THAT(atom1.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1353 EXPECT_EQ(atom1.late_acquire_frames(), 0);
1354 EXPECT_EQ(atom1.bad_desired_present_frames(), 0);
1355 EXPECT_EQ(atom1.uid(), UID_0);
1356 EXPECT_EQ(atom1.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1357 EXPECT_EQ(atom1.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1358 EXPECT_EQ(atom1.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_PERFORMANCE);
1359
1360 const SurfaceflingerStatsLayerInfo& atom2 = atomList.atom(2);
1361
1362 EXPECT_EQ(atom2.layer_name(), genLayerName(LAYER_ID_0));
1363 EXPECT_EQ(atom2.total_frames(), 1);
1364 EXPECT_EQ(atom2.dropped_frames(), 0);
1365 EXPECT_THAT(atom2.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1366 EXPECT_THAT(atom2.post_to_present(), HistogramEq(buildExpectedHistogram({4}, {1})));
1367 EXPECT_THAT(atom2.acquire_to_present(), HistogramEq(buildExpectedHistogram({3}, {1})));
1368 EXPECT_THAT(atom2.latch_to_present(), HistogramEq(buildExpectedHistogram({2}, {1})));
1369 EXPECT_THAT(atom2.desired_to_present(), HistogramEq(buildExpectedHistogram({1}, {1})));
1370 EXPECT_THAT(atom2.post_to_acquire(), HistogramEq(buildExpectedHistogram({1}, {1})));
1371 EXPECT_EQ(atom2.late_acquire_frames(), LATE_ACQUIRE_FRAMES);
1372 EXPECT_EQ(atom2.bad_desired_present_frames(), BAD_DESIRED_PRESENT_FRAMES);
1373 EXPECT_EQ(atom2.uid(), UID_0);
1374 EXPECT_EQ(atom2.display_refresh_rate_bucket(), REFRESH_RATE_BUCKET_0);
1375 EXPECT_EQ(atom2.render_rate_bucket(), RENDER_RATE_BUCKET_0);
1376 EXPECT_EQ(atom2.game_mode(), SurfaceflingerStatsLayerInfo::GAME_MODE_STANDARD);
1377}
1378
Alec Mouri37384342020-01-02 17:23:37 -08001379TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1380 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1381
Alec Mouri37384342020-01-02 17:23:37 -08001382 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1383 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1384 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1385 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1386
Tej Singhe2751772021-04-06 22:05:29 -07001387 std::string pulledData;
1388 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001389
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001390 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001391 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1392 ASSERT_EQ(atomList.atom_size(), 2);
1393 std::vector<std::string> actualLayerNames = {atomList.atom(0).layer_name(),
1394 atomList.atom(1).layer_name()};
1395 EXPECT_THAT(actualLayerNames,
1396 UnorderedElementsAre(genLayerName(LAYER_ID_0), genLayerName(LAYER_ID_1)));
Alec Mouri37384342020-01-02 17:23:37 -08001397}
1398
1399TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1400 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1401
Alec Mouri37384342020-01-02 17:23:37 -08001402 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1403 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1404 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1405 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1406
Tej Singh38a4b212020-03-13 19:04:51 -07001407 // Now make sure that TimeStats flushes global stats to set the callback.
Peiyong Lin65248e02020-04-18 21:15:07 -07001408 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouri37384342020-01-02 17:23:37 -08001409 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1410 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
Alec Mouri37384342020-01-02 17:23:37 -08001411
Tej Singhe2751772021-04-06 22:05:29 -07001412 std::string pulledData;
1413 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
1414
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001415 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001416 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1417 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001418 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001419 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1, 2}, {2, 1})));
Alec Mouri37384342020-01-02 17:23:37 -08001420}
1421
1422TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
Tej Singhe2751772021-04-06 22:05:29 -07001423 mTimeStats = std::make_unique<impl::TimeStats>(std::nullopt, 1);
Alec Mouri37384342020-01-02 17:23:37 -08001424 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1425
Alec Mouri37384342020-01-02 17:23:37 -08001426 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1427 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1428 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1429 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1430
Tej Singhe2751772021-04-06 22:05:29 -07001431 std::string pulledData;
1432 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001433
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001434 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001435 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1436 ASSERT_EQ(atomList.atom_size(), 1);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001437 const SurfaceflingerStatsLayerInfo& atom = atomList.atom(0);
Tej Singhe2751772021-04-06 22:05:29 -07001438 EXPECT_THAT(atom.present_to_present(), HistogramEq(buildExpectedHistogram({1}, {2})));
Alec Mouri37384342020-01-02 17:23:37 -08001439}
1440
1441TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
Tej Singhe2751772021-04-06 22:05:29 -07001442 mTimeStats = std::make_unique<impl::TimeStats>(1, std::nullopt);
Alec Mouri37384342020-01-02 17:23:37 -08001443 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1444
Alec Mouri37384342020-01-02 17:23:37 -08001445 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1446 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1447 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1448 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1449 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1450
Tej Singhe2751772021-04-06 22:05:29 -07001451 std::string pulledData;
1452 EXPECT_TRUE(mTimeStats->onPullAtom(10063 /*SURFACEFLINGER_STATS_LAYER_INFO*/, &pulledData));
Alec Mouri37384342020-01-02 17:23:37 -08001453
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001454 SurfaceflingerStatsLayerInfoWrapper atomList;
Tej Singhe2751772021-04-06 22:05:29 -07001455 ASSERT_TRUE(atomList.ParseFromString(pulledData));
1456 ASSERT_EQ(atomList.atom_size(), 1);
1457 EXPECT_EQ(atomList.atom(0).layer_name(), genLayerName(LAYER_ID_1));
Alec Mouri37384342020-01-02 17:23:37 -08001458}
1459
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001460TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -08001461 if (g_noSlowTests) {
1462 GTEST_SKIP();
1463 }
1464
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001465 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1466
1467 for (size_t i = 0; i < 10000000; ++i) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001468 const int32_t layerId = genRandomInt32(-1, 10);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001469 const int32_t frameNumber = genRandomInt32(1, 10);
1470 switch (genRandomInt32(0, 100)) {
1471 case 0:
1472 ALOGV("removeTimeRecord");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001473 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001474 continue;
1475 case 1:
1476 ALOGV("onDestroy");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001477 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001478 continue;
1479 }
1480 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1481 const int32_t ts = genRandomInt32(1, 1000000000);
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001482 ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001483 setTimeStamp(type, layerId, frameNumber, ts, {}, kGameMode);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001484 }
1485}
1486
Ady Abraham3403a3f2021-04-27 16:58:40 -07001487TEST_F(TimeStatsTest, refreshRateIsClampedToNearestBucket) {
1488 // this stat is not in the proto so verify by checking the string dump
1489 const auto verifyRefreshRateBucket = [&](Fps fps, int32_t bucket) {
1490 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
1491 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1492
1493 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Adithya Srinivasan58069dc2021-06-04 20:37:02 +00001494 mTimeStats->incrementJankyFrames({fps, std::nullopt, UID_0, genLayerName(LAYER_ID_0),
1495 kGameMode, JankType::None, 0, 0, 0});
Ady Abraham3403a3f2021-04-27 16:58:40 -07001496 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1497 std::string expectedResult = "displayRefreshRate = " + std::to_string(bucket) + " fps";
1498 EXPECT_THAT(result, HasSubstr(expectedResult)) << "failed for " << fps;
1499 };
1500
1501 verifyRefreshRateBucket(Fps(91.f), 90);
1502 verifyRefreshRateBucket(Fps(89.f), 90);
1503
1504 verifyRefreshRateBucket(Fps(61.f), 60);
1505 verifyRefreshRateBucket(Fps(59.f), 60);
1506
1507 verifyRefreshRateBucket(Fps(31.f), 30);
1508 verifyRefreshRateBucket(Fps(29.f), 30);
1509}
1510
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001511} // namespace
1512} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001513
1514// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +01001515#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"