Home | History | Annotate | Download | only in Scheduler
      1 /*
      2  * Copyright 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 #pragma once
     18 
     19 #include <cstdint>
     20 #include <functional>
     21 #include <memory>
     22 
     23 #include <ui/DisplayStatInfo.h>
     24 #include <ui/GraphicTypes.h>
     25 
     26 #include "DispSync.h"
     27 #include "EventControlThread.h"
     28 #include "EventThread.h"
     29 #include "IdleTimer.h"
     30 #include "InjectVSyncSource.h"
     31 #include "LayerHistory.h"
     32 #include "RefreshRateConfigs.h"
     33 #include "SchedulerUtils.h"
     34 
     35 namespace android {
     36 
     37 class EventControlThread;
     38 
     39 class Scheduler {
     40 public:
     41     // Enum to keep track of whether we trigger event to notify choreographer of config changes.
     42     enum class ConfigEvent { None, Changed };
     43 
     44     // logical or operator with the semantics of at least one of the events is Changed
     45     friend ConfigEvent operator|(const ConfigEvent& first, const ConfigEvent& second) {
     46         if (first == ConfigEvent::Changed) return ConfigEvent::Changed;
     47         if (second == ConfigEvent::Changed) return ConfigEvent::Changed;
     48         return ConfigEvent::None;
     49     }
     50 
     51     using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
     52     using ChangeRefreshRateCallback = std::function<void(RefreshRateType, ConfigEvent)>;
     53     using GetVsyncPeriod = std::function<nsecs_t()>;
     54 
     55     // Enum to indicate whether to start the transaction early, or at vsync time.
     56     enum class TransactionStart { EARLY, NORMAL };
     57 
     58     /* The scheduler handle is a BBinder object passed to the client from which we can extract
     59      * an ID for subsequent operations.
     60      */
     61     class ConnectionHandle : public BBinder {
     62     public:
     63         ConnectionHandle(int64_t id) : id(id) {}
     64 
     65         ~ConnectionHandle() = default;
     66 
     67         const int64_t id;
     68     };
     69 
     70     class Connection {
     71     public:
     72         Connection(sp<ConnectionHandle> handle, sp<EventThreadConnection> eventConnection,
     73                    std::unique_ptr<EventThread> eventThread)
     74               : handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
     75 
     76         ~Connection() = default;
     77 
     78         sp<ConnectionHandle> handle;
     79         sp<EventThreadConnection> eventConnection;
     80         const std::unique_ptr<EventThread> thread;
     81     };
     82 
     83     // Stores per-display state about VSYNC.
     84     struct VsyncState {
     85         explicit VsyncState(Scheduler& scheduler) : scheduler(scheduler) {}
     86 
     87         void resync(const GetVsyncPeriod&);
     88 
     89         Scheduler& scheduler;
     90         std::atomic<nsecs_t> lastResyncTime = 0;
     91     };
     92 
     93     explicit Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
     94                        const scheduler::RefreshRateConfigs& refreshRateConfig);
     95 
     96     virtual ~Scheduler();
     97 
     98     /** Creates an EventThread connection. */
     99     sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
    100                                           ResyncCallback,
    101                                           impl::EventThread::InterceptVSyncsCallback);
    102 
    103     sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
    104                                                              ResyncCallback);
    105 
    106     // Getter methods.
    107     EventThread* getEventThread(const sp<ConnectionHandle>& handle);
    108 
    109     // Provides access to the DispSync object for the primary display.
    110     void withPrimaryDispSync(std::function<void(DispSync&)> const& fn);
    111 
    112     sp<EventThreadConnection> getEventConnection(const sp<ConnectionHandle>& handle);
    113 
    114     // Should be called when receiving a hotplug event.
    115     void hotplugReceived(const sp<ConnectionHandle>& handle, PhysicalDisplayId displayId,
    116                          bool connected);
    117 
    118     // Should be called after the screen is turned on.
    119     void onScreenAcquired(const sp<ConnectionHandle>& handle);
    120 
    121     // Should be called before the screen is turned off.
    122     void onScreenReleased(const sp<ConnectionHandle>& handle);
    123 
    124     // Should be called when display config changed
    125     void onConfigChanged(const sp<ConnectionHandle>& handle, PhysicalDisplayId displayId,
    126                          int32_t configId);
    127 
    128     // Should be called when dumpsys command is received.
    129     void dump(const sp<ConnectionHandle>& handle, std::string& result) const;
    130 
    131     // Offers ability to modify phase offset in the event thread.
    132     void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
    133 
    134     void getDisplayStatInfo(DisplayStatInfo* stats);
    135 
    136     void enableHardwareVsync();
    137     void disableHardwareVsync(bool makeUnavailable);
    138     void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
    139     // Creates a callback for resyncing.
    140     ResyncCallback makeResyncCallback(GetVsyncPeriod&& getVsyncPeriod);
    141     void setRefreshSkipCount(int count);
    142     // Passes a vsync sample to DispSync. periodChange will be true if DipSync
    143     // detected that the vsync period changed, and false otherwise.
    144     void addResyncSample(const nsecs_t timestamp, bool* periodChanged);
    145     void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
    146     void setIgnorePresentFences(bool ignore);
    147     nsecs_t expectedPresentTime();
    148     // Registers the layer in the scheduler, and returns the handle for future references.
    149     std::unique_ptr<scheduler::LayerHistory::LayerHandle> registerLayer(std::string const& name,
    150                                                                         int windowType);
    151 
    152     // Stores present time for a layer.
    153     void addLayerPresentTimeAndHDR(
    154             const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle,
    155             nsecs_t presentTime, bool isHDR);
    156     // Stores visibility for a layer.
    157     void setLayerVisibility(
    158             const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, bool visible);
    159     // Updates FPS based on the most content presented.
    160     void updateFpsBasedOnContent();
    161     // Callback that gets invoked when Scheduler wants to change the refresh rate.
    162     void setChangeRefreshRateCallback(const ChangeRefreshRateCallback& changeRefreshRateCallback);
    163     void setGetVsyncPeriodCallback(const GetVsyncPeriod&& getVsyncPeriod);
    164 
    165     // Returns whether idle timer is enabled or not
    166     bool isIdleTimerEnabled() { return mSetIdleTimerMs > 0; }
    167 
    168     // Function that resets the idle timer.
    169     void resetIdleTimer();
    170 
    171     // Function that resets the touch timer.
    172     void notifyTouchEvent();
    173 
    174     // Returns relevant information about Scheduler for dumpsys purposes.
    175     std::string doDump();
    176 
    177     // calls DispSync::dump() on primary disp sync
    178     void dumpPrimaryDispSync(std::string& result) const;
    179 
    180 protected:
    181     virtual std::unique_ptr<EventThread> makeEventThread(
    182             const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
    183             impl::EventThread::InterceptVSyncsCallback interceptCallback);
    184 
    185 private:
    186     friend class TestableScheduler;
    187 
    188     // In order to make sure that the features don't override themselves, we need a state machine
    189     // to keep track which feature requested the config change.
    190     enum class ContentFeatureState { CONTENT_DETECTION_ON, CONTENT_DETECTION_OFF };
    191     enum class IdleTimerState { EXPIRED, RESET };
    192     enum class TouchState { INACTIVE, ACTIVE };
    193 
    194     // Creates a connection on the given EventThread and forwards the given callbacks.
    195     sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&);
    196 
    197     nsecs_t calculateAverage() const;
    198     void updateFrameSkipping(const int64_t skipCount);
    199 
    200     // Function that is called when the timer resets.
    201     void resetTimerCallback();
    202     // Function that is called when the timer expires.
    203     void expiredTimerCallback();
    204     // Function that is called when the timer resets when paired with a display
    205     // driver timeout in the kernel. This enables hardware vsync when we move
    206     // out from idle.
    207     void resetKernelTimerCallback();
    208     // Function that is called when the timer expires when paired with a display
    209     // driver timeout in the kernel. This disables hardware vsync when we move
    210     // into idle.
    211     void expiredKernelTimerCallback();
    212     // Function that is called when the touch timer resets.
    213     void resetTouchTimerCallback();
    214     // Function that is called when the touch timer expires.
    215     void expiredTouchTimerCallback();
    216     // Sets vsync period.
    217     void setVsyncPeriod(const nsecs_t period);
    218     // Idle timer feature's function to change the refresh rate.
    219     void timerChangeRefreshRate(IdleTimerState idleTimerState);
    220     // Touch timer feature's function to change the refresh rate.
    221     void touchChangeRefreshRate(TouchState touchState);
    222     // Calculate the new refresh rate type
    223     RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
    224     // Acquires a lock and calls the ChangeRefreshRateCallback() with given parameters.
    225     void changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent);
    226 
    227     // Helper function to calculate error frames
    228     float getErrorFrames(float contentFps, float configFps);
    229 
    230     // If fences from sync Framework are supported.
    231     const bool mHasSyncFramework;
    232 
    233     // The offset in nanoseconds to use, when DispSync timestamps present fence
    234     // signaling time.
    235     nsecs_t mDispSyncPresentTimeOffset;
    236 
    237     // Each connection has it's own ID. This variable keeps track of the count.
    238     static std::atomic<int64_t> sNextId;
    239 
    240     // Connections are stored in a map <connection ID, connection> for easy retrieval.
    241     std::unordered_map<int64_t, std::unique_ptr<Connection>> mConnections;
    242 
    243     std::mutex mHWVsyncLock;
    244     bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock);
    245     bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock);
    246     const std::shared_ptr<VsyncState> mPrimaryVsyncState{std::make_shared<VsyncState>(*this)};
    247 
    248     std::unique_ptr<DispSync> mPrimaryDispSync;
    249     std::unique_ptr<EventControlThread> mEventControlThread;
    250 
    251     // TODO(b/113612090): The following set of variables needs to be revised. For now, this is
    252     // a proof of concept. We turn on frame skipping if the difference between the timestamps
    253     // is between 32 and 34ms. We expect this currently for 30fps videos, so we render them at 30Hz.
    254     nsecs_t mPreviousFrameTimestamp = 0;
    255     // Keeping track of whether we are skipping the refresh count. If we want to
    256     // simulate 30Hz rendering, we skip every other frame, and this variable is set
    257     // to 1.
    258     int64_t mSkipCount = 0;
    259     std::array<int64_t, scheduler::ARRAY_SIZE> mTimeDifferences{};
    260     size_t mCounter = 0;
    261 
    262     // Historical information about individual layers. Used for predicting the refresh rate.
    263     scheduler::LayerHistory mLayerHistory;
    264 
    265     // Timer that records time between requests for next vsync. If the time is higher than a given
    266     // interval, a callback is fired. Set this variable to >0 to use this feature.
    267     int64_t mSetIdleTimerMs = 0;
    268     std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
    269     // Enables whether to use idle timer callbacks that support the kernel
    270     // timer.
    271     bool mSupportKernelTimer;
    272 
    273     // Timer used to monitor touch events.
    274     int64_t mSetTouchTimerMs = 0;
    275     std::unique_ptr<scheduler::IdleTimer> mTouchTimer;
    276 
    277     std::mutex mCallbackLock;
    278     ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock);
    279     GetVsyncPeriod mGetVsyncPeriod GUARDED_BY(mCallbackLock);
    280 
    281     // In order to make sure that the features don't override themselves, we need a state machine
    282     // to keep track which feature requested the config change.
    283     std::mutex mFeatureStateLock;
    284     ContentFeatureState mCurrentContentFeatureState GUARDED_BY(mFeatureStateLock) =
    285             ContentFeatureState::CONTENT_DETECTION_OFF;
    286     IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET;
    287     TouchState mCurrentTouchState GUARDED_BY(mFeatureStateLock) = TouchState::INACTIVE;
    288     uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock);
    289     RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock);
    290     bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false;
    291 
    292     const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
    293 
    294     // Global config to force HDR content to work on DEFAULT refreshRate
    295     static constexpr bool mForceHDRContentToDefaultRefreshRate = true;
    296 };
    297 
    298 } // namespace android
    299