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 #pragma clang diagnostic ignored "-Wextra" 30 #include <ui/GraphicTypes.h> 31 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" 32 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 FenceTime; 45 class InjectVSyncSource; 46 class PredictedVsyncTracer; 47 48 namespace scheduler { 49 class VsyncController; 50 class VSyncDispatch; 51 class VSyncTracker; 52 } // namespace scheduler 53 54 namespace frametimeline { 55 class TokenManager; 56 } // namespace frametimeline 57 58 struct ISchedulerCallback { 59 virtual void setVsyncEnabled(bool) = 0; 60 virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, 61 scheduler::RefreshRateConfigEvent) = 0; 62 virtual void repaintEverythingForHWC() = 0; 63 virtual void kernelTimerChanged(bool expired) = 0; 64 virtual void triggerOnFrameRateOverridesChanged() = 0; 65 66 protected: 67 ~ISchedulerCallback() = default; 68 }; 69 70 class Scheduler { 71 public: 72 using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; 73 using ModeEvent = scheduler::RefreshRateConfigEvent; 74 75 Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&); 76 ~Scheduler(); 77 78 using ConnectionHandle = scheduler::ConnectionHandle; 79 ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*, 80 std::chrono::nanoseconds workDuration, 81 std::chrono::nanoseconds readyDuration, 82 impl::EventThread::InterceptVSyncsCallback); 83 84 sp<IDisplayEventConnection> createDisplayEventConnection( 85 ConnectionHandle, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); 86 87 sp<EventThreadConnection> getEventConnection(ConnectionHandle); 88 89 void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); 90 void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mFeatureStateLock); 91 void onNonPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr); 92 void onScreenAcquired(ConnectionHandle); 93 void onScreenReleased(ConnectionHandle); 94 95 void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId) 96 EXCLUDES(mFrameRateOverridesLock) EXCLUDES(mConnectionsLock); 97 98 // Modifies work duration in the event thread. 99 void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration, 100 std::chrono::nanoseconds readyDuration); 101 102 DisplayStatInfo getDisplayStatInfo(nsecs_t now); 103 104 // Returns injector handle if injection has toggled, or an invalid handle otherwise. 105 ConnectionHandle enableVSyncInjection(bool enable); 106 // Returns false if injection is disabled. 107 bool injectVSync(nsecs_t when, nsecs_t expectedVSyncTime, nsecs_t deadlineTimestamp); 108 void enableHardwareVsync(); 109 void disableHardwareVsync(bool makeUnavailable); 110 111 // Resyncs the scheduler to hardware vsync. 112 // If makeAvailable is true, then hardware vsync will be turned on. 113 // Otherwise, if hardware vsync is not already enabled then this method will 114 // no-op. 115 // The period is the vsync period from the current display configuration. 116 void resyncToHardwareVsync(bool makeAvailable, nsecs_t period); 117 void resync() EXCLUDES(mRefreshRateConfigsLock); 118 119 // Passes a vsync sample to VsyncController. periodFlushed will be true if 120 // VsyncController detected that the vsync period changed, and false otherwise. 121 void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod, 122 bool* periodFlushed); 123 void addPresentFence(const std::shared_ptr<FenceTime>&); 124 void setIgnorePresentFences(bool ignore); 125 126 // Layers are registered on creation, and unregistered when the weak reference expires. 127 void registerLayer(Layer*); 128 void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType) 129 EXCLUDES(mRefreshRateConfigsLock); 130 void setModeChangePending(bool pending); 131 void deregisterLayer(Layer*); 132 133 // Detects content using layer history, and selects a matching refresh rate. 134 void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock); 135 136 void resetIdleTimer(); 137 138 // Function that resets the touch timer. 139 void notifyTouchEvent(); 140 141 void setDisplayPowerState(bool normal); 142 getVsyncDispatch()143 scheduler::VSyncDispatch& getVsyncDispatch() { return *mVsyncSchedule.dispatch; } 144 145 // Returns true if a given vsync timestamp is considered valid vsync 146 // for a given uid 147 bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const 148 EXCLUDES(mFrameRateOverridesLock); 149 150 std::chrono::steady_clock::time_point getPreviousVsyncFrom(nsecs_t expectedPresentTime) const; 151 152 void dump(std::string&) const; 153 void dump(ConnectionHandle, std::string&) const; 154 void dumpVsync(std::string&) const; 155 156 // Get the appropriate refresh for current conditions. 157 DisplayModePtr getPreferredDisplayMode(); 158 159 // Notifies the scheduler about a refresh rate timeline change. 160 void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); 161 162 // Notifies the scheduler when the display was refreshed 163 void onDisplayRefreshed(nsecs_t timestamp); 164 165 // Notifies the scheduler when the display size has changed. Called from SF's main thread 166 void onActiveDisplayAreaChanged(uint32_t displayArea); 167 168 size_t getEventThreadConnectionCount(ConnectionHandle handle); 169 170 std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, 171 std::chrono::nanoseconds workDuration, 172 std::chrono::nanoseconds readyDuration, 173 bool traceVsync = true); 174 175 // Stores the preferred refresh rate that an app should run at. 176 // FrameRateOverride.refreshRateHz == 0 means no preference. 177 void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesLock); 178 // Retrieves the overridden refresh rate for a given uid. 179 std::optional<Fps> getFrameRateOverride(uid_t uid) const 180 EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock); 181 setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs)182 void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs) 183 EXCLUDES(mRefreshRateConfigsLock) { 184 // We need to stop the idle timer on the previous RefreshRateConfigs instance 185 // and cleanup the scheduler's state before we switch to the other RefreshRateConfigs. 186 { 187 std::scoped_lock lock(mRefreshRateConfigsLock); 188 if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer(); 189 } 190 { 191 std::scoped_lock lock(mFeatureStateLock); 192 mFeatures = {}; 193 } 194 { 195 std::scoped_lock lock(mRefreshRateConfigsLock); 196 mRefreshRateConfigs = std::move(refreshRateConfigs); 197 mRefreshRateConfigs->setIdleTimerCallbacks( 198 [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Reset); }, 199 [this] { 200 std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Expired); 201 }, 202 [this] { 203 std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Reset); 204 }, 205 [this] { 206 std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Expired); 207 }); 208 mRefreshRateConfigs->startIdleTimer(); 209 } 210 } 211 getVsyncPeriodFromRefreshRateConfigs()212 nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) { 213 std::scoped_lock lock(mRefreshRateConfigsLock); 214 return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); 215 } 216 217 private: 218 friend class TestableScheduler; 219 220 // In order to make sure that the features don't override themselves, we need a state machine 221 // to keep track which feature requested the config change. 222 enum class ContentDetectionState { Off, On }; 223 enum class TimerState { Reset, Expired }; 224 enum class TouchState { Inactive, Active }; 225 226 struct Options { 227 // Whether to use content detection at all. 228 bool useContentDetection; 229 }; 230 231 struct VsyncSchedule { 232 std::unique_ptr<scheduler::VsyncController> controller; 233 std::unique_ptr<scheduler::VSyncTracker> tracker; 234 std::unique_ptr<scheduler::VSyncDispatch> dispatch; 235 }; 236 237 // Unlike the testing constructor, this creates the VsyncSchedule, LayerHistory, and timers. 238 Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&, Options); 239 240 // Used by tests to inject mocks. 241 Scheduler(VsyncSchedule, const std::shared_ptr<scheduler::RefreshRateConfigs>&, 242 ISchedulerCallback&, std::unique_ptr<LayerHistory>, Options); 243 244 static VsyncSchedule createVsyncSchedule(bool supportKernelIdleTimer); 245 static std::unique_ptr<LayerHistory> createLayerHistory(); 246 247 // Create a connection on the given EventThread. 248 ConnectionHandle createConnection(std::unique_ptr<EventThread>); 249 sp<EventThreadConnection> createConnectionInternal( 250 EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); 251 252 // Update feature state machine to given state when corresponding timer resets or expires. 253 void kernelIdleTimerCallback(TimerState) EXCLUDES(mRefreshRateConfigsLock); 254 void idleTimerCallback(TimerState); 255 void touchTimerCallback(TimerState); 256 void displayPowerTimerCallback(TimerState); 257 258 // handles various timer features to change the refresh rate. 259 template <class T> 260 bool handleTimerStateChanged(T* currentState, T newState); 261 262 void setVsyncPeriod(nsecs_t period); 263 264 // This function checks whether individual features that are affecting the refresh rate 265 // selection were initialized, prioritizes them, and calculates the DisplayModeId 266 // for the suggested refresh rate. 267 DisplayModePtr calculateRefreshRateModeId( 268 scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) 269 REQUIRES(mFeatureStateLock); 270 271 void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock); 272 bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, 273 Fps displayRefreshRate) REQUIRES(mFeatureStateLock) 274 EXCLUDES(mFrameRateOverridesLock); 275 276 impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const 277 EXCLUDES(mRefreshRateConfigsLock); 278 impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; 279 holdRefreshRateConfigs()280 std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const 281 EXCLUDES(mRefreshRateConfigsLock) { 282 std::scoped_lock lock(mRefreshRateConfigsLock); 283 return mRefreshRateConfigs; 284 } 285 286 // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. 287 struct Connection { 288 sp<EventThreadConnection> connection; 289 std::unique_ptr<EventThread> thread; 290 }; 291 292 ConnectionHandle::Id mNextConnectionHandleId = 0; 293 mutable std::mutex mConnectionsLock; 294 std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock); 295 296 bool mInjectVSyncs = false; 297 InjectVSyncSource* mVSyncInjector = nullptr; 298 ConnectionHandle mInjectorConnectionHandle; 299 300 mutable std::mutex mHWVsyncLock; 301 bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false; 302 bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false; 303 304 std::atomic<nsecs_t> mLastResyncTime = 0; 305 306 const Options mOptions; 307 VsyncSchedule mVsyncSchedule; 308 309 // Used to choose refresh rate if content detection is enabled. 310 std::unique_ptr<LayerHistory> mLayerHistory; 311 312 // Timer used to monitor touch events. 313 std::optional<scheduler::OneShotTimer> mTouchTimer; 314 // Timer used to monitor display power mode. 315 std::optional<scheduler::OneShotTimer> mDisplayPowerTimer; 316 317 ISchedulerCallback& mSchedulerCallback; 318 319 // In order to make sure that the features don't override themselves, we need a state machine 320 // to keep track which feature requested the config change. 321 mutable std::mutex mFeatureStateLock; 322 323 struct { 324 TimerState idleTimer = TimerState::Reset; 325 TouchState touch = TouchState::Inactive; 326 TimerState displayPowerTimer = TimerState::Expired; 327 328 DisplayModePtr mode; 329 LayerHistory::Summary contentRequirements; 330 331 bool isDisplayPowerStateNormal = true; 332 333 // Used to cache the last parameters of onPrimaryDisplayModeChanged 334 struct ModeChangedParams { 335 ConnectionHandle handle; 336 DisplayModePtr mode; 337 }; 338 339 std::optional<ModeChangedParams> cachedModeChangedParams; 340 } mFeatures GUARDED_BY(mFeatureStateLock); 341 342 mutable std::mutex mRefreshRateConfigsLock; 343 std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs 344 GUARDED_BY(mRefreshRateConfigsLock); 345 346 std::mutex mVsyncTimelineLock; 347 std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline 348 GUARDED_BY(mVsyncTimelineLock); 349 static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; 350 351 const std::unique_ptr<PredictedVsyncTracer> mPredictedVsyncTracer; 352 353 // The frame rate override lists need their own mutex as they are being read 354 // by SurfaceFlinger, Scheduler and EventThread (as a callback) to prevent deadlocks 355 mutable std::mutex mFrameRateOverridesLock; 356 357 // mappings between a UID and a preferred refresh rate that this app would 358 // run at. 359 scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent 360 GUARDED_BY(mFrameRateOverridesLock); 361 scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor 362 GUARDED_BY(mFrameRateOverridesLock); 363 364 // Keeps track of whether the screen is acquired for debug 365 std::atomic<bool> mScreenAcquired = false; 366 }; 367 368 } // namespace android 369