/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #include #include #include #include #include "AsyncCallRecorder.h" #include "DisplayHardware/DisplayMode.h" #include "Scheduler/EventThread.h" using namespace std::chrono_literals; using namespace std::placeholders; using namespace android::flag_operators; using testing::_; using testing::Invoke; namespace android { namespace { constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID(111); constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID(222); constexpr PhysicalDisplayId DISPLAY_ID_64BIT(0xabcd12349876fedcULL); constexpr std::chrono::duration VSYNC_PERIOD(16ms); class MockVSyncSource : public VSyncSource { public: const char* getName() const override { return "test"; } MOCK_METHOD1(setVSyncEnabled, void(bool)); MOCK_METHOD1(setCallback, void(VSyncSource::Callback*)); MOCK_METHOD2(setDuration, void(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration)); MOCK_METHOD1(pauseVsyncCallback, void(bool)); MOCK_CONST_METHOD1(dump, void(std::string&)); }; } // namespace class EventThreadTest : public testing::Test { protected: class MockEventThreadConnection : public EventThreadConnection { public: MockEventThreadConnection(impl::EventThread* eventThread, uid_t callingUid, ResyncCallback&& resyncCallback, ISurfaceComposer::EventRegistrationFlags eventRegistration) : EventThreadConnection(eventThread, callingUid, std::move(resyncCallback), eventRegistration) {} MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event)); }; using ConnectionEventRecorder = AsyncCallRecorderWithCannedReturn; EventThreadTest(); ~EventThreadTest() override; void createThread(std::unique_ptr); sp createConnection( ConnectionEventRecorder& recorder, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}, uid_t ownerUid = mConnectionUid); void expectVSyncSetEnabledCallReceived(bool expectedState); void expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration, std::chrono::nanoseconds expectedReadyDuration); VSyncSource::Callback* expectVSyncSetCallbackCallReceived(); void expectInterceptCallReceived(nsecs_t expectedTimestamp); void expectVsyncEventReceivedByConnection(const char* name, ConnectionEventRecorder& connectionEventRecorder, nsecs_t expectedTimestamp, unsigned expectedCount); void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount); void expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, bool expectedConnected); void expectConfigChangedEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId, nsecs_t expectedVsyncPeriod); void expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t); void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, std::vector); AsyncCallRecorder mVSyncSetEnabledCallRecorder; AsyncCallRecorder mVSyncSetCallbackCallRecorder; AsyncCallRecorder mVSyncSetDurationCallRecorder; AsyncCallRecorder mResyncCallRecorder; AsyncCallRecorder mInterceptVSyncCallRecorder; AsyncCallRecorder mThrottleVsyncCallRecorder; ConnectionEventRecorder mConnectionEventCallRecorder{0}; ConnectionEventRecorder mThrottledConnectionEventCallRecorder{0}; MockVSyncSource* mVSyncSource; VSyncSource::Callback* mCallback = nullptr; std::unique_ptr mThread; sp mConnection; sp mThrottledConnection; static constexpr uid_t mConnectionUid = 443; static constexpr uid_t mThrottledConnectionUid = 177; }; EventThreadTest::EventThreadTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); auto vsyncSource = std::make_unique(); mVSyncSource = vsyncSource.get(); EXPECT_CALL(*mVSyncSource, setVSyncEnabled(_)) .WillRepeatedly(Invoke(mVSyncSetEnabledCallRecorder.getInvocable())); EXPECT_CALL(*mVSyncSource, setCallback(_)) .WillRepeatedly(Invoke(mVSyncSetCallbackCallRecorder.getInvocable())); EXPECT_CALL(*mVSyncSource, setDuration(_, _)) .WillRepeatedly(Invoke(mVSyncSetDurationCallRecorder.getInvocable())); createThread(std::move(vsyncSource)); mConnection = createConnection(mConnectionEventCallRecorder, ISurfaceComposer::EventRegistration::modeChanged | ISurfaceComposer::EventRegistration::frameRateOverride); mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder, ISurfaceComposer::EventRegistration::modeChanged, mThrottledConnectionUid); // A display must be connected for VSYNC events to be delivered. mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true); expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true); } EventThreadTest::~EventThreadTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); // EventThread should unregister itself as VSyncSource callback. EXPECT_TRUE(!mVSyncSetCallbackCallRecorder.waitForUnexpectedCall().has_value()); } void EventThreadTest::createThread(std::unique_ptr source) { const auto throttleVsync = [&](nsecs_t expectedVsyncTimestamp, uid_t uid) { mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTimestamp, uid); return (uid == mThrottledConnectionUid); }; const auto getVsyncPeriod = [](uid_t uid) { return VSYNC_PERIOD.count(); }; mThread = std::make_unique(std::move(source), /*tokenManager=*/nullptr, mInterceptVSyncCallRecorder.getInvocable(), throttleVsync, getVsyncPeriod); // EventThread should register itself as VSyncSource callback. mCallback = expectVSyncSetCallbackCallReceived(); ASSERT_TRUE(mCallback); } sp EventThreadTest::createConnection( ConnectionEventRecorder& recorder, ISurfaceComposer::EventRegistrationFlags eventRegistration, uid_t ownerUid) { sp connection = new MockEventThreadConnection(mThread.get(), ownerUid, mResyncCallRecorder.getInvocable(), eventRegistration); EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable())); return connection; } void EventThreadTest::expectVSyncSetEnabledCallReceived(bool expectedState) { auto args = mVSyncSetEnabledCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); EXPECT_EQ(expectedState, std::get<0>(args.value())); } void EventThreadTest::expectVSyncSetDurationCallReceived( std::chrono::nanoseconds expectedDuration, std::chrono::nanoseconds expectedReadyDuration) { auto args = mVSyncSetDurationCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); EXPECT_EQ(expectedDuration, std::get<0>(args.value())); EXPECT_EQ(expectedReadyDuration, std::get<1>(args.value())); } VSyncSource::Callback* EventThreadTest::expectVSyncSetCallbackCallReceived() { auto callbackSet = mVSyncSetCallbackCallRecorder.waitForCall(); return callbackSet.has_value() ? std::get<0>(callbackSet.value()) : nullptr; } void EventThreadTest::expectInterceptCallReceived(nsecs_t expectedTimestamp) { auto args = mInterceptVSyncCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); EXPECT_EQ(expectedTimestamp, std::get<0>(args.value())); } void EventThreadTest::expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t uid) { auto args = mThrottleVsyncCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); EXPECT_EQ(expectedTimestamp, std::get<0>(args.value())); EXPECT_EQ(uid, std::get<1>(args.value())); } void EventThreadTest::expectVsyncEventReceivedByConnection( const char* name, ConnectionEventRecorder& connectionEventRecorder, nsecs_t expectedTimestamp, unsigned expectedCount) { auto args = connectionEventRecorder.waitForCall(); ASSERT_TRUE(args.has_value()) << name << " did not receive an event for timestamp " << expectedTimestamp; const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_VSYNC, event.header.type) << name << " did not get the correct event for timestamp " << expectedTimestamp; EXPECT_EQ(expectedTimestamp, event.header.timestamp) << name << " did not get the expected timestamp for timestamp " << expectedTimestamp; EXPECT_EQ(expectedCount, event.vsync.count) << name << " did not get the expected count for timestamp " << expectedTimestamp; } void EventThreadTest::expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount) { expectVsyncEventReceivedByConnection("mConnectionEventCallRecorder", mConnectionEventCallRecorder, expectedTimestamp, expectedCount); } void EventThreadTest::expectHotplugEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, bool expectedConnected) { auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); EXPECT_EQ(expectedConnected, event.hotplug.connected); } void EventThreadTest::expectConfigChangedEventReceivedByConnection( PhysicalDisplayId expectedDisplayId, int32_t expectedConfigId, nsecs_t expectedVsyncPeriod) { auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); EXPECT_EQ(expectedConfigId, event.modeChange.modeId); EXPECT_EQ(expectedVsyncPeriod, event.modeChange.vsyncPeriod); } void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection( PhysicalDisplayId expectedDisplayId, std::vector expectedOverrides) { for (const auto [uid, frameRateHz] : expectedOverrides) { auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); EXPECT_EQ(uid, event.frameRateOverride.uid); EXPECT_EQ(frameRateHz, event.frameRateOverride.frameRateHz); } auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); } namespace { /* ------------------------------------------------------------------------ * Test cases */ TEST_F(EventThreadTest, canCreateAndDestroyThreadWithNoEventsSent) { EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mVSyncSetDurationCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value()); EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value()); } TEST_F(EventThreadTest, vsyncRequestIsIgnoredIfDisplayIsDisconnected) { mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false); expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false); // Signal that we want the next vsync event to be posted to the connection. mThread->requestNextVsync(mConnection); // EventThread should not enable vsync callbacks. EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); } TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { // Signal that we want the next vsync event to be posted to the connection mThread->requestNextVsync(mConnection); // EventThread should immediately request a resync. EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value()); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // Use the received callback to signal a first vsync event. // The interceptor should receive the event, as well as the connection. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectThrottleVsyncReceived(456, mConnectionUid); expectVsyncEventReceivedByConnection(123, 1u); // Use the received callback to signal a second vsync event. // The interceptor should receive the event, but the connection should // not as it was only interested in the first. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value()); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); // EventThread should also detect that at this point that it does not need // any more vsync events, and should disable their generation. expectVSyncSetEnabledCallReceived(false); } TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // Create a first connection, register it, and request a vsync rate of zero. ConnectionEventRecorder firstConnectionEventRecorder{0}; sp firstConnection = createConnection(firstConnectionEventRecorder); mThread->setVsyncRate(0, firstConnection); // By itself, this should not enable vsync events EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value()); // However if there is another connection which wants events at a nonzero rate..... ConnectionEventRecorder secondConnectionEventRecorder{0}; sp secondConnection = createConnection(secondConnectionEventRecorder); mThread->setVsyncRate(1, secondConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // Send a vsync event. EventThread should then make a call to the // interceptor, and the second connection. The first connection should not // get the event. mCallback->onVSyncEvent(123, 456, 0); expectInterceptCallReceived(123); EXPECT_FALSE(firstConnectionEventRecorder.waitForUnexpectedCall().has_value()); expectVsyncEventReceivedByConnection("secondConnection", secondConnectionEventRecorder, 123, 1u); } TEST_F(EventThreadTest, setVsyncRateOnePostsAllEventsToThatConnection) { mThread->setVsyncRate(1, mConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // Send a vsync event. EventThread should then make a call to the // interceptor, and the connection. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectThrottleVsyncReceived(456, mConnectionUid); expectVsyncEventReceivedByConnection(123, 1u); // A second event should go to the same places. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); expectThrottleVsyncReceived(123, mConnectionUid); expectVsyncEventReceivedByConnection(456, 2u); // A third event should go to the same places. mCallback->onVSyncEvent(789, 777, 111); expectInterceptCallReceived(789); expectThrottleVsyncReceived(777, mConnectionUid); expectVsyncEventReceivedByConnection(789, 3u); } TEST_F(EventThreadTest, setVsyncRateTwoPostsEveryOtherEventToThatConnection) { mThread->setVsyncRate(2, mConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // The first event will be seen by the interceptor, and not the connection. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value()); // The second event will be seen by the interceptor and the connection. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); expectVsyncEventReceivedByConnection(456, 2u); EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value()); // The third event will be seen by the interceptor, and not the connection. mCallback->onVSyncEvent(789, 777, 744); expectInterceptCallReceived(789); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); EXPECT_FALSE(mThrottleVsyncCallRecorder.waitForUnexpectedCall().has_value()); // The fourth event will be seen by the interceptor and the connection. mCallback->onVSyncEvent(101112, 7847, 86); expectInterceptCallReceived(101112); expectVsyncEventReceivedByConnection(101112, 4u); } TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) { mThread->setVsyncRate(1, mConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // Destroy the only (strong) reference to the connection. mConnection = nullptr; // The first event will be seen by the interceptor, and not the connection. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); // EventThread should disable vsync callbacks expectVSyncSetEnabledCallReceived(false); } TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) { ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY}; sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // The first event will be seen by the interceptor, and by the connection, // which then returns an error. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); // A subsequent event will be seen by the interceptor and not by the // connection. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); EXPECT_FALSE(errorConnectionEventRecorder.waitForUnexpectedCall().has_value()); // EventThread should disable vsync callbacks with the second event expectVSyncSetEnabledCallReceived(false); } TEST_F(EventThreadTest, tracksEventConnections) { EXPECT_EQ(2, mThread->getEventThreadConnectionCount()); ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY}; sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); EXPECT_EQ(3, mThread->getEventThreadConnectionCount()); ConnectionEventRecorder secondConnectionEventRecorder{0}; sp secondConnection = createConnection(secondConnectionEventRecorder); mThread->setVsyncRate(1, secondConnection); EXPECT_EQ(4, mThread->getEventThreadConnectionCount()); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // The first event will be seen by the interceptor, and by the connection, // which then returns an error. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); expectVsyncEventReceivedByConnection("successConnection", secondConnectionEventRecorder, 123, 1u); EXPECT_EQ(3, mThread->getEventThreadConnectionCount()); } TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) { ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK}; sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // The first event will be seen by the interceptor, and by the connection, // which then returns an non-fatal error. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 123, 1u); // A subsequent event will be seen by the interceptor, and by the connection, // which still then returns an non-fatal error. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); expectVsyncEventReceivedByConnection("errorConnection", errorConnectionEventRecorder, 456, 2u); // EventThread will not disable vsync callbacks as the errors are non-fatal. EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); } TEST_F(EventThreadTest, setPhaseOffsetForwardsToVSyncSource) { mThread->setDuration(321ns, 456ns); expectVSyncSetDurationCallReceived(321ns, 456ns); } TEST_F(EventThreadTest, postHotplugInternalDisconnect) { mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, false); expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, false); } TEST_F(EventThreadTest, postHotplugInternalConnect) { mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true); expectHotplugEventReceivedByConnection(INTERNAL_DISPLAY_ID, true); } TEST_F(EventThreadTest, postHotplugExternalDisconnect) { mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, false); expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, false); } TEST_F(EventThreadTest, postHotplugExternalConnect) { mThread->onHotplugReceived(EXTERNAL_DISPLAY_ID, true); expectHotplugEventReceivedByConnection(EXTERNAL_DISPLAY_ID, true); } TEST_F(EventThreadTest, postConfigChangedPrimary) { mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666); } TEST_F(EventThreadTest, postConfigChangedExternal) { mThread->onModeChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666); expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666); } TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { mThread->onModeChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666); expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666); } TEST_F(EventThreadTest, suppressConfigChanged) { ConnectionEventRecorder suppressConnectionEventRecorder{0}; sp suppressConnection = createConnection(suppressConnectionEventRecorder); mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666); auto args = suppressConnectionEventRecorder.waitForCall(); ASSERT_FALSE(args.has_value()); } TEST_F(EventThreadTest, postUidFrameRateMapping) { const std::vector overrides = { {.uid = 1, .frameRateHz = 20}, {.uid = 3, .frameRateHz = 40}, {.uid = 5, .frameRateHz = 60}, }; mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides); expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides); } TEST_F(EventThreadTest, suppressUidFrameRateMapping) { const std::vector overrides = { {.uid = 1, .frameRateHz = 20}, {.uid = 3, .frameRateHz = 40}, {.uid = 5, .frameRateHz = 60}, }; ConnectionEventRecorder suppressConnectionEventRecorder{0}; sp suppressConnection = createConnection(suppressConnectionEventRecorder); mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides); expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides); auto args = suppressConnectionEventRecorder.waitForCall(); ASSERT_FALSE(args.has_value()); } TEST_F(EventThreadTest, requestNextVsyncWithThrottleVsyncDoesntPostVSync) { // Signal that we want the next vsync event to be posted to the throttled connection mThread->requestNextVsync(mThrottledConnection); // EventThread should immediately request a resync. EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value()); // EventThread should enable vsync callbacks. expectVSyncSetEnabledCallReceived(true); // Use the received callback to signal a first vsync event. // The interceptor should receive the event, but not the connection. mCallback->onVSyncEvent(123, 456, 789); expectInterceptCallReceived(123); expectThrottleVsyncReceived(456, mThrottledConnectionUid); mThrottledConnectionEventCallRecorder.waitForUnexpectedCall(); // Use the received callback to signal a second vsync event. // The interceptor should receive the event, but the connection should // not as it was only interested in the first. mCallback->onVSyncEvent(456, 123, 0); expectInterceptCallReceived(456); expectThrottleVsyncReceived(123, mThrottledConnectionUid); EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value()); // EventThread should not change the vsync state as it didn't send the event // yet EXPECT_FALSE(mVSyncSetEnabledCallRecorder.waitForUnexpectedCall().has_value()); } } // namespace } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wextra"