• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 
17 #undef LOG_TAG
18 #define LOG_TAG "LibSurfaceFlingerUnittests"
19 
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <log/log.h>
24 
25 #include <utils/Errors.h>
26 
27 #include "AsyncCallRecorder.h"
28 #include "EventThread.h"
29 
30 using namespace std::chrono_literals;
31 using namespace std::placeholders;
32 
33 using testing::_;
34 using testing::Invoke;
35 
36 namespace android {
37 namespace {
38 
39 class MockVSyncSource : public VSyncSource {
40 public:
41     MOCK_METHOD1(setVSyncEnabled, void(bool));
42     MOCK_METHOD1(setCallback, void(VSyncSource::Callback*));
43     MOCK_METHOD1(setPhaseOffset, void(nsecs_t));
44 };
45 
46 } // namespace
47 
48 class EventThreadTest : public testing::Test {
49 protected:
50     class MockEventThreadConnection : public android::impl::EventThread::Connection {
51     public:
MockEventThreadConnection(android::impl::EventThread * eventThread)52         explicit MockEventThreadConnection(android::impl::EventThread* eventThread)
53               : android::impl::EventThread::Connection(eventThread) {}
54         MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
55     };
56 
57     using ConnectionEventRecorder =
58             AsyncCallRecorderWithCannedReturn<status_t (*)(const DisplayEventReceiver::Event&)>;
59 
60     EventThreadTest();
61     ~EventThreadTest() override;
62 
63     void createThread();
64     sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder);
65 
66     void expectVSyncSetEnabledCallReceived(bool expectedState);
67     void expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset);
68     VSyncSource::Callback* expectVSyncSetCallbackCallReceived();
69     void expectInterceptCallReceived(nsecs_t expectedTimestamp);
70     void expectVsyncEventReceivedByConnection(const char* name,
71                                               ConnectionEventRecorder& connectionEventRecorder,
72                                               nsecs_t expectedTimestamp, unsigned expectedCount);
73     void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
74     void expectHotplugEventReceivedByConnection(int expectedDisplayType, bool expectedConnected);
75 
76     AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
77     AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
78     AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
79     AsyncCallRecorder<void (*)()> mResyncCallRecorder;
80     AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
81     ConnectionEventRecorder mConnectionEventCallRecorder{0};
82 
83     MockVSyncSource mVSyncSource;
84     std::unique_ptr<android::impl::EventThread> mThread;
85     sp<MockEventThreadConnection> mConnection;
86 };
87 
EventThreadTest()88 EventThreadTest::EventThreadTest() {
89     const ::testing::TestInfo* const test_info =
90             ::testing::UnitTest::GetInstance()->current_test_info();
91     ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
92 
93     EXPECT_CALL(mVSyncSource, setVSyncEnabled(_))
94             .WillRepeatedly(Invoke(mVSyncSetEnabledCallRecorder.getInvocable()));
95 
96     EXPECT_CALL(mVSyncSource, setCallback(_))
97             .WillRepeatedly(Invoke(mVSyncSetCallbackCallRecorder.getInvocable()));
98 
99     EXPECT_CALL(mVSyncSource, setPhaseOffset(_))
100             .WillRepeatedly(Invoke(mVSyncSetPhaseOffsetCallRecorder.getInvocable()));
101 
102     createThread();
103     mConnection = createConnection(mConnectionEventCallRecorder);
104 }
105 
~EventThreadTest()106 EventThreadTest::~EventThreadTest() {
107     const ::testing::TestInfo* const test_info =
108             ::testing::UnitTest::GetInstance()->current_test_info();
109     ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
110 }
111 
createThread()112 void EventThreadTest::createThread() {
113     mThread =
114             std::make_unique<android::impl::EventThread>(&mVSyncSource,
115                                                          mResyncCallRecorder.getInvocable(),
116                                                          mInterceptVSyncCallRecorder.getInvocable(),
117                                                          "unit-test-event-thread");
118 }
119 
createConnection(ConnectionEventRecorder & recorder)120 sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
121         ConnectionEventRecorder& recorder) {
122     sp<MockEventThreadConnection> connection = new MockEventThreadConnection(mThread.get());
123     EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
124     return connection;
125 }
126 
expectVSyncSetEnabledCallReceived(bool expectedState)127 void EventThreadTest::expectVSyncSetEnabledCallReceived(bool expectedState) {
128     auto args = mVSyncSetEnabledCallRecorder.waitForCall();
129     ASSERT_TRUE(args.has_value());
130     EXPECT_EQ(expectedState, std::get<0>(args.value()));
131 }
132 
expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset)133 void EventThreadTest::expectVSyncSetPhaseOffsetCallReceived(nsecs_t expectedPhaseOffset) {
134     auto args = mVSyncSetPhaseOffsetCallRecorder.waitForCall();
135     ASSERT_TRUE(args.has_value());
136     EXPECT_EQ(expectedPhaseOffset, std::get<0>(args.value()));
137 }
138 
expectVSyncSetCallbackCallReceived()139 VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() {
140     auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall();
141     return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr;
142 }
143 
expectInterceptCallReceived(nsecs_t expectedTimestamp)144 void EventThreadTest::expectInterceptCallReceived(nsecs_t expectedTimestamp) {
145     auto args = mInterceptVSyncCallRecorder.waitForCall();
146     ASSERT_TRUE(args.has_value());
147     EXPECT_EQ(expectedTimestamp, std::get<0>(args.value()));
148 }
149 
expectVsyncEventReceivedByConnection(const char * name,ConnectionEventRecorder & connectionEventRecorder,nsecs_t expectedTimestamp,unsigned expectedCount)150 void EventThreadTest::expectVsyncEventReceivedByConnection(
151         const char* name, ConnectionEventRecorder& connectionEventRecorder,
152         nsecs_t expectedTimestamp, unsigned expectedCount) {
153     auto args = connectionEventRecorder.waitForCall();
154     ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp "
155                                   << expectedTimestamp;
156     const auto& event = std::get<0>(args.value());
157     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type)
158             << name << " did not get the correct event for timestamp " << expectedTimestamp;
159     EXPECT_EQ(expectedTimestamp, event.header.timestamp)
160             << name << " did not get the expected timestamp for timestamp " << expectedTimestamp;
161     EXPECT_EQ(expectedCount, event.vsync.count)
162             << name << " did not get the expected count for timestamp " << expectedTimestamp;
163 }
164 
expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,unsigned expectedCount)165 void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp,
166                                                            unsigned expectedCount) {
167     expectVsyncEventReceivedByConnection("mConnectionEventCallRecorder",
168                                          mConnectionEventCallRecorder, expectedTimestamp,
169                                          expectedCount);
170 }
171 
expectHotplugEventReceivedByConnection(int expectedDisplayType,bool expectedConnected)172 void EventThreadTest::expectHotplugEventReceivedByConnection(int expectedDisplayType,
173                                                              bool expectedConnected) {
174     auto args = mConnectionEventCallRecorder.waitForCall();
175     ASSERT_TRUE(args.has_value());
176     const auto& event = std::get<0>(args.value());
177     EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
178     EXPECT_EQ(static_cast<unsigned>(expectedDisplayType), event.header.id);
179     EXPECT_EQ(expectedConnected, event.hotplug.connected);
180 }
181 
182 namespace {
183 
184 /* ------------------------------------------------------------------------
185  * Test cases
186  */
187 
TEST_F(EventThreadTest,canCreateAndDestroyThreadWithNoEventsSent)188 TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) {
189     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
190     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
191     EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
192     EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
193     EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
194     EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
195 }
196 
TEST_F(EventThreadTest,requestNextVsyncPostsASingleVSyncEventToTheConnection)197 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
198     // Signal that we want the next vsync event to be posted to the connection
199     mThread->requestNextVsync(mConnection);
200 
201     // EventThread should immediately request a resync.
202     EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
203 
204     // EventThread should enable vsync callbacks, and set a callback interface
205     // pointer to use them with the VSync source.
206     expectVSyncSetEnabledCallReceived(true);
207     auto callback = expectVSyncSetCallbackCallReceived();
208     ASSERT_TRUE(callback);
209 
210     // Use the received callback to signal a first vsync event.
211     // The interceptor should receive the event, as well as the connection.
212     callback->onVSyncEvent(123);
213     expectInterceptCallReceived(123);
214     expectVsyncEventReceivedByConnection(123, 1u);
215 
216     // Use the received callback to signal a second vsync event.
217     // The interceptor should receive the event, but the the connection should
218     // not as it was only interested in the first.
219     callback->onVSyncEvent(456);
220     expectInterceptCallReceived(456);
221     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
222 
223     // EventThread should also detect that at this point that it does not need
224     // any more vsync events, and should disable their generation.
225     expectVSyncSetEnabledCallReceived(false);
226 }
227 
TEST_F(EventThreadTest,setVsyncRateZeroPostsNoVSyncEventsToThatConnection)228 TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) {
229     // Create a first connection, register it, and request a vsync rate of zero.
230     ConnectionEventRecorder firstConnectionEventRecorder{0};
231     sp<MockEventThreadConnection> firstConnection = createConnection(firstConnectionEventRecorder);
232     mThread->setVsyncRate(0, firstConnection);
233 
234     // By itself, this should not enable vsync events
235     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
236     EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
237 
238     // However if there is another connection which wants events at a nonzero rate.....
239     ConnectionEventRecorder secondConnectionEventRecorder{0};
240     sp<MockEventThreadConnection> secondConnection =
241             createConnection(secondConnectionEventRecorder);
242     mThread->setVsyncRate(1, secondConnection);
243 
244     // EventThread should enable vsync callbacks, and set a callback interface
245     // pointer to use them with the VSync source.
246     expectVSyncSetEnabledCallReceived(true);
247     auto callback = expectVSyncSetCallbackCallReceived();
248     ASSERT_TRUE(callback);
249 
250     // Send a vsync event. EventThread should then make a call to the
251     // interceptor, and the second connection. The first connection should not
252     // get the event.
253     callback->onVSyncEvent(123);
254     expectInterceptCallReceived(123);
255     EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value());
256     expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123,
257                                          1u);
258 }
259 
TEST_F(EventThreadTest,setVsyncRateOnePostsAllEventsToThatConnection)260 TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) {
261     mThread->setVsyncRate(1, mConnection);
262 
263     // EventThread should enable vsync callbacks, and set a callback interface
264     // pointer to use them with the VSync source.
265     expectVSyncSetEnabledCallReceived(true);
266     auto callback = expectVSyncSetCallbackCallReceived();
267     ASSERT_TRUE(callback);
268 
269     // Send a vsync event. EventThread should then make a call to the
270     // interceptor, and the connection.
271     callback->onVSyncEvent(123);
272     expectInterceptCallReceived(123);
273     expectVsyncEventReceivedByConnection(123, 1u);
274 
275     // A second event should go to the same places.
276     callback->onVSyncEvent(456);
277     expectInterceptCallReceived(456);
278     expectVsyncEventReceivedByConnection(456, 2u);
279 
280     // A third event should go to the same places.
281     callback->onVSyncEvent(789);
282     expectInterceptCallReceived(789);
283     expectVsyncEventReceivedByConnection(789, 3u);
284 }
285 
TEST_F(EventThreadTest,setVsyncRateTwoPostsEveryOtherEventToThatConnection)286 TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) {
287     mThread->setVsyncRate(2, mConnection);
288 
289     // EventThread should enable vsync callbacks, and set a callback interface
290     // pointer to use them with the VSync source.
291     expectVSyncSetEnabledCallReceived(true);
292     auto callback = expectVSyncSetCallbackCallReceived();
293     ASSERT_TRUE(callback);
294 
295     // The first event will be seen by the interceptor, and not the connection.
296     callback->onVSyncEvent(123);
297     expectInterceptCallReceived(123);
298     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
299 
300     // The second event will be seen by the interceptor and the connection.
301     callback->onVSyncEvent(456);
302     expectInterceptCallReceived(456);
303     expectVsyncEventReceivedByConnection(456, 2u);
304 
305     // The third event will be seen by the interceptor, and not the connection.
306     callback->onVSyncEvent(789);
307     expectInterceptCallReceived(789);
308     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
309 
310     // The fourth event will be seen by the interceptor and the connection.
311     callback->onVSyncEvent(101112);
312     expectInterceptCallReceived(101112);
313     expectVsyncEventReceivedByConnection(101112, 4u);
314 }
315 
TEST_F(EventThreadTest,connectionsRemovedIfInstanceDestroyed)316 TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) {
317     mThread->setVsyncRate(1, mConnection);
318 
319     // EventThread should enable vsync callbacks, and set a callback interface
320     // pointer to use them with the VSync source.
321     expectVSyncSetEnabledCallReceived(true);
322     auto callback = expectVSyncSetCallbackCallReceived();
323     ASSERT_TRUE(callback);
324 
325     // Destroy the only (strong) reference to the connection.
326     mConnection = nullptr;
327 
328     // The first event will be seen by the interceptor, and not the connection.
329     callback->onVSyncEvent(123);
330     expectInterceptCallReceived(123);
331     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
332 
333     // EventThread should disable vsync callbacks
334     expectVSyncSetEnabledCallReceived(false);
335 }
336 
TEST_F(EventThreadTest,connectionsRemovedIfEventDeliveryError)337 TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) {
338     ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY};
339     sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
340     mThread->setVsyncRate(1, errorConnection);
341 
342     // EventThread should enable vsync callbacks, and set a callback interface
343     // pointer to use them with the VSync source.
344     expectVSyncSetEnabledCallReceived(true);
345     auto callback = expectVSyncSetCallbackCallReceived();
346     ASSERT_TRUE(callback);
347 
348     // The first event will be seen by the interceptor, and by the connection,
349     // which then returns an error.
350     callback->onVSyncEvent(123);
351     expectInterceptCallReceived(123);
352     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
353 
354     // A subsequent event will be seen by the interceptor and not by the
355     // connection.
356     callback->onVSyncEvent(456);
357     expectInterceptCallReceived(456);
358     EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value());
359 
360     // EventThread should disable vsync callbacks with the second event
361     expectVSyncSetEnabledCallReceived(false);
362 }
363 
TEST_F(EventThreadTest,eventsDroppedIfNonfatalEventDeliveryError)364 TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) {
365     ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK};
366     sp<MockEventThreadConnection> errorConnection = createConnection(errorConnectionEventRecorder);
367     mThread->setVsyncRate(1, errorConnection);
368 
369     // EventThread should enable vsync callbacks, and set a callback interface
370     // pointer to use them with the VSync source.
371     expectVSyncSetEnabledCallReceived(true);
372     auto callback = expectVSyncSetCallbackCallReceived();
373     ASSERT_TRUE(callback);
374 
375     // The first event will be seen by the interceptor, and by the connection,
376     // which then returns an non-fatal error.
377     callback->onVSyncEvent(123);
378     expectInterceptCallReceived(123);
379     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u);
380 
381     // A subsequent event will be seen by the interceptor, and by the connection,
382     // which still then returns an non-fatal error.
383     callback->onVSyncEvent(456);
384     expectInterceptCallReceived(456);
385     expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u);
386 
387     // EventThread will not disable vsync callbacks as the errors are non-fatal.
388     EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value());
389 }
390 
TEST_F(EventThreadTest,setPhaseOffsetForwardsToVSyncSource)391 TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) {
392     mThread->setPhaseOffset(321);
393     expectVSyncSetPhaseOffsetCallReceived(321);
394 }
395 
TEST_F(EventThreadTest,postHotplugPrimaryDisconnect)396 TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) {
397     mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, false);
398     expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, false);
399 }
400 
TEST_F(EventThreadTest,postHotplugPrimaryConnect)401 TEST_F(EventThreadTest, postHotplugPrimaryConnect) {
402     mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true);
403     expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, true);
404 }
405 
TEST_F(EventThreadTest,postHotplugExternalDisconnect)406 TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
407     mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, false);
408     expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, false);
409 }
410 
TEST_F(EventThreadTest,postHotplugExternalConnect)411 TEST_F(EventThreadTest, postHotplugExternalConnect) {
412     mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, true);
413     expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, true);
414 }
415 
TEST_F(EventThreadTest,postHotplugVirtualDisconnectIsFilteredOut)416 TEST_F(EventThreadTest, postHotplugVirtualDisconnectIsFilteredOut) {
417     mThread->onHotplugReceived(DisplayDevice::DISPLAY_VIRTUAL, false);
418     EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
419 }
420 
421 } // namespace
422 } // namespace android
423