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