blob: c1f0c4ef0308effbc9c96f07d459a884c6a0f525 [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 Mouri37384342020-01-02 17:23:37 -080026#include <android/util/ProtoOutputStream.h>
Alec Mourifb571ea2019-01-24 18:42:10 -080027#include <gmock/gmock.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080028#include <gtest/gtest.h>
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080029#include <log/log.h>
30#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;
57
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080058// clang-format off
Alec Mouri7d436ec2021-01-27 20:40:50 -080059#define FMT_PROTO true
60#define FMT_STRING false
61#define LAYER_ID_0 0
62#define LAYER_ID_1 1
63#define UID_0 123
64#define REFRESH_RATE_0 61
65#define RENDER_RATE_0 31
66#define REFRESH_RATE_BUCKET_0 60
67#define RENDER_RATE_BUCKET_0 30
68#define LAYER_ID_INVALID -1
69#define NUM_LAYERS 1
70#define NUM_LAYERS_INVALID "INVALID"
71
72const constexpr Fps kRefreshRate0 = Fps(static_cast<float>(REFRESH_RATE_0));
73const constexpr Fps kRenderRate0 = Fps(static_cast<float>(RENDER_RATE_0));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -080074
75enum InputCommand : int32_t {
76 ENABLE = 0,
77 DISABLE = 1,
78 CLEAR = 2,
79 DUMP_ALL = 3,
80 DUMP_MAXLAYERS_1 = 4,
81 DUMP_MAXLAYERS_INVALID = 5,
82 INPUT_COMMAND_BEGIN = ENABLE,
83 INPUT_COMMAND_END = DUMP_MAXLAYERS_INVALID,
84 INPUT_COMMAND_RANGE = INPUT_COMMAND_END - INPUT_COMMAND_BEGIN + 1,
85};
86
87enum TimeStamp : int32_t {
88 POST = 0,
89 ACQUIRE = 1,
90 ACQUIRE_FENCE = 2,
91 LATCH = 3,
92 DESIRED = 4,
93 PRESENT = 5,
94 PRESENT_FENCE = 6,
95 TIME_STAMP_BEGIN = POST,
96 TIME_STAMP_END = PRESENT,
97 TIME_STAMP_RANGE = TIME_STAMP_END - TIME_STAMP_BEGIN + 1,
98};
99
100static const TimeStamp NORMAL_SEQUENCE[] = {
101 TimeStamp::POST,
102 TimeStamp::ACQUIRE,
103 TimeStamp::LATCH,
104 TimeStamp::DESIRED,
105 TimeStamp::PRESENT,
106};
107
108static const TimeStamp NORMAL_SEQUENCE_2[] = {
109 TimeStamp::POST,
110 TimeStamp::ACQUIRE_FENCE,
111 TimeStamp::LATCH,
112 TimeStamp::DESIRED,
113 TimeStamp::PRESENT_FENCE,
114};
115
116static const TimeStamp UNORDERED_SEQUENCE[] = {
117 TimeStamp::ACQUIRE,
118 TimeStamp::LATCH,
119 TimeStamp::POST,
120 TimeStamp::DESIRED,
121 TimeStamp::PRESENT,
122};
123
124static const TimeStamp INCOMPLETE_SEQUENCE[] = {
125 TimeStamp::POST,
126};
127// clang-format on
128
129class TimeStatsTest : public testing::Test {
130public:
131 TimeStatsTest() {
132 const ::testing::TestInfo* const test_info =
133 ::testing::UnitTest::GetInstance()->current_test_info();
134 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
135 }
136
137 ~TimeStatsTest() {
138 const ::testing::TestInfo* const test_info =
139 ::testing::UnitTest::GetInstance()->current_test_info();
140 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
141 }
142
143 std::string inputCommand(InputCommand cmd, bool useProto);
144
Ady Abraham8b9e6122021-01-26 19:11:45 -0800145 void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
146 TimeStats::SetFrameRateVote frameRateVote);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800147
148 int32_t genRandomInt32(int32_t begin, int32_t end);
149
150 template <size_t N>
151 void insertTimeRecord(const TimeStamp (&sequence)[N], int32_t id, uint64_t frameNumber,
Ady Abraham8b9e6122021-01-26 19:11:45 -0800152 nsecs_t ts, TimeStats::SetFrameRateVote frameRateVote = {}) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800153 for (size_t i = 0; i < N; i++, ts += 1000000) {
Ady Abraham8b9e6122021-01-26 19:11:45 -0800154 setTimeStamp(sequence[i], id, frameNumber, ts, frameRateVote);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800155 }
156 }
157
158 std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000159
160 class FakeStatsEventDelegate : public impl::TimeStats::StatsEventDelegate {
161 public:
162 FakeStatsEventDelegate() = default;
163 ~FakeStatsEventDelegate() override = default;
164
Tej Singh2a457b62020-01-31 16:16:10 -0800165 struct AStatsEvent* addStatsEventToPullData(AStatsEventList*) override {
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000166 return mEvent;
167 }
Tej Singh38a4b212020-03-13 19:04:51 -0700168 void setStatsPullAtomCallback(int32_t atom_tag, AStatsManager_PullAtomMetadata*,
169 AStatsManager_PullAtomCallback callback,
170 void* cookie) override {
Alec Mouri37384342020-01-02 17:23:37 -0800171 mAtomTags.push_back(atom_tag);
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000172 mCallback = callback;
173 mCookie = cookie;
174 }
175
Tej Singh2a457b62020-01-31 16:16:10 -0800176 AStatsManager_PullAtomCallbackReturn makePullAtomCallback(int32_t atom_tag, void* cookie) {
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000177 return (*mCallback)(atom_tag, nullptr, cookie);
178 }
179
Tej Singh38a4b212020-03-13 19:04:51 -0700180 MOCK_METHOD1(clearStatsPullAtomCallback, void(int32_t));
Tej Singh2a457b62020-01-31 16:16:10 -0800181 MOCK_METHOD2(statsEventSetAtomId, void(AStatsEvent*, uint32_t));
Alec Mouri717bcb62020-02-10 17:07:19 -0800182 MOCK_METHOD2(statsEventWriteInt32, void(AStatsEvent*, int32_t));
Tej Singh2a457b62020-01-31 16:16:10 -0800183 MOCK_METHOD2(statsEventWriteInt64, void(AStatsEvent*, int64_t));
184 MOCK_METHOD2(statsEventWriteString8, void(AStatsEvent*, const char*));
185 MOCK_METHOD3(statsEventWriteByteArray, void(AStatsEvent*, const uint8_t*, size_t));
186 MOCK_METHOD1(statsEventBuild, void(AStatsEvent*));
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000187
Tej Singh2a457b62020-01-31 16:16:10 -0800188 AStatsEvent* mEvent = AStatsEvent_obtain();
Alec Mouri37384342020-01-02 17:23:37 -0800189 std::vector<int32_t> mAtomTags;
Tej Singh2a457b62020-01-31 16:16:10 -0800190 AStatsManager_PullAtomCallback mCallback = nullptr;
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000191 void* mCookie = nullptr;
192 };
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000193 FakeStatsEventDelegate* mDelegate = new FakeStatsEventDelegate;
194 std::unique_ptr<TimeStats> mTimeStats =
Alec Mouri37384342020-01-02 17:23:37 -0800195 std::make_unique<impl::TimeStats>(std::unique_ptr<FakeStatsEventDelegate>(mDelegate),
196 std::nullopt, std::nullopt);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800197};
198
199std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
Yiwei Zhang5434a782018-12-05 18:06:32 -0800200 std::string result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800201 Vector<String16> args;
202
203 switch (cmd) {
204 case InputCommand::ENABLE:
205 args.push_back(String16("-enable"));
206 break;
207 case InputCommand::DISABLE:
208 args.push_back(String16("-disable"));
209 break;
210 case InputCommand::CLEAR:
211 args.push_back(String16("-clear"));
212 break;
213 case InputCommand::DUMP_ALL:
214 args.push_back(String16("-dump"));
215 break;
216 case InputCommand::DUMP_MAXLAYERS_1:
217 args.push_back(String16("-dump"));
218 args.push_back(String16("-maxlayers"));
219 args.push_back(String16(std::to_string(NUM_LAYERS).c_str()));
220 break;
221 case InputCommand::DUMP_MAXLAYERS_INVALID:
222 args.push_back(String16("-dump"));
223 args.push_back(String16("-maxlayers"));
224 args.push_back(String16(NUM_LAYERS_INVALID));
225 break;
226 default:
227 ALOGD("Invalid control command");
228 }
229
Dominik Laskowskic2867142019-01-21 11:33:38 -0800230 EXPECT_NO_FATAL_FAILURE(mTimeStats->parseArgs(useProto, args, result));
Yiwei Zhang5434a782018-12-05 18:06:32 -0800231 return result;
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800232}
233
Yiwei Zhang1a88c402019-11-18 10:43:58 -0800234static std::string genLayerName(int32_t layerId) {
Peiyong Lind8460c82020-07-28 16:04:22 -0700235 return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.example.fake#") + std::to_string(layerId);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800236}
237
Ady Abraham8b9e6122021-01-26 19:11:45 -0800238void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts,
239 TimeStats::SetFrameRateVote frameRateVote) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800240 switch (type) {
241 case TimeStamp::POST:
Alec Mouri9a29e672020-09-14 12:39:14 -0700242 ASSERT_NO_FATAL_FAILURE(
243 mTimeStats->setPostTime(id, frameNumber, genLayerName(id), UID_0, ts));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800244 break;
245 case TimeStamp::ACQUIRE:
246 ASSERT_NO_FATAL_FAILURE(mTimeStats->setAcquireTime(id, frameNumber, ts));
247 break;
248 case TimeStamp::ACQUIRE_FENCE:
249 ASSERT_NO_FATAL_FAILURE(
250 mTimeStats->setAcquireFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
251 break;
252 case TimeStamp::LATCH:
253 ASSERT_NO_FATAL_FAILURE(mTimeStats->setLatchTime(id, frameNumber, ts));
254 break;
255 case TimeStamp::DESIRED:
256 ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
257 break;
258 case TimeStamp::PRESENT:
Ady Abraham8b9e6122021-01-26 19:11:45 -0800259 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts, kRefreshRate0,
260 kRenderRate0, frameRateVote));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800261 break;
262 case TimeStamp::PRESENT_FENCE:
Ady Abraham8b9e6122021-01-26 19:11:45 -0800263 ASSERT_NO_FATAL_FAILURE(
264 mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts),
265 kRefreshRate0, kRenderRate0, frameRateVote));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800266 break;
267 default:
268 ALOGD("Invalid timestamp type");
269 }
270}
271
272int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) {
273 std::uniform_int_distribution<int32_t> distr(begin, end);
274 return distr(mRandomEngine);
275}
276
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000277TEST_F(TimeStatsTest, disabledByDefault) {
278 ASSERT_FALSE(mTimeStats->isEnabled());
279}
280
Tej Singh38a4b212020-03-13 19:04:51 -0700281TEST_F(TimeStatsTest, setsCallbacksAfterBoot) {
Alec Mouri8e2f31b2020-01-16 22:04:35 +0000282 mTimeStats->onBootFinished();
Alec Mouri3ecd5cd2020-01-29 12:53:07 -0800283 EXPECT_THAT(mDelegate->mAtomTags,
284 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
285 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
286}
287
Tej Singh38a4b212020-03-13 19:04:51 -0700288TEST_F(TimeStatsTest, clearsCallbacksOnDestruction) {
Alec Mouri3ecd5cd2020-01-29 12:53:07 -0800289 EXPECT_CALL(*mDelegate,
Tej Singh38a4b212020-03-13 19:04:51 -0700290 clearStatsPullAtomCallback(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO));
Alec Mouri3ecd5cd2020-01-29 12:53:07 -0800291 EXPECT_CALL(*mDelegate,
Tej Singh38a4b212020-03-13 19:04:51 -0700292 clearStatsPullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO));
Alec Mouri3ecd5cd2020-01-29 12:53:07 -0800293 mTimeStats.reset();
Alec Mourib3885ad2019-09-06 17:08:55 -0700294}
295
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800296TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
297 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
298 ASSERT_TRUE(mTimeStats->isEnabled());
299
300 EXPECT_TRUE(inputCommand(InputCommand::DISABLE, FMT_STRING).empty());
301 ASSERT_FALSE(mTimeStats->isEnabled());
302}
303
304TEST_F(TimeStatsTest, canIncreaseGlobalStats) {
305 constexpr size_t TOTAL_FRAMES = 5;
306 constexpr size_t MISSED_FRAMES = 4;
307 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
308
309 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
310
311 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
312 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
313 }
314 for (size_t i = 0; i < MISSED_FRAMES; i++) {
315 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
316 }
317 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
318 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
319 }
320
321 SFTimeStatsGlobalProto globalProto;
322 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
323
324 ASSERT_TRUE(globalProto.has_total_frames());
325 EXPECT_EQ(TOTAL_FRAMES, globalProto.total_frames());
326 ASSERT_TRUE(globalProto.has_missed_frames());
327 EXPECT_EQ(MISSED_FRAMES, globalProto.missed_frames());
328 ASSERT_TRUE(globalProto.has_client_composition_frames());
329 EXPECT_EQ(CLIENT_COMPOSITION_FRAMES, globalProto.client_composition_frames());
330}
331
Alec Mouri91f6df32020-01-30 08:48:58 -0800332TEST_F(TimeStatsTest, canIncreaseLateAcquireFrames) {
333 // this stat is not in the proto so verify by checking the string dump
334 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
335
336 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
337
338 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
339 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
340 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
341 }
342 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
343
344 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
345 const std::string expectedResult = "lateAcquireFrames = " + std::to_string(LATE_ACQUIRE_FRAMES);
346 EXPECT_THAT(result, HasSubstr(expectedResult));
347}
348
349TEST_F(TimeStatsTest, canIncreaseBadDesiredPresent) {
350 // this stat is not in the proto so verify by checking the string dump
351 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 2;
352
353 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
354
355 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
356 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
357 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
358 }
359 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
360
361 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
362 const std::string expectedResult =
363 "badDesiredPresentFrames = " + std::to_string(BAD_DESIRED_PRESENT_FRAMES);
364 EXPECT_THAT(result, HasSubstr(expectedResult));
365}
366
Alec Mouri9a29e672020-09-14 12:39:14 -0700367TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
368 // this stat is not in the proto so verify by checking the string dump
369 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
370
371 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mouri363faf02021-01-29 16:34:55 -0800372 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
373 JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
374 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
375 JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
376 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
377 JankType::DisplayHAL, 1, 2, 3});
378 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
379 JankType::AppDeadlineMissed, 1, 2, 3});
380 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasanead17162021-02-18 02:17:37 +0000381 JankType::SurfaceFlingerScheduling, 1, 2, 3});
382 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
383 JankType::PredictionError, 1, 2, 3});
384 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
385 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
386 3});
387 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Alec Mouri363faf02021-01-29 16:34:55 -0800388 JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700389
390 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
Alec Mouri7d436ec2021-01-27 20:40:50 -0800391 std::string expectedResult =
392 "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
393 EXPECT_THAT(result, HasSubstr(expectedResult));
394 expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
395 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000396 expectedResult = "totalTimelineFrames = " + std::to_string(8);
Alec Mouri9a29e672020-09-14 12:39:14 -0700397 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000398 expectedResult = "jankyFrames = " + std::to_string(7);
Alec Mouri9a29e672020-09-14 12:39:14 -0700399 EXPECT_THAT(result, HasSubstr(expectedResult));
400 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
401 EXPECT_THAT(result, HasSubstr(expectedResult));
402 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
403 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000404 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700405 EXPECT_THAT(result, HasSubstr(expectedResult));
Adithya Srinivasanead17162021-02-18 02:17:37 +0000406 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
407 EXPECT_THAT(result, HasSubstr(expectedResult));
408 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
409 EXPECT_THAT(result, HasSubstr(expectedResult));
410 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
411 EXPECT_THAT(result, HasSubstr(expectedResult));
412 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
Alec Mouri9a29e672020-09-14 12:39:14 -0700413 EXPECT_THAT(result, HasSubstr(expectedResult));
414}
415
Ady Abraham8b9e6122021-01-26 19:11:45 -0800416TEST_F(TimeStatsTest, canCaptureSetFrameRateVote) {
417 // this stat is not in the proto so verify by checking the string dump
418 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
419
420 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
421
422 const auto frameRate60 = TimeStats::SetFrameRateVote{
423 .frameRate = 60.0f,
424 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
425 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
426 };
427 const auto frameRate90 = TimeStats::SetFrameRateVote{
428 .frameRate = 90.0f,
429 .frameRateCompatibility =
430 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
431 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
432 };
433 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
434 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
435 std::string expectedResult = "frameRate = 60.00";
436 EXPECT_THAT(result, HasSubstr(expectedResult));
437 expectedResult = "frameRateCompatibility = Default";
438 EXPECT_THAT(result, HasSubstr(expectedResult));
439 expectedResult = "seamlessness = ShouldBeSeamless";
440 EXPECT_THAT(result, HasSubstr(expectedResult));
441
442 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRate90);
443 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
444 expectedResult = "frameRate = 90.00";
445 EXPECT_THAT(result, HasSubstr(expectedResult));
446 expectedResult = "frameRateCompatibility = ExactOrMultiple";
447 EXPECT_THAT(result, HasSubstr(expectedResult));
448 expectedResult = "seamlessness = NotRequired";
449 EXPECT_THAT(result, HasSubstr(expectedResult));
450
451 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRate60);
452 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
453 expectedResult = "frameRate = 60.00";
454 EXPECT_THAT(result, HasSubstr(expectedResult));
455 expectedResult = "frameRateCompatibility = Default";
456 EXPECT_THAT(result, HasSubstr(expectedResult));
457 expectedResult = "seamlessness = ShouldBeSeamless";
458 EXPECT_THAT(result, HasSubstr(expectedResult));
459}
460
461TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) {
462 // this stat is not in the proto so verify by checking the string dump
463 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
464
465 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
466
467 const auto frameRate90 = TimeStats::SetFrameRateVote{
468 .frameRate = 90.0f,
469 .frameRateCompatibility =
470 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
471 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
472 };
473 const auto frameRateDefault = TimeStats::SetFrameRateVote{
474 .frameRate = 0.0f,
475 .frameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility::Default,
476 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::ShouldBeSeamless,
477 };
478 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate90);
479 std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
480 std::string expectedResult = "frameRate = 90.00";
481 EXPECT_THAT(result, HasSubstr(expectedResult));
482 expectedResult = "frameRateCompatibility = ExactOrMultiple";
483 EXPECT_THAT(result, HasSubstr(expectedResult));
484 expectedResult = "seamlessness = NotRequired";
485 EXPECT_THAT(result, HasSubstr(expectedResult));
486
487 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000, frameRateDefault);
488 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
489 expectedResult = "frameRate = 90.00";
490 EXPECT_THAT(result, HasSubstr(expectedResult));
491 expectedResult = "frameRateCompatibility = ExactOrMultiple";
492 EXPECT_THAT(result, HasSubstr(expectedResult));
493 expectedResult = "seamlessness = NotRequired";
494 EXPECT_THAT(result, HasSubstr(expectedResult));
495
496 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 4, 4000000, frameRateDefault);
497 result = inputCommand(InputCommand::DUMP_ALL, FMT_STRING);
498 expectedResult = "frameRate = 90.00";
499 EXPECT_THAT(result, HasSubstr(expectedResult));
500 expectedResult = "frameRateCompatibility = ExactOrMultiple";
501 EXPECT_THAT(result, HasSubstr(expectedResult));
502 expectedResult = "seamlessness = NotRequired";
503 EXPECT_THAT(result, HasSubstr(expectedResult));
504}
505
Vishnu Nair9b079a22020-01-21 14:36:08 -0800506TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) {
507 // this stat is not in the proto so verify by checking the string dump
508 constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2;
509
510 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
511 for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) {
512 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
513 }
514
515 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
516 const std::string expectedResult =
517 "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES);
518 EXPECT_THAT(result, HasSubstr(expectedResult));
519}
520
Alec Mouri8de697e2020-03-19 10:52:01 -0700521TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) {
522 // this stat is not in the proto so verify by checking the string dump
523 constexpr size_t REFRESH_RATE_SWITCHES = 2;
524
525 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
526 for (size_t i = 0; i < REFRESH_RATE_SWITCHES; i++) {
527 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
528 }
529
530 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
531 const std::string expectedResult =
532 "refreshRateSwitches = " + std::to_string(REFRESH_RATE_SWITCHES);
533 EXPECT_THAT(result, HasSubstr(expectedResult));
534}
535
Alec Mouri8f7a0102020-04-15 12:11:10 -0700536TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) {
537 // this stat is not in the proto so verify by checking the string dump
538 constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2;
539
540 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
541 for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) {
542 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
543 }
544
545 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
546 const std::string expectedResult =
547 "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES);
548 EXPECT_THAT(result, HasSubstr(expectedResult));
549}
550
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800551TEST_F(TimeStatsTest, canAverageFrameDuration) {
552 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Peiyong Lin65248e02020-04-18 21:15:07 -0700553 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000554 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
555 std::chrono::nanoseconds(6ms).count());
556 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
557 std::chrono::nanoseconds(16ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800558
559 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
560 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 10.000 ms"));
561}
562
563TEST_F(TimeStatsTest, canAverageRenderEngineTimings) {
564 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
Adithya Srinivasanead17162021-02-18 02:17:37 +0000565 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800566 std::make_shared<FenceTime>(
567 std::chrono::duration_cast<
568 std::chrono::nanoseconds>(3ms)
569 .count()));
570
Adithya Srinivasanead17162021-02-18 02:17:37 +0000571 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
572 std::chrono::nanoseconds(8ms).count());
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800573
Peiyong Lind8460c82020-07-28 16:04:22 -0700574 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700575 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000576 mTimeStats->setPresentFenceGlobal(
577 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800578
579 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
580 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 3.000 ms"));
581}
582
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800583TEST_F(TimeStatsTest, canInsertGlobalPresentToPresent) {
584 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
585
586 ASSERT_NO_FATAL_FAILURE(
587 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
588 ASSERT_NO_FATAL_FAILURE(
589 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
590
Peiyong Lin65248e02020-04-18 21:15:07 -0700591 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800592 ASSERT_NO_FATAL_FAILURE(
593 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000)));
594 ASSERT_NO_FATAL_FAILURE(
595 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000)));
596
Peiyong Lin65248e02020-04-18 21:15:07 -0700597 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::OFF));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800598 ASSERT_NO_FATAL_FAILURE(
599 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(6000000)));
600 ASSERT_NO_FATAL_FAILURE(
601 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(8000000)));
602
603 SFTimeStatsGlobalProto globalProto;
604 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
605
606 ASSERT_EQ(1, globalProto.present_to_present_size());
607 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.present_to_present().Get(0);
608 EXPECT_EQ(1, histogramProto.frame_count());
609 EXPECT_EQ(2, histogramProto.time_millis());
610}
611
Alec Mouri9519bf12019-11-15 16:54:44 -0800612TEST_F(TimeStatsTest, canInsertGlobalFrameDuration) {
613 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
614
Peiyong Lin65248e02020-04-18 21:15:07 -0700615 mTimeStats->setPowerMode(PowerMode::OFF);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000616 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
617 std::chrono::nanoseconds(5ms).count());
Peiyong Lin65248e02020-04-18 21:15:07 -0700618 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000619 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
620 std::chrono::nanoseconds(6ms).count());
Alec Mouri9519bf12019-11-15 16:54:44 -0800621
622 SFTimeStatsGlobalProto globalProto;
623 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
624
625 ASSERT_EQ(1, globalProto.frame_duration_size());
626 const SFTimeStatsHistogramBucketProto& histogramProto = globalProto.frame_duration().Get(0);
627 EXPECT_EQ(1, histogramProto.frame_count());
628 EXPECT_EQ(3, histogramProto.time_millis());
629}
630
Alec Mourie4034bb2019-11-19 12:45:54 -0800631TEST_F(TimeStatsTest, canInsertGlobalRenderEngineTiming) {
632 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
633
Adithya Srinivasanead17162021-02-18 02:17:37 +0000634 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(1ms).count(),
Alec Mourie4034bb2019-11-19 12:45:54 -0800635 std::make_shared<FenceTime>(
636 std::chrono::duration_cast<
637 std::chrono::nanoseconds>(3ms)
638 .count()));
639
Adithya Srinivasanead17162021-02-18 02:17:37 +0000640 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
641 std::chrono::nanoseconds(6ms).count());
Alec Mourie4034bb2019-11-19 12:45:54 -0800642
643 // First verify that flushing RenderEngine durations did not occur yet.
644 SFTimeStatsGlobalProto preFlushProto;
645 ASSERT_TRUE(preFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
646 ASSERT_EQ(0, preFlushProto.render_engine_timing_size());
647
Peiyong Lind8460c82020-07-28 16:04:22 -0700648 // Push a fake present fence to trigger flushing the RenderEngine timings.
Peiyong Lin65248e02020-04-18 21:15:07 -0700649 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000650 mTimeStats->setPresentFenceGlobal(
651 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mourie4034bb2019-11-19 12:45:54 -0800652
653 // Now we can verify that RenderEngine durations were flushed now.
654 SFTimeStatsGlobalProto postFlushProto;
655 ASSERT_TRUE(postFlushProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
656
657 ASSERT_EQ(1, postFlushProto.render_engine_timing_size());
658 const SFTimeStatsHistogramBucketProto& histogramProto =
659 postFlushProto.render_engine_timing().Get(0);
660 EXPECT_EQ(2, histogramProto.frame_count());
661 EXPECT_EQ(2, histogramProto.time_millis());
662}
663
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800664TEST_F(TimeStatsTest, canInsertOneLayerTimeStats) {
665 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
666
667 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
668 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_0, 2, 2000000);
669
670 SFTimeStatsGlobalProto globalProto;
671 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
672
673 ASSERT_EQ(1, globalProto.stats_size());
674 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
675 ASSERT_TRUE(layerProto.has_layer_name());
676 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
677 ASSERT_TRUE(layerProto.has_total_frames());
678 EXPECT_EQ(1, layerProto.total_frames());
679 ASSERT_EQ(6, layerProto.deltas_size());
680 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
681 ASSERT_EQ(1, deltaProto.histograms_size());
682 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
683 EXPECT_EQ(1, histogramProto.frame_count());
684 if ("post2acquire" == deltaProto.delta_name()) {
685 EXPECT_EQ(1, histogramProto.time_millis());
686 } else if ("post2present" == deltaProto.delta_name()) {
687 EXPECT_EQ(4, histogramProto.time_millis());
688 } else if ("acquire2present" == deltaProto.delta_name()) {
689 EXPECT_EQ(3, histogramProto.time_millis());
690 } else if ("latch2present" == deltaProto.delta_name()) {
691 EXPECT_EQ(2, histogramProto.time_millis());
692 } else if ("desired2present" == deltaProto.delta_name()) {
693 EXPECT_EQ(1, histogramProto.time_millis());
694 } else if ("present2present" == deltaProto.delta_name()) {
695 EXPECT_EQ(1, histogramProto.time_millis());
696 } else {
697 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
698 }
699 }
700}
701
702TEST_F(TimeStatsTest, canNotInsertInvalidLayerNameTimeStats) {
703 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
704
705 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_INVALID, 1, 1000000);
706 insertTimeRecord(NORMAL_SEQUENCE_2, LAYER_ID_INVALID, 2, 2000000);
707
708 SFTimeStatsGlobalProto globalProto;
709 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
710
711 ASSERT_EQ(0, globalProto.stats_size());
712}
713
714TEST_F(TimeStatsTest, canInsertMultipleLayersTimeStats) {
715 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
716
717 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
718 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
719 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
720 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
721
722 SFTimeStatsGlobalProto globalProto;
723 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
724
725 EXPECT_EQ(2, globalProto.stats_size());
726}
727
728TEST_F(TimeStatsTest, canInsertUnorderedLayerTimeStats) {
729 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
730
731 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
732 insertTimeRecord(UNORDERED_SEQUENCE, LAYER_ID_0, 2, 2000000);
733
734 SFTimeStatsGlobalProto globalProto;
735 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
736
737 ASSERT_EQ(1, globalProto.stats_size());
738 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
739 ASSERT_TRUE(layerProto.has_layer_name());
740 EXPECT_EQ(genLayerName(LAYER_ID_0), layerProto.layer_name());
741 ASSERT_TRUE(layerProto.has_total_frames());
742 EXPECT_EQ(1, layerProto.total_frames());
743 ASSERT_EQ(6, layerProto.deltas_size());
744 for (const SFTimeStatsDeltaProto& deltaProto : layerProto.deltas()) {
745 ASSERT_EQ(1, deltaProto.histograms_size());
746 const SFTimeStatsHistogramBucketProto& histogramProto = deltaProto.histograms().Get(0);
747 EXPECT_EQ(1, histogramProto.frame_count());
748 if ("post2acquire" == deltaProto.delta_name()) {
749 EXPECT_EQ(0, histogramProto.time_millis());
750 } else if ("post2present" == deltaProto.delta_name()) {
751 EXPECT_EQ(2, histogramProto.time_millis());
752 } else if ("acquire2present" == deltaProto.delta_name()) {
753 EXPECT_EQ(2, histogramProto.time_millis());
754 } else if ("latch2present" == deltaProto.delta_name()) {
755 EXPECT_EQ(2, histogramProto.time_millis());
756 } else if ("desired2present" == deltaProto.delta_name()) {
757 EXPECT_EQ(1, histogramProto.time_millis());
758 } else if ("present2present" == deltaProto.delta_name()) {
759 EXPECT_EQ(1, histogramProto.time_millis());
760 } else {
761 FAIL() << "Unknown delta_name: " << deltaProto.delta_name();
762 }
763 }
764}
765
Alec Mourifb571ea2019-01-24 18:42:10 -0800766TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
767 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
768
769 uint32_t fpsOne = 30;
770 uint32_t fpsTwo = 90;
771 uint64_t millisOne = 5000;
772 uint64_t millisTwo = 7000;
773
774 mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
775 mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
776
777 SFTimeStatsGlobalProto globalProto;
778 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
779
780 SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
781 SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
782 expectedConfigOne->set_fps(fpsOne);
783 expectedBucketOne.set_duration_millis(millisOne);
784
785 SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
786 SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
787 expectedConfigTwo->set_fps(fpsTwo);
788 expectedBucketTwo.set_duration_millis(millisTwo);
789
790 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
791
792 std::unordered_set<uint32_t> seen_fps;
793 for (const auto& bucket : globalProto.display_config_stats()) {
794 seen_fps.emplace(bucket.config().fps());
795 if (fpsOne == bucket.config().fps()) {
796 EXPECT_EQ(millisOne, bucket.duration_millis());
797 } else if (fpsTwo == bucket.config().fps()) {
798 EXPECT_EQ(millisTwo, bucket.duration_millis());
799 } else {
800 FAIL() << "Unknown fps: " << bucket.config().fps();
801 }
802 }
803 EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
804}
805
806TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
807 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
808
809 uint32_t fps = 30;
810 uint64_t millisOne = 5000;
811 uint64_t millisTwo = 7000;
812
813 mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
814 mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
815
816 SFTimeStatsGlobalProto globalProto;
817 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
818 EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
819 EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
820 EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
821}
822
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800823TEST_F(TimeStatsTest, canRemoveTimeRecord) {
824 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
825
826 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
827 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 2, 2000000);
828 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(0, 2));
829 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
830
831 SFTimeStatsGlobalProto globalProto;
832 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
833
834 ASSERT_EQ(1, globalProto.stats_size());
835 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
836 ASSERT_TRUE(layerProto.has_total_frames());
837 EXPECT_EQ(1, layerProto.total_frames());
838}
839
840TEST_F(TimeStatsTest, canRecoverFromIncompleteTimeRecordError) {
841 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
842
843 uint64_t frameNumber = 1;
844 nsecs_t ts = 1000000;
845 insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
Alec Mourifb571ea2019-01-24 18:42:10 -0800846 for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800847 frameNumber++;
848 ts += 1000000;
849 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
850 }
851
852 SFTimeStatsGlobalProto globalProto;
853 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
854
855 ASSERT_EQ(1, globalProto.stats_size());
856 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
857 ASSERT_TRUE(layerProto.has_total_frames());
858 EXPECT_EQ(1, layerProto.total_frames());
859}
860
861TEST_F(TimeStatsTest, layerTimeStatsOnDestroy) {
862 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
863
864 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
865 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
866 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(0));
867 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 3000000);
868
869 SFTimeStatsGlobalProto globalProto;
870 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
871
872 ASSERT_EQ(1, globalProto.stats_size());
873 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
874 ASSERT_TRUE(layerProto.has_total_frames());
875 EXPECT_EQ(1, layerProto.total_frames());
876}
877
878TEST_F(TimeStatsTest, canClearTimeStats) {
879 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
880
881 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames());
882 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames());
883 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames());
Peiyong Lin65248e02020-04-18 21:15:07 -0700884 ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON));
Alec Mouri31ac64a2020-01-09 09:26:22 -0800885
Adithya Srinivasanead17162021-02-18 02:17:37 +0000886 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(),
887 std::chrono::nanoseconds(6ms).count());
888 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
889 std::chrono::nanoseconds(6ms).count());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800890 ASSERT_NO_FATAL_FAILURE(
891 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(1000000)));
892 ASSERT_NO_FATAL_FAILURE(
893 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(2000000)));
894 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
895 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
896
897 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
898
899 SFTimeStatsGlobalProto globalProto;
900 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
901
902 EXPECT_EQ(0, globalProto.total_frames());
903 EXPECT_EQ(0, globalProto.missed_frames());
904 EXPECT_EQ(0, globalProto.client_composition_frames());
905 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri31ac64a2020-01-09 09:26:22 -0800906 EXPECT_EQ(0, globalProto.frame_duration_size());
907 EXPECT_EQ(0, globalProto.render_engine_timing_size());
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800908 EXPECT_EQ(0, globalProto.stats_size());
909}
910
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800911TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) {
912 // These stats are not in the proto so verify by checking the string dump.
Vishnu Nair9b079a22020-01-21 14:36:08 -0800913 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
914 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames());
Alec Mouri8de697e2020-03-19 10:52:01 -0700915 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches());
Alec Mouri8f7a0102020-04-15 12:11:10 -0700916 ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges());
Peiyong Lin65248e02020-04-18 21:15:07 -0700917 mTimeStats->setPowerMode(PowerMode::ON);
Adithya Srinivasanead17162021-02-18 02:17:37 +0000918 mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(),
919 std::chrono::nanoseconds(5ms).count());
920 mTimeStats->recordRenderEngineDuration(std::chrono::nanoseconds(4ms).count(),
921 std::chrono::nanoseconds(6ms).count());
922 mTimeStats->setPresentFenceGlobal(
923 std::make_shared<FenceTime>(std::chrono::nanoseconds(1ms).count()));
Alec Mouri9a29e672020-09-14 12:39:14 -0700924
Alec Mouri363faf02021-01-29 16:34:55 -0800925 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
926 JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
927 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
928 JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
929 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
930 JankType::DisplayHAL, 1, 2, 3});
931 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
932 JankType::AppDeadlineMissed, 1, 2, 3});
933 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasanead17162021-02-18 02:17:37 +0000934 JankType::SurfaceFlingerScheduling, 1, 2, 3});
935 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
936 JankType::PredictionError, 1, 2, 3});
937 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
938 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
939 3});
940 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Alec Mouri363faf02021-01-29 16:34:55 -0800941 JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -0700942
Vishnu Nair9b079a22020-01-21 14:36:08 -0800943 EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
944
945 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
946 EXPECT_THAT(result, HasSubstr("clientCompositionReusedFrames = 0"));
Alec Mouri8de697e2020-03-19 10:52:01 -0700947 EXPECT_THAT(result, HasSubstr("refreshRateSwitches = 0"));
Alec Mouri8f7a0102020-04-15 12:11:10 -0700948 EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
Vishnu Nairabf97fd2020-02-03 13:51:16 -0800949 EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
950 EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
Alec Mouri56e63852021-03-09 18:17:25 -0800951 std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
952 EXPECT_THAT(result, HasSubstr(expectedResult));
953 expectedResult = "jankyFrames = " + std::to_string(0);
954 EXPECT_THAT(result, HasSubstr(expectedResult));
955 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
956 EXPECT_THAT(result, HasSubstr(expectedResult));
957 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
958 EXPECT_THAT(result, HasSubstr(expectedResult));
959 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
960 EXPECT_THAT(result, HasSubstr(expectedResult));
961 expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
962 EXPECT_THAT(result, HasSubstr(expectedResult));
963 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
964 EXPECT_THAT(result, HasSubstr(expectedResult));
965 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
966 EXPECT_THAT(result, HasSubstr(expectedResult));
967 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
968 EXPECT_THAT(result, HasSubstr(expectedResult));
Vishnu Nair9b079a22020-01-21 14:36:08 -0800969}
970
Yiwei Zhang16faa5d2018-11-13 18:12:59 -0800971TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
972 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
973
974 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
975 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 1000000);
976 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
977 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 2000000);
978 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 3, 2000000);
979
980 SFTimeStatsGlobalProto globalProto;
981 ASSERT_TRUE(
982 globalProto.ParseFromString(inputCommand(InputCommand::DUMP_MAXLAYERS_1, FMT_PROTO)));
983
984 ASSERT_EQ(1, globalProto.stats_size());
985 const SFTimeStatsLayerProto& layerProto = globalProto.stats().Get(0);
986 ASSERT_TRUE(layerProto.has_layer_name());
987 EXPECT_EQ(genLayerName(LAYER_ID_1), layerProto.layer_name());
988 ASSERT_TRUE(layerProto.has_total_frames());
989 EXPECT_EQ(2, layerProto.total_frames());
990}
991
992TEST_F(TimeStatsTest, canDumpWithInvalidMaxLayers) {
993 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
994
995 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
996 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
997
998 SFTimeStatsGlobalProto globalProto;
999 ASSERT_TRUE(globalProto.ParseFromString(
1000 inputCommand(InputCommand::DUMP_MAXLAYERS_INVALID, FMT_PROTO)));
1001
1002 ASSERT_EQ(0, globalProto.stats_size());
1003}
1004
Yiwei Zhangdd221b22020-06-12 11:06:19 -07001005TEST_F(TimeStatsTest, noInfInAverageFPS) {
1006 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1007 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1008 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 1000000);
1009
1010 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1011 EXPECT_THAT(result, HasSubstr("averageFPS = 0.000"));
1012}
1013
Alec Mouri37384342020-01-02 17:23:37 -08001014namespace {
1015std::string buildExpectedHistogramBytestring(const std::vector<int32_t>& times,
1016 const std::vector<int32_t>& frameCounts) {
1017 util::ProtoOutputStream proto;
1018 for (int i = 0; i < times.size(); i++) {
1019 ALOGE("Writing time: %d", times[i]);
1020 proto.write(util::FIELD_TYPE_INT32 | util::FIELD_COUNT_REPEATED | 1 /* field id */,
1021 (int32_t)times[i]);
1022 ALOGE("Writing count: %d", frameCounts[i]);
1023 proto.write(util::FIELD_TYPE_INT64 | util::FIELD_COUNT_REPEATED | 2 /* field id */,
1024 (int64_t)frameCounts[i]);
1025 }
1026 std::string byteString;
1027 proto.serializeToString(&byteString);
1028 return byteString;
1029}
1030
Ady Abraham8b9e6122021-01-26 19:11:45 -08001031std::string frameRateVoteToProtoByteString(
1032 float refreshRate,
1033 TimeStats::SetFrameRateVote::FrameRateCompatibility frameRateCompatibility,
1034 TimeStats::SetFrameRateVote::Seamlessness seamlessness) {
Alec Mouri75de8f22021-01-20 14:53:44 -08001035 util::ProtoOutputStream proto;
1036 proto.write(android::util::FIELD_TYPE_FLOAT | 1 /* field id */, refreshRate);
Ady Abraham8b9e6122021-01-26 19:11:45 -08001037 proto.write(android::util::FIELD_TYPE_ENUM | 2 /* field id */,
1038 static_cast<int>(frameRateCompatibility));
1039 proto.write(android::util::FIELD_TYPE_ENUM | 3 /* field id */, static_cast<int>(seamlessness));
Alec Mouri75de8f22021-01-20 14:53:44 -08001040
1041 std::string byteString;
1042 proto.serializeToString(&byteString);
1043 return byteString;
1044}
1045
Alec Mouri37384342020-01-02 17:23:37 -08001046std::string dumpByteStringHex(const std::string& str) {
1047 std::stringstream ss;
1048 ss << std::hex;
1049 for (const char& c : str) {
1050 ss << (int)c << " ";
1051 }
1052
1053 return ss.str();
1054}
1055
1056} // namespace
1057
1058MATCHER_P2(BytesEq, bytes, size, "") {
1059 std::string expected;
1060 expected.append((const char*)bytes, size);
1061 std::string actual;
1062 actual.append((const char*)arg, size);
1063
1064 *result_listener << "Bytes are not equal! \n";
1065 *result_listener << "size: " << size << "\n";
1066 *result_listener << "expected: " << dumpByteStringHex(expected).c_str() << "\n";
1067 *result_listener << "actual: " << dumpByteStringHex(actual).c_str() << "\n";
1068
1069 return expected == actual;
1070}
1071
Alec Mouridfad9002020-02-12 17:49:09 -08001072TEST_F(TimeStatsTest, globalStatsCallback) {
1073 constexpr size_t TOTAL_FRAMES = 5;
1074 constexpr size_t MISSED_FRAMES = 4;
1075 constexpr size_t CLIENT_COMPOSITION_FRAMES = 3;
1076 constexpr size_t DISPLAY_EVENT_CONNECTIONS = 14;
1077
1078 mTimeStats->onBootFinished();
1079 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1080
1081 for (size_t i = 0; i < TOTAL_FRAMES; i++) {
1082 mTimeStats->incrementTotalFrames();
1083 }
1084 for (size_t i = 0; i < MISSED_FRAMES; i++) {
1085 mTimeStats->incrementMissedFrames();
1086 }
1087 for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) {
1088 mTimeStats->incrementClientCompositionFrames();
1089 }
1090
Alec Mouri9a29e672020-09-14 12:39:14 -07001091 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1092
Alec Mouridfad9002020-02-12 17:49:09 -08001093 mTimeStats->recordDisplayEventConnectionCount(DISPLAY_EVENT_CONNECTIONS);
Peiyong Lin65248e02020-04-18 21:15:07 -07001094 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouridfad9002020-02-12 17:49:09 -08001095 mTimeStats->recordFrameDuration(1000000, 3000000);
1096 mTimeStats->recordRenderEngineDuration(2000000, 4000000);
1097 mTimeStats->recordRenderEngineDuration(2000000, std::make_shared<FenceTime>(3000000));
1098
1099 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1100 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1101
Alec Mouri363faf02021-01-29 16:34:55 -08001102 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1103 JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
1104 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1105 JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
1106 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1107 JankType::DisplayHAL, 1, 2, 3});
1108 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1109 JankType::AppDeadlineMissed, 1, 2, 3});
1110 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasanead17162021-02-18 02:17:37 +00001111 JankType::SurfaceFlingerScheduling, 1, 2, 3});
1112 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1113 JankType::PredictionError, 1, 2, 3});
1114 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1115 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
1116 3});
1117 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Alec Mouri363faf02021-01-29 16:34:55 -08001118 JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -07001119
Alec Mouridfad9002020-02-12 17:49:09 -08001120 EXPECT_THAT(mDelegate->mAtomTags,
1121 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1122 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1123 EXPECT_NE(nullptr, mDelegate->mCallback);
1124 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1125
1126 std::string expectedFrameDuration = buildExpectedHistogramBytestring({2}, {1});
1127 std::string expectedRenderEngineTiming = buildExpectedHistogramBytestring({1, 2}, {1, 1});
Alec Mouri75de8f22021-01-20 14:53:44 -08001128 std::string expectedEmptyHistogram = buildExpectedHistogramBytestring({}, {});
Adithya Srinivasanead17162021-02-18 02:17:37 +00001129 std::string expectedSfDeadlineMissed = buildExpectedHistogramBytestring({1}, {7});
1130 std::string expectedSfPredictionErrors = buildExpectedHistogramBytestring({2}, {7});
Alec Mouridfad9002020-02-12 17:49:09 -08001131
1132 {
1133 InSequence seq;
1134 EXPECT_CALL(*mDelegate,
1135 statsEventSetAtomId(mDelegate->mEvent,
1136 android::util::SURFACEFLINGER_STATS_GLOBAL_INFO));
1137 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, TOTAL_FRAMES));
1138 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, MISSED_FRAMES));
1139 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, CLIENT_COMPOSITION_FRAMES));
1140 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, _));
1141 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, 2));
1142 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, DISPLAY_EVENT_CONNECTIONS));
1143 EXPECT_CALL(*mDelegate,
1144 statsEventWriteByteArray(mDelegate->mEvent,
1145 BytesEq((const uint8_t*)expectedFrameDuration.c_str(),
1146 expectedFrameDuration.size()),
1147 expectedFrameDuration.size()));
1148 EXPECT_CALL(*mDelegate,
1149 statsEventWriteByteArray(mDelegate->mEvent,
1150 BytesEq((const uint8_t*)
1151 expectedRenderEngineTiming.c_str(),
1152 expectedRenderEngineTiming.size()),
1153 expectedRenderEngineTiming.size()));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001154 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 8));
1155 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 7));
Alec Mouri9a29e672020-09-14 12:39:14 -07001156 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1157 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1158 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001159 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 2));
Alec Mouri9a29e672020-09-14 12:39:14 -07001160 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001161 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1162 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Alec Mouri7d436ec2021-01-27 20:40:50 -08001163 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, REFRESH_RATE_BUCKET_0));
Alec Mouri75de8f22021-01-20 14:53:44 -08001164 EXPECT_CALL(*mDelegate,
1165 statsEventWriteByteArray(mDelegate->mEvent,
Alec Mouri363faf02021-01-29 16:34:55 -08001166 BytesEq((const uint8_t*)
1167 expectedSfDeadlineMissed.c_str(),
1168 expectedSfDeadlineMissed.size()),
1169 expectedSfDeadlineMissed.size()));
Alec Mouri75de8f22021-01-20 14:53:44 -08001170 EXPECT_CALL(*mDelegate,
1171 statsEventWriteByteArray(mDelegate->mEvent,
Alec Mouri363faf02021-01-29 16:34:55 -08001172 BytesEq((const uint8_t*)
1173 expectedSfPredictionErrors.c_str(),
1174 expectedSfPredictionErrors.size()),
1175 expectedSfPredictionErrors.size()));
Alec Mouri7d436ec2021-01-27 20:40:50 -08001176 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, RENDER_RATE_BUCKET_0));
Alec Mouri75de8f22021-01-20 14:53:44 -08001177
Alec Mouridfad9002020-02-12 17:49:09 -08001178 EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
1179 }
1180 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
1181 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1182 mDelegate->mCookie));
1183
1184 SFTimeStatsGlobalProto globalProto;
1185 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1186
1187 EXPECT_EQ(0, globalProto.total_frames());
1188 EXPECT_EQ(0, globalProto.missed_frames());
1189 EXPECT_EQ(0, globalProto.client_composition_frames());
1190 EXPECT_EQ(0, globalProto.present_to_present_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001191
1192 // also check dump-only stats: expect that global stats are indeed dropped but there should
1193 // still be stats for the layer
1194 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1195 std::string expectedResult = "totalTimelineFrames = " + std::to_string(0);
1196 EXPECT_THAT(result, HasSubstr(expectedResult));
1197 expectedResult = "totalTimelineFrames = " + std::to_string(8);
1198 EXPECT_THAT(result, HasSubstr(expectedResult));
1199 expectedResult = "jankyFrames = " + std::to_string(0);
1200 EXPECT_THAT(result, HasSubstr(expectedResult));
1201 expectedResult = "jankyFrames = " + std::to_string(7);
1202 EXPECT_THAT(result, HasSubstr(expectedResult));
1203 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(0);
1204 EXPECT_THAT(result, HasSubstr(expectedResult));
1205 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1206 EXPECT_THAT(result, HasSubstr(expectedResult));
1207 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(0);
1208 EXPECT_THAT(result, HasSubstr(expectedResult));
1209 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1210 EXPECT_THAT(result, HasSubstr(expectedResult));
1211 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(0);
1212 EXPECT_THAT(result, HasSubstr(expectedResult));
1213 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1214 EXPECT_THAT(result, HasSubstr(expectedResult));
1215 expectedResult = "appUnattributedJankyFrames = " + std::to_string(0);
1216 EXPECT_THAT(result, HasSubstr(expectedResult));
1217 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1218 EXPECT_THAT(result, HasSubstr(expectedResult));
1219 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(0);
1220 EXPECT_THAT(result, HasSubstr(expectedResult));
1221 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1222 EXPECT_THAT(result, HasSubstr(expectedResult));
1223 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(0);
1224 EXPECT_THAT(result, HasSubstr(expectedResult));
1225 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1226 EXPECT_THAT(result, HasSubstr(expectedResult));
1227 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(0);
1228 EXPECT_THAT(result, HasSubstr(expectedResult));
1229 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1230 EXPECT_THAT(result, HasSubstr(expectedResult));
Alec Mouridfad9002020-02-12 17:49:09 -08001231}
1232
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001233TEST_F(TimeStatsTest, layerStatsCallback_pullsAllAndClears) {
1234 constexpr size_t LATE_ACQUIRE_FRAMES = 2;
1235 constexpr size_t BAD_DESIRED_PRESENT_FRAMES = 3;
Alec Mouri37384342020-01-02 17:23:37 -08001236 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1237
1238 mTimeStats->onBootFinished();
1239
1240 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001241 for (size_t i = 0; i < LATE_ACQUIRE_FRAMES; i++) {
1242 mTimeStats->incrementLatchSkipped(LAYER_ID_0, TimeStats::LatchSkipReason::LateAcquire);
1243 }
1244 for (size_t i = 0; i < BAD_DESIRED_PRESENT_FRAMES; i++) {
1245 mTimeStats->incrementBadDesiredPresent(LAYER_ID_0);
1246 }
Ady Abraham8b9e6122021-01-26 19:11:45 -08001247 const auto frameRate60 = TimeStats::SetFrameRateVote{
1248 .frameRate = 60.0f,
1249 .frameRateCompatibility =
1250 TimeStats::SetFrameRateVote::FrameRateCompatibility::ExactOrMultiple,
1251 .seamlessness = TimeStats::SetFrameRateVote::Seamlessness::NotRequired,
1252 };
1253 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000, frameRate60);
Alec Mouri37384342020-01-02 17:23:37 -08001254
Alec Mouri363faf02021-01-29 16:34:55 -08001255 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1256 JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
1257 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1258 JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
1259 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1260 JankType::DisplayHAL, 1, 2, 3});
1261 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1262 JankType::AppDeadlineMissed, 1, 2, 3});
1263 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Adithya Srinivasanead17162021-02-18 02:17:37 +00001264 JankType::SurfaceFlingerScheduling, 1, 2, 2});
1265 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1266 JankType::PredictionError, 1, 2, 2});
1267 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
1268 JankType::AppDeadlineMissed | JankType::BufferStuffing, 1, 2,
1269 2});
1270 mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
Alec Mouri363faf02021-01-29 16:34:55 -08001271 JankType::None, 1, 2, 3});
Alec Mouri9a29e672020-09-14 12:39:14 -07001272
Alec Mouri37384342020-01-02 17:23:37 -08001273 EXPECT_THAT(mDelegate->mAtomTags,
1274 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1275 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1276 EXPECT_NE(nullptr, mDelegate->mCallback);
1277 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1278
1279 std::string expectedPresentToPresent = buildExpectedHistogramBytestring({1}, {1});
1280 std::string expectedPostToPresent = buildExpectedHistogramBytestring({4}, {1});
1281 std::string expectedAcquireToPresent = buildExpectedHistogramBytestring({3}, {1});
1282 std::string expectedLatchToPresent = buildExpectedHistogramBytestring({2}, {1});
1283 std::string expectedDesiredToPresent = buildExpectedHistogramBytestring({1}, {1});
1284 std::string expectedPostToAcquire = buildExpectedHistogramBytestring({1}, {1});
Ady Abraham8b9e6122021-01-26 19:11:45 -08001285 std::string expectedFrameRateOverride =
1286 frameRateVoteToProtoByteString(frameRate60.frameRate,
1287 frameRate60.frameRateCompatibility,
1288 frameRate60.seamlessness);
Adithya Srinivasanead17162021-02-18 02:17:37 +00001289 std::string expectedAppDeadlineMissed = buildExpectedHistogramBytestring({3, 2}, {4, 3});
Alec Mouri37384342020-01-02 17:23:37 -08001290 {
1291 InSequence seq;
1292 EXPECT_CALL(*mDelegate,
1293 statsEventSetAtomId(mDelegate->mEvent,
1294 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1295 EXPECT_CALL(*mDelegate,
1296 statsEventWriteString8(mDelegate->mEvent,
1297 StrEq(genLayerName(LAYER_ID_0).c_str())));
1298 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, 1));
1299 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, 0));
1300 EXPECT_CALL(*mDelegate,
1301 statsEventWriteByteArray(mDelegate->mEvent,
1302 BytesEq((const uint8_t*)
1303 expectedPresentToPresent.c_str(),
1304 expectedPresentToPresent.size()),
1305 expectedPresentToPresent.size()));
1306 EXPECT_CALL(*mDelegate,
1307 statsEventWriteByteArray(mDelegate->mEvent,
1308 BytesEq((const uint8_t*)expectedPostToPresent.c_str(),
1309 expectedPostToPresent.size()),
1310 expectedPostToPresent.size()));
1311 EXPECT_CALL(*mDelegate,
1312 statsEventWriteByteArray(mDelegate->mEvent,
1313 BytesEq((const uint8_t*)
1314 expectedAcquireToPresent.c_str(),
1315 expectedAcquireToPresent.size()),
1316 expectedAcquireToPresent.size()));
1317 EXPECT_CALL(*mDelegate,
1318 statsEventWriteByteArray(mDelegate->mEvent,
1319 BytesEq((const uint8_t*)expectedLatchToPresent.c_str(),
1320 expectedLatchToPresent.size()),
1321 expectedLatchToPresent.size()));
1322 EXPECT_CALL(*mDelegate,
1323 statsEventWriteByteArray(mDelegate->mEvent,
1324 BytesEq((const uint8_t*)
1325 expectedDesiredToPresent.c_str(),
1326 expectedDesiredToPresent.size()),
1327 expectedDesiredToPresent.size()));
1328 EXPECT_CALL(*mDelegate,
1329 statsEventWriteByteArray(mDelegate->mEvent,
1330 BytesEq((const uint8_t*)expectedPostToAcquire.c_str(),
1331 expectedPostToAcquire.size()),
1332 expectedPostToAcquire.size()));
Yiwei Zhang7bfc75b2020-02-10 11:20:34 -08001333 EXPECT_CALL(*mDelegate, statsEventWriteInt64(mDelegate->mEvent, LATE_ACQUIRE_FRAMES));
1334 EXPECT_CALL(*mDelegate,
1335 statsEventWriteInt64(mDelegate->mEvent, BAD_DESIRED_PRESENT_FRAMES));
Alec Mouri9a29e672020-09-14 12:39:14 -07001336 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, UID_0));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001337 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 8));
1338 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 7));
Alec Mouri9a29e672020-09-14 12:39:14 -07001339 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1340 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1341 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001342 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 2));
Alec Mouri9a29e672020-09-14 12:39:14 -07001343 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Adithya Srinivasanead17162021-02-18 02:17:37 +00001344 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
1345 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 1));
Alec Mouri7d436ec2021-01-27 20:40:50 -08001346 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, REFRESH_RATE_BUCKET_0));
1347 EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, RENDER_RATE_BUCKET_0));
Alec Mouri75de8f22021-01-20 14:53:44 -08001348 EXPECT_CALL(*mDelegate,
1349 statsEventWriteByteArray(mDelegate->mEvent,
1350 BytesEq((const uint8_t*)
1351 expectedFrameRateOverride.c_str(),
1352 expectedFrameRateOverride.size()),
1353 expectedFrameRateOverride.size()));
1354 EXPECT_CALL(*mDelegate,
1355 statsEventWriteByteArray(mDelegate->mEvent,
Alec Mouri363faf02021-01-29 16:34:55 -08001356 BytesEq((const uint8_t*)
1357 expectedAppDeadlineMissed.c_str(),
1358 expectedAppDeadlineMissed.size()),
1359 expectedAppDeadlineMissed.size()));
Alec Mouri9a29e672020-09-14 12:39:14 -07001360
Alec Mouri37384342020-01-02 17:23:37 -08001361 EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
1362 }
Tej Singh2a457b62020-01-31 16:16:10 -08001363 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
Alec Mouri37384342020-01-02 17:23:37 -08001364 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
1365 mDelegate->mCookie));
1366
1367 SFTimeStatsGlobalProto globalProto;
1368 ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
1369
1370 EXPECT_EQ(0, globalProto.stats_size());
Alec Mouri56e63852021-03-09 18:17:25 -08001371
1372 // also check dump-only stats: expect that layer stats are indeed dropped but there should still
1373 // be global stats
1374 const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
1375 std::string expectedResult = "totalTimelineFrames = " + std::to_string(8);
1376 EXPECT_THAT(result, HasSubstr(expectedResult));
1377 expectedResult = "jankyFrames = " + std::to_string(7);
1378 EXPECT_THAT(result, HasSubstr(expectedResult));
1379 expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
1380 EXPECT_THAT(result, HasSubstr(expectedResult));
1381 expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
1382 EXPECT_THAT(result, HasSubstr(expectedResult));
1383 expectedResult = "sfUnattributedJankyFrames = " + std::to_string(1);
1384 EXPECT_THAT(result, HasSubstr(expectedResult));
1385 expectedResult = "appUnattributedJankyFrames = " + std::to_string(2);
1386 EXPECT_THAT(result, HasSubstr(expectedResult));
1387 expectedResult = "sfSchedulingJankyFrames = " + std::to_string(1);
1388 EXPECT_THAT(result, HasSubstr(expectedResult));
1389 expectedResult = "sfPredictionErrorJankyFrames = " + std::to_string(1);
1390 EXPECT_THAT(result, HasSubstr(expectedResult));
1391 expectedResult = "appBufferStuffingJankyFrames = " + std::to_string(1);
1392 EXPECT_THAT(result, HasSubstr(expectedResult));
1393
1394 std::string expectedMissing = "uid = " + std::to_string(UID_0);
1395 EXPECT_THAT(result, Not(HasSubstr(expectedMissing)));
Alec Mouri37384342020-01-02 17:23:37 -08001396}
1397
1398TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleLayers) {
1399 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1400
1401 mTimeStats->onBootFinished();
1402
1403 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1404 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1405 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1406 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1407
1408 EXPECT_THAT(mDelegate->mAtomTags,
1409 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1410 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1411 EXPECT_NE(nullptr, mDelegate->mCallback);
1412 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1413
1414 EXPECT_CALL(*mDelegate,
1415 statsEventSetAtomId(mDelegate->mEvent,
1416 android::util::SURFACEFLINGER_STATS_LAYER_INFO))
1417 .Times(2);
1418 EXPECT_CALL(*mDelegate,
1419 statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_0).c_str())));
1420 EXPECT_CALL(*mDelegate,
1421 statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_1).c_str())));
Tej Singh2a457b62020-01-31 16:16:10 -08001422 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
Alec Mouri37384342020-01-02 17:23:37 -08001423 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
1424 mDelegate->mCookie));
1425}
1426
1427TEST_F(TimeStatsTest, layerStatsCallback_pullsMultipleBuckets) {
1428 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1429
1430 mTimeStats->onBootFinished();
1431
1432 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1433 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1434 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1435 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1436
Tej Singh38a4b212020-03-13 19:04:51 -07001437 // Now make sure that TimeStats flushes global stats to set the callback.
Peiyong Lin65248e02020-04-18 21:15:07 -07001438 mTimeStats->setPowerMode(PowerMode::ON);
Alec Mouri37384342020-01-02 17:23:37 -08001439 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
1440 mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
1441 EXPECT_THAT(mDelegate->mAtomTags,
1442 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1443 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1444 EXPECT_NE(nullptr, mDelegate->mCallback);
1445 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1446
1447 EXPECT_THAT(mDelegate->mAtomTags,
1448 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1449 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1450 std::string expectedPresentToPresent = buildExpectedHistogramBytestring({1, 2}, {2, 1});
1451 {
1452 InSequence seq;
1453 EXPECT_CALL(*mDelegate,
1454 statsEventWriteByteArray(mDelegate->mEvent,
1455 BytesEq((const uint8_t*)
1456 expectedPresentToPresent.c_str(),
1457 expectedPresentToPresent.size()),
1458 expectedPresentToPresent.size()));
1459 EXPECT_CALL(*mDelegate, statsEventWriteByteArray(mDelegate->mEvent, _, _))
1460 .Times(AnyNumber());
1461 }
Tej Singh2a457b62020-01-31 16:16:10 -08001462 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
Alec Mouri37384342020-01-02 17:23:37 -08001463 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
1464 mDelegate->mCookie));
1465}
1466
1467TEST_F(TimeStatsTest, layerStatsCallback_limitsHistogramBuckets) {
1468 mDelegate = new FakeStatsEventDelegate;
1469 mTimeStats =
1470 std::make_unique<impl::TimeStats>(std::unique_ptr<FakeStatsEventDelegate>(mDelegate),
1471 std::nullopt, 1);
1472 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1473
1474 mTimeStats->onBootFinished();
1475
1476 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1477 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1478 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 3, 4000000);
1479 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 4, 5000000);
1480
1481 EXPECT_THAT(mDelegate->mAtomTags,
1482 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1483 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1484 EXPECT_NE(nullptr, mDelegate->mCallback);
1485 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1486
1487 EXPECT_THAT(mDelegate->mAtomTags,
1488 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1489 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1490 std::string expectedPresentToPresent = buildExpectedHistogramBytestring({1}, {2});
1491 {
1492 InSequence seq;
1493 EXPECT_CALL(*mDelegate,
1494 statsEventWriteByteArray(mDelegate->mEvent,
1495 BytesEq((const uint8_t*)
1496 expectedPresentToPresent.c_str(),
1497 expectedPresentToPresent.size()),
1498 expectedPresentToPresent.size()));
1499 EXPECT_CALL(*mDelegate, statsEventWriteByteArray(mDelegate->mEvent, _, _))
1500 .Times(AnyNumber());
1501 }
Tej Singh2a457b62020-01-31 16:16:10 -08001502 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
Alec Mouri37384342020-01-02 17:23:37 -08001503 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
1504 mDelegate->mCookie));
1505}
1506
1507TEST_F(TimeStatsTest, layerStatsCallback_limitsLayers) {
1508 mDelegate = new FakeStatsEventDelegate;
1509 mTimeStats =
1510 std::make_unique<impl::TimeStats>(std::unique_ptr<FakeStatsEventDelegate>(mDelegate), 1,
1511 std::nullopt);
1512 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1513
1514 mTimeStats->onBootFinished();
1515
1516 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
1517 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
1518 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 1, 2000000);
1519 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 2, 3000000);
1520 insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_1, 4, 5000000);
1521
1522 EXPECT_THAT(mDelegate->mAtomTags,
1523 UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
1524 android::util::SURFACEFLINGER_STATS_LAYER_INFO));
1525 EXPECT_NE(nullptr, mDelegate->mCallback);
1526 EXPECT_EQ(mTimeStats.get(), mDelegate->mCookie);
1527
1528 EXPECT_CALL(*mDelegate,
1529 statsEventSetAtomId(mDelegate->mEvent,
1530 android::util::SURFACEFLINGER_STATS_LAYER_INFO))
1531 .Times(1);
1532 EXPECT_CALL(*mDelegate,
1533 statsEventWriteString8(mDelegate->mEvent, StrEq(genLayerName(LAYER_ID_1).c_str())));
Tej Singh2a457b62020-01-31 16:16:10 -08001534 EXPECT_EQ(AStatsManager_PULL_SUCCESS,
Alec Mouri37384342020-01-02 17:23:37 -08001535 mDelegate->makePullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
1536 mDelegate->mCookie));
1537}
1538
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001539TEST_F(TimeStatsTest, canSurviveMonkey) {
Lloyd Pique067fe1e2018-12-06 19:44:13 -08001540 if (g_noSlowTests) {
1541 GTEST_SKIP();
1542 }
1543
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001544 EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
1545
1546 for (size_t i = 0; i < 10000000; ++i) {
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001547 const int32_t layerId = genRandomInt32(-1, 10);
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001548 const int32_t frameNumber = genRandomInt32(1, 10);
1549 switch (genRandomInt32(0, 100)) {
1550 case 0:
1551 ALOGV("removeTimeRecord");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001552 ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001553 continue;
1554 case 1:
1555 ALOGV("onDestroy");
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001556 ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId));
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001557 continue;
1558 }
1559 TimeStamp type = static_cast<TimeStamp>(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END));
1560 const int32_t ts = genRandomInt32(1, 1000000000);
Yiwei Zhang1a88c402019-11-18 10:43:58 -08001561 ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts);
Ady Abraham8b9e6122021-01-26 19:11:45 -08001562 setTimeStamp(type, layerId, frameNumber, ts, {});
Yiwei Zhang16faa5d2018-11-13 18:12:59 -08001563 }
1564}
1565
1566} // namespace
1567} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08001568
1569// TODO(b/129481165): remove the #pragma below and fix conversion issues
Marin Shalamanovbed7fd32020-12-21 20:02:20 +01001570#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"