/* * Copyright (C) 2011 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. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DisplayHardware/DisplayMode.h" // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- class EventThread; class EventThreadTest; class SurfaceFlinger; namespace frametimeline { class TokenManager; } // namespace frametimeline // --------------------------------------------------------------------------- using ResyncCallback = std::function; using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; enum class VSyncRequest { None = -2, // Single wakes up for the next two frames to avoid scheduler overhead Single = -1, // SingleSuppressCallback only wakes up for the next frame SingleSuppressCallback = 0, Periodic = 1, // Subsequent values are periods. }; class VSyncSource { public: class Callback { public: virtual ~Callback() {} virtual void onVSyncEvent(nsecs_t when, nsecs_t expectedVSyncTimestamp, nsecs_t deadlineTimestamp) = 0; }; virtual ~VSyncSource() {} virtual const char* getName() const = 0; virtual void setVSyncEnabled(bool enable) = 0; virtual void setCallback(Callback* callback) = 0; virtual void setDuration(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) = 0; virtual void dump(std::string& result) const = 0; }; class EventThreadConnection : public BnDisplayEventConnection { public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); virtual ~EventThreadConnection(); virtual status_t postEvent(const DisplayEventReceiver::Event& event); status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t rate) override; void requestNextVsync() override; // asynchronous // Called in response to requestNextVsync. const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; const uid_t mOwnerUid; const ISurfaceComposer::EventRegistrationFlags mEventRegistration; private: virtual void onFirstRef(); EventThread* const mEventThread; gui::BitTube mChannel; std::vector mPendingEvents; }; class EventThread { public: virtual ~EventThread(); virtual sp createEventConnection( ResyncCallback, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const = 0; // called before the screen is turned off from main thread virtual void onScreenReleased() = 0; // called after the screen is turned on from main thread virtual void onScreenAcquired() = 0; virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; // called when SF changes the active mode and apps needs to be notified about the change virtual void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, nsecs_t vsyncPeriod) = 0; // called when SF updates the Frame Rate Override list virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId, std::vector overrides) = 0; virtual void dump(std::string& result) const = 0; virtual void setDuration(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) = 0; virtual status_t registerDisplayEventConnection( const sp& connection) = 0; virtual void setVsyncRate(uint32_t rate, const sp& connection) = 0; // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer. virtual void requestNextVsync(const sp& connection) = 0; // Retrieves the number of event connections tracked by this EventThread. virtual size_t getEventThreadConnectionCount() = 0; }; namespace impl { class EventThread : public android::EventThread, private VSyncSource::Callback { public: using InterceptVSyncsCallback = std::function; using ThrottleVsyncCallback = std::function; using GetVsyncPeriodFunction = std::function; EventThread(std::unique_ptr, frametimeline::TokenManager*, InterceptVSyncsCallback, ThrottleVsyncCallback, GetVsyncPeriodFunction); ~EventThread(); sp createEventConnection( ResyncCallback, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const override; status_t registerDisplayEventConnection(const sp& connection) override; void setVsyncRate(uint32_t rate, const sp& connection) override; void requestNextVsync(const sp& connection) override; // called before the screen is turned off from main thread void onScreenReleased() override; // called after the screen is turned on from main thread void onScreenAcquired() override; void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, nsecs_t vsyncPeriod) override; void onFrameRateOverridesChanged(PhysicalDisplayId displayId, std::vector overrides) override; void dump(std::string& result) const override; void setDuration(std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration) override; size_t getEventThreadConnectionCount() override; private: friend EventThreadTest; using DisplayEventConsumers = std::vector>; void threadMain(std::unique_lock& lock) REQUIRES(mMutex); bool shouldConsumeEvent(const DisplayEventReceiver::Event& event, const sp& connection) const REQUIRES(mMutex); void dispatchEvent(const DisplayEventReceiver::Event& event, const DisplayEventConsumers& consumers) REQUIRES(mMutex); void removeDisplayEventConnectionLocked(const wp& connection) REQUIRES(mMutex); // Implements VSyncSource::Callback void onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp, nsecs_t deadlineTimestamp) override; const std::unique_ptr mVSyncSource GUARDED_BY(mMutex); frametimeline::TokenManager* const mTokenManager; const InterceptVSyncsCallback mInterceptVSyncsCallback; const ThrottleVsyncCallback mThrottleVsyncCallback; const GetVsyncPeriodFunction mGetVsyncPeriodFunction; const char* const mThreadName; std::thread mThread; mutable std::mutex mMutex; mutable std::condition_variable mCondition; std::vector> mDisplayEventConnections GUARDED_BY(mMutex); std::deque mPendingEvents GUARDED_BY(mMutex); // VSYNC state of connected display. struct VSyncState { explicit VSyncState(PhysicalDisplayId displayId) : displayId(displayId) {} const PhysicalDisplayId displayId; // Number of VSYNC events since display was connected. uint32_t count = 0; // True if VSYNC should be faked, e.g. when display is off. bool synthetic = false; }; // TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals, // and support headless mode by injecting a fake display with synthetic VSYNC. std::optional mVSyncState GUARDED_BY(mMutex); // State machine for event loop. enum class State { Idle, Quit, SyntheticVSync, VSync, }; State mState GUARDED_BY(mMutex) = State::Idle; static const char* toCString(State); }; // --------------------------------------------------------------------------- } // namespace impl } // namespace android