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 <atomic> 20 #include <functional> 21 #include <memory> 22 #include <mutex> 23 #include <optional> 24 #include <unordered_map> 25 26 // TODO(b/129481165): remove the #pragma below and fix conversion issues 27 #pragma clang diagnostic push 28 #pragma clang diagnostic ignored "-Wconversion" 29 #include <ui/GraphicTypes.h> 30 #pragma clang diagnostic pop 31 32 #include "EventControlThread.h" 33 #include "EventThread.h" 34 #include "LayerHistory.h" 35 #include "OneShotTimer.h" 36 #include "RefreshRateConfigs.h" 37 #include "SchedulerUtils.h" 38 39 namespace android { 40 41 using namespace std::chrono_literals; 42 using scheduler::LayerHistory; 43 44 class DispSync; 45 class FenceTime; 46 class InjectVSyncSource; 47 struct DisplayStateInfo; 48 49 class ISchedulerCallback { 50 public: 51 virtual ~ISchedulerCallback() = default; 52 virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, 53 scheduler::RefreshRateConfigEvent) = 0; 54 virtual void repaintEverythingForHWC() = 0; 55 virtual void kernelTimerChanged(bool expired) = 0; 56 }; 57 58 class IPhaseOffsetControl { 59 public: 60 virtual ~IPhaseOffsetControl() = default; 61 virtual void setPhaseOffset(scheduler::ConnectionHandle, nsecs_t phaseOffset) = 0; 62 }; 63 64 class Scheduler : public IPhaseOffsetControl { 65 public: 66 using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; 67 using ConfigEvent = scheduler::RefreshRateConfigEvent; 68 69 // Indicates whether to start the transaction early, or at vsync time. 70 enum class TransactionStart { 71 Early, // DEPRECATED. Start the transaction early. Times out on its own 72 EarlyStart, // Start the transaction early and keep this config until EarlyEnd 73 EarlyEnd, // End the early config started at EarlyStart 74 Normal // Start the transaction at the normal time 75 }; 76 77 Scheduler(impl::EventControlThread::SetVSyncEnabledFunction, 78 const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, 79 bool useContentDetectionV2, bool useContentDetection); 80 81 virtual ~Scheduler(); 82 83 DispSync& getPrimaryDispSync(); 84 85 using ConnectionHandle = scheduler::ConnectionHandle; 86 ConnectionHandle createConnection(const char* connectionName, nsecs_t phaseOffsetNs, 87 impl::EventThread::InterceptVSyncsCallback); 88 89 sp<IDisplayEventConnection> createDisplayEventConnection(ConnectionHandle, 90 ISurfaceComposer::ConfigChanged); 91 92 sp<EventThreadConnection> getEventConnection(ConnectionHandle); 93 94 void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); 95 void onPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId, 96 HwcConfigIndexType configId, nsecs_t vsyncPeriod) 97 EXCLUDES(mFeatureStateLock); 98 void onNonPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId, 99 HwcConfigIndexType configId, nsecs_t vsyncPeriod); 100 void onScreenAcquired(ConnectionHandle); 101 void onScreenReleased(ConnectionHandle); 102 103 // Modifies phase offset in the event thread. 104 void setPhaseOffset(ConnectionHandle, nsecs_t phaseOffset) override; 105 106 void getDisplayStatInfo(DisplayStatInfo* stats); 107 108 // Returns injector handle if injection has toggled, or an invalid handle otherwise. 109 ConnectionHandle enableVSyncInjection(bool enable); 110 111 // Returns false if injection is disabled. 112 bool injectVSync(nsecs_t when, nsecs_t expectedVSyncTime); 113 114 void enableHardwareVsync(); 115 void disableHardwareVsync(bool makeUnavailable); 116 117 // Resyncs the scheduler to hardware vsync. 118 // If makeAvailable is true, then hardware vsync will be turned on. 119 // Otherwise, if hardware vsync is not already enabled then this method will 120 // no-op. 121 // The period is the vsync period from the current display configuration. 122 void resyncToHardwareVsync(bool makeAvailable, nsecs_t period); 123 void resync(); 124 125 // Passes a vsync sample to DispSync. periodFlushed will be true if 126 // DispSync detected that the vsync period changed, and false otherwise. 127 void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, 128 bool* periodFlushed); 129 void addPresentFence(const std::shared_ptr<FenceTime>&); 130 void setIgnorePresentFences(bool ignore); 131 nsecs_t getDispSyncExpectedPresentTime(nsecs_t now); 132 133 // Layers are registered on creation, and unregistered when the weak reference expires. 134 void registerLayer(Layer*); 135 void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType); 136 void setConfigChangePending(bool pending); 137 138 // Detects content using layer history, and selects a matching refresh rate. 139 void chooseRefreshRateForContent(); 140 isIdleTimerEnabled()141 bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); } 142 void resetIdleTimer(); 143 144 // Function that resets the touch timer. 145 void notifyTouchEvent(); 146 147 void setDisplayPowerState(bool normal); 148 149 void dump(std::string&) const; 150 void dump(ConnectionHandle, std::string&) const; 151 152 // Get the appropriate refresh for current conditions. 153 std::optional<HwcConfigIndexType> getPreferredConfigId(); 154 155 // Notifies the scheduler about a refresh rate timeline change. 156 void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); 157 158 // Notifies the scheduler when the display was refreshed 159 void onDisplayRefreshed(nsecs_t timestamp); 160 161 // Notifies the scheduler when the display size has changed. Called from SF's main thread 162 void onPrimaryDisplayAreaChanged(uint32_t displayArea); 163 164 size_t getEventThreadConnectionCount(ConnectionHandle handle); 165 166 private: 167 friend class TestableScheduler; 168 169 // In order to make sure that the features don't override themselves, we need a state machine 170 // to keep track which feature requested the config change. 171 enum class ContentDetectionState { Off, On }; 172 enum class TimerState { Reset, Expired }; 173 enum class TouchState { Inactive, Active }; 174 175 // Used by tests to inject mocks. 176 Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>, 177 const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, 178 bool useContentDetectionV2, bool useContentDetection); 179 180 std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs); 181 182 // Create a connection on the given EventThread. 183 ConnectionHandle createConnection(std::unique_ptr<EventThread>); 184 sp<EventThreadConnection> createConnectionInternal(EventThread*, 185 ISurfaceComposer::ConfigChanged); 186 187 // Update feature state machine to given state when corresponding timer resets or expires. 188 void kernelIdleTimerCallback(TimerState); 189 void idleTimerCallback(TimerState); 190 void touchTimerCallback(TimerState); 191 void displayPowerTimerCallback(TimerState); 192 193 // handles various timer features to change the refresh rate. 194 template <class T> 195 bool handleTimerStateChanged(T* currentState, T newState); 196 197 void setVsyncPeriod(nsecs_t period); 198 199 // This function checks whether individual features that are affecting the refresh rate 200 // selection were initialized, prioritizes them, and calculates the HwcConfigIndexType 201 // for the suggested refresh rate. 202 HwcConfigIndexType calculateRefreshRateConfigIndexType( 203 scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) 204 REQUIRES(mFeatureStateLock); 205 206 void dispatchCachedReportedConfig() REQUIRES(mFeatureStateLock); 207 208 // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. 209 struct Connection { 210 sp<EventThreadConnection> connection; 211 std::unique_ptr<EventThread> thread; 212 }; 213 214 ConnectionHandle::Id mNextConnectionHandleId = 0; 215 std::unordered_map<ConnectionHandle, Connection> mConnections; 216 217 bool mInjectVSyncs = false; 218 InjectVSyncSource* mVSyncInjector = nullptr; 219 ConnectionHandle mInjectorConnectionHandle; 220 221 std::mutex mHWVsyncLock; 222 bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false; 223 bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false; 224 225 std::atomic<nsecs_t> mLastResyncTime = 0; 226 227 // Whether to use idle timer callbacks that support the kernel timer. 228 const bool mSupportKernelTimer; 229 230 std::unique_ptr<DispSync> mPrimaryDispSync; 231 std::unique_ptr<EventControlThread> mEventControlThread; 232 233 // Used to choose refresh rate if content detection is enabled. 234 std::unique_ptr<LayerHistory> mLayerHistory; 235 236 // Timer that records time between requests for next vsync. 237 std::optional<scheduler::OneShotTimer> mIdleTimer; 238 // Timer used to monitor touch events. 239 std::optional<scheduler::OneShotTimer> mTouchTimer; 240 // Timer used to monitor display power mode. 241 std::optional<scheduler::OneShotTimer> mDisplayPowerTimer; 242 243 ISchedulerCallback& mSchedulerCallback; 244 245 // In order to make sure that the features don't override themselves, we need a state machine 246 // to keep track which feature requested the config change. 247 std::mutex mFeatureStateLock; 248 249 struct { 250 ContentDetectionState contentDetectionV1 = ContentDetectionState::Off; 251 TimerState idleTimer = TimerState::Reset; 252 TouchState touch = TouchState::Inactive; 253 TimerState displayPowerTimer = TimerState::Expired; 254 255 std::optional<HwcConfigIndexType> configId; 256 LayerHistory::Summary contentRequirements; 257 258 bool isDisplayPowerStateNormal = true; 259 260 // Used to cache the last parameters of onPrimaryDisplayConfigChanged 261 struct ConfigChangedParams { 262 ConnectionHandle handle; 263 PhysicalDisplayId displayId; 264 HwcConfigIndexType configId; 265 nsecs_t vsyncPeriod; 266 }; 267 268 std::optional<ConfigChangedParams> cachedConfigChangedParams; 269 } mFeatures GUARDED_BY(mFeatureStateLock); 270 271 const scheduler::RefreshRateConfigs& mRefreshRateConfigs; 272 273 std::mutex mVsyncTimelineLock; 274 std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline 275 GUARDED_BY(mVsyncTimelineLock); 276 static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; 277 278 // This variable indicates whether to use the content detection feature at all. 279 const bool mUseContentDetection; 280 // This variable indicates whether to use V2 version of the content detection. 281 const bool mUseContentDetectionV2; 282 }; 283 284 } // namespace android 285