• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
25 namespace android {
26 
27 namespace {
28 
29 using namespace testing;
30 
31 class MockJankListener : public gui::BnJankListener {
32 public:
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 
42 class JankTrackerTest : public Test {
43 public:
JankTrackerTest()44     JankTrackerTest() {}
45 
SetUp()46     void SetUp() override { mListener = sp<StrictMock<MockJankListener>>::make(); }
47 
addJankListener(int32_t layerId)48     void addJankListener(int32_t layerId) {
49         JankTracker::addJankListener(layerId, IInterface::asBinder(mListener));
50     }
51 
removeJankListener(int32_t layerId,int64_t after)52     void removeJankListener(int32_t layerId, int64_t after) {
53         JankTracker::removeJankListener(layerId, IInterface::asBinder(mListener), after);
54     }
55 
addJankData(int32_t layerId,int jankType)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 
flushBackgroundThread()64     void flushBackgroundThread() { BackgroundExecutor::getLowPriorityInstance().flushQueue(); }
65 
listenerCount()66     size_t listenerCount() { return JankTracker::sListenerCount; }
67 
getCollectedJankData(int32_t layerId)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 
TEST_F(JankTrackerTest,jankDataIsTrackedAndPropagated)76 TEST_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 
TEST_F(JankTrackerTest,jankDataIsAutomaticallyFlushedInBatches)123 TEST_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 
TEST_F(JankTrackerTest,jankListenerIsRemovedWhenReturningNullError)156 TEST_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 
TEST_F(JankTrackerTest,jankDataIsDroppedIfNobodyIsListening)175 TEST_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 
TEST_F(JankTrackerTest,listenerCountTracksRegistrations)186 TEST_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 
TEST_F(JankTrackerTest,listenerCountIsAccurateOnDuplicateRegistration)202 TEST_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 
TEST_F(JankTrackerTest,multipleLayersAreTrackedIndependently)216 TEST_F(JankTrackerTest, multipleLayersAreTrackedIndependently) {
217     size_t jankDataReceived = 0;
218     size_t numBatchesReceived = 0;
219 
220     EXPECT_CALL(*mListener.get(), onJankData(_))
221             .WillRepeatedly([&](const std::vector<gui::JankData>& jankData) {
222                 jankDataReceived += jankData.size();
223                 numBatchesReceived++;
224                 return binder::Status::ok();
225             });
226     addJankListener(123);
227     addJankListener(321);
228     addJankData(123, 1);
229     addJankData(123, 2);
230     addJankData(123, 3);
231     addJankData(321, 4);
232     addJankData(321, 5);
233 
234     JankTracker::flushJankData(123);
235     flushBackgroundThread();
236     EXPECT_EQ(numBatchesReceived, 1u);
237     EXPECT_EQ(jankDataReceived, 3u);
238 
239     JankTracker::flushJankData(321);
240     flushBackgroundThread();
241     EXPECT_EQ(numBatchesReceived, 2u);
242     EXPECT_EQ(jankDataReceived, 5u);
243 }
244 
245 } // namespace android
246