blob: 2941a14ef9ebb9f4ca47464d6bb92947aebaaf49 [file] [log] [blame]
Pascal Mütschardd56514e2024-05-24 17:37:13 +02001/*
2 * Copyright 2024 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
17#include <android/gui/BnJankListener.h>
18#include <binder/IInterface.h>
19#include "BackgroundExecutor.h"
20#include "Jank/JankTracker.h"
21
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24
25namespace android {
26
27namespace {
28
29using namespace testing;
30
31class MockJankListener : public gui::BnJankListener {
32public:
33 MockJankListener() = default;
34 ~MockJankListener() override = default;
35
36 MOCK_METHOD(binder::Status, onJankData, (const std::vector<gui::JankData>& jankData),
37 (override));
38};
39
40} // anonymous namespace
41
42class JankTrackerTest : public Test {
43public:
44 JankTrackerTest() {}
45
46 void SetUp() override { mListener = sp<StrictMock<MockJankListener>>::make(); }
47
48 void addJankListener(int32_t layerId) {
49 JankTracker::addJankListener(layerId, IInterface::asBinder(mListener));
50 }
51
52 void removeJankListener(int32_t layerId, int64_t after) {
53 JankTracker::removeJankListener(layerId, IInterface::asBinder(mListener), after);
54 }
55
56 void addJankData(int32_t layerId, int jankType) {
57 gui::JankData data;
58 data.frameVsyncId = mVsyncId++;
59 data.jankType = jankType;
60 data.frameIntervalNs = 8333333;
61 JankTracker::onJankData(layerId, data);
62 }
63
64 void flushBackgroundThread() { BackgroundExecutor::getLowPriorityInstance().flushQueue(); }
65
66 size_t listenerCount() { return JankTracker::sListenerCount; }
67
68 std::vector<gui::JankData> getCollectedJankData(int32_t layerId) {
69 return JankTracker::getCollectedJankDataForTesting(layerId);
70 }
71
72 sp<StrictMock<MockJankListener>> mListener = nullptr;
73 int64_t mVsyncId = 1000;
74};
75
76TEST_F(JankTrackerTest, jankDataIsTrackedAndPropagated) {
77 ASSERT_EQ(listenerCount(), 0u);
78
79 EXPECT_CALL(*mListener.get(), onJankData(SizeIs(3)))
80 .WillOnce([](const std::vector<gui::JankData>& jankData) {
81 EXPECT_EQ(jankData[0].frameVsyncId, 1000);
82 EXPECT_EQ(jankData[0].jankType, 1);
83 EXPECT_EQ(jankData[0].frameIntervalNs, 8333333);
84
85 EXPECT_EQ(jankData[1].frameVsyncId, 1001);
86 EXPECT_EQ(jankData[1].jankType, 2);
87 EXPECT_EQ(jankData[1].frameIntervalNs, 8333333);
88
89 EXPECT_EQ(jankData[2].frameVsyncId, 1002);
90 EXPECT_EQ(jankData[2].jankType, 3);
91 EXPECT_EQ(jankData[2].frameIntervalNs, 8333333);
92 return binder::Status::ok();
93 });
94 EXPECT_CALL(*mListener.get(), onJankData(SizeIs(2)))
95 .WillOnce([](const std::vector<gui::JankData>& jankData) {
96 EXPECT_EQ(jankData[0].frameVsyncId, 1003);
97 EXPECT_EQ(jankData[0].jankType, 4);
98 EXPECT_EQ(jankData[0].frameIntervalNs, 8333333);
99
100 EXPECT_EQ(jankData[1].frameVsyncId, 1004);
101 EXPECT_EQ(jankData[1].jankType, 5);
102 EXPECT_EQ(jankData[1].frameIntervalNs, 8333333);
103
104 return binder::Status::ok();
105 });
106
107 addJankListener(123);
108 addJankData(123, 1);
109 addJankData(123, 2);
110 addJankData(123, 3);
111 JankTracker::flushJankData(123);
112 addJankData(123, 4);
113 removeJankListener(123, mVsyncId);
114 addJankData(123, 5);
115 JankTracker::flushJankData(123);
116 addJankData(123, 6);
117 JankTracker::flushJankData(123);
118 removeJankListener(123, 0);
119
120 flushBackgroundThread();
121}
122
123TEST_F(JankTrackerTest, jankDataIsAutomaticallyFlushedInBatches) {
124 ASSERT_EQ(listenerCount(), 0u);
125
126 // needs to be larger than kJankDataBatchSize in JankTracker.cpp.
127 constexpr size_t kNumberOfJankDataToSend = 234;
128
129 size_t jankDataReceived = 0;
130 size_t numBatchesReceived = 0;
131
132 EXPECT_CALL(*mListener.get(), onJankData(_))
133 .WillRepeatedly([&](const std::vector<gui::JankData>& jankData) {
134 jankDataReceived += jankData.size();
135 numBatchesReceived++;
136 return binder::Status::ok();
137 });
138
139 addJankListener(123);
140 for (size_t i = 0; i < kNumberOfJankDataToSend; i++) {
141 addJankData(123, 0);
142 }
143
144 flushBackgroundThread();
145 // Check that we got some data, without explicitly flushing.
146 EXPECT_GT(jankDataReceived, 0u);
147 EXPECT_GT(numBatchesReceived, 0u);
148 EXPECT_LT(numBatchesReceived, jankDataReceived); // batches should be > size 1.
149
150 removeJankListener(123, 0);
151 JankTracker::flushJankData(123);
152 flushBackgroundThread();
153 EXPECT_EQ(jankDataReceived, kNumberOfJankDataToSend);
154}
155
156TEST_F(JankTrackerTest, jankListenerIsRemovedWhenReturningNullError) {
157 ASSERT_EQ(listenerCount(), 0u);
158
159 EXPECT_CALL(*mListener.get(), onJankData(SizeIs(3)))
160 .WillOnce(Return(binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER)));
161
162 addJankListener(123);
163 addJankData(123, 1);
164 addJankData(123, 2);
165 addJankData(123, 3);
166 JankTracker::flushJankData(123);
167 addJankData(123, 4);
168 addJankData(123, 5);
169 JankTracker::flushJankData(123);
170 flushBackgroundThread();
171
172 EXPECT_EQ(listenerCount(), 0u);
173}
174
175TEST_F(JankTrackerTest, jankDataIsDroppedIfNobodyIsListening) {
176 ASSERT_EQ(listenerCount(), 0u);
177
178 addJankData(123, 1);
179 addJankData(123, 2);
180 addJankData(123, 3);
181 flushBackgroundThread();
182
183 EXPECT_EQ(getCollectedJankData(123).size(), 0u);
184}
185
186TEST_F(JankTrackerTest, listenerCountTracksRegistrations) {
187 ASSERT_EQ(listenerCount(), 0u);
188
189 addJankListener(123);
190 addJankListener(456);
191 flushBackgroundThread();
192 EXPECT_EQ(listenerCount(), 2u);
193
194 removeJankListener(123, 0);
195 JankTracker::flushJankData(123);
196 removeJankListener(456, 0);
197 JankTracker::flushJankData(456);
198 flushBackgroundThread();
199 EXPECT_EQ(listenerCount(), 0u);
200}
201
202TEST_F(JankTrackerTest, listenerCountIsAccurateOnDuplicateRegistration) {
203 ASSERT_EQ(listenerCount(), 0u);
204
205 addJankListener(123);
206 addJankListener(123);
207 flushBackgroundThread();
208 EXPECT_EQ(listenerCount(), 1u);
209
210 removeJankListener(123, 0);
211 JankTracker::flushJankData(123);
212 flushBackgroundThread();
213 EXPECT_EQ(listenerCount(), 0u);
214}
215
216} // namespace android