1 /*
2  * Copyright 2021 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 <functional>
20 #include <memory>
21 #include <string>
22 
23 #include <android-base/thread_annotations.h>
24 #include <ThreadContext.h>
25 #include <ftl/enum.h>
26 #include <ftl/optional.h>
27 #include <ui/DisplayId.h>
28 
29 #include <scheduler/Features.h>
30 #include <scheduler/IVsyncSource.h>
31 #include <scheduler/Time.h>
32 
33 #include "ThreadContext.h"
34 #include "VSyncTracker.h"
35 
36 namespace android {
37 class EventThreadTest;
38 class VsyncScheduleTest;
39 }
40 
41 namespace android::fuzz {
42 class SchedulerFuzzer;
43 }
44 
45 namespace android::scheduler {
46 
47 // TODO(b/185535769): Rename classes, and remove aliases.
48 class VSyncDispatch;
49 class VSyncTracker;
50 
51 class VsyncController;
52 using VsyncDispatch = VSyncDispatch;
53 using VsyncTracker = VSyncTracker;
54 
55 // Schedule that synchronizes to hardware VSYNC of a physical display.
56 class VsyncSchedule final : public IVsyncSource {
57 public:
58     using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;
59 
60     VsyncSchedule(ftl::NonNull<DisplayModePtr> modePtr, FeatureFlags, RequestHardwareVsync);
61     ~VsyncSchedule();
62 
63     // IVsyncSource overrides:
64     Period period() const override;
65     TimePoint vsyncDeadlineAfter(TimePoint,
66                                  ftl::Optional<TimePoint> lastVsyncOpt = {}) const override;
67     Period minFramePeriod() const override;
68 
69     // Inform the schedule that the display mode changed the schedule needs to recalibrate
70     // itself to the new vsync period. The schedule will end the period transition internally.
71     // This will enable hardware VSYNCs in order to calibrate.
72     //
73     // \param [in] DisplayModePtr  The mode that the display is changing to.
74     // \param [in] force    True to force a transition even if it is not a
75     //                      change.
76     void onDisplayModeChanged(ftl::NonNull<DisplayModePtr>, bool force);
77 
78     // Pass a VSYNC sample to VsyncController. Return true if
79     // VsyncController detected that the VSYNC period changed. Enable or disable
80     // hardware VSYNCs depending on whether more samples are needed.
81     bool addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod);
82 
83     // TODO(b/185535769): Hide behind API.
getTracker()84     VsyncTracker& getTracker() const { return *mTracker; }
getTracker()85     VsyncTracker& getTracker() { return *mTracker; }
getController()86     VsyncController& getController() { return *mController; }
87 
88     // TODO(b/185535769): Once these are hidden behind the API, they may no
89     // longer need to be shared_ptrs.
90     using DispatchPtr = std::shared_ptr<VsyncDispatch>;
91     using TrackerPtr = std::shared_ptr<VsyncTracker>;
92 
93     // TODO(b/185535769): Remove once VsyncSchedule owns all registrations.
getDispatch()94     DispatchPtr getDispatch() { return mDispatch; }
95 
96     void dump(std::string&) const;
97 
98     // Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which
99     // case this call is ignored.
100     void enableHardwareVsync() EXCLUDES(mHwVsyncLock);
101 
102     // Disable hardware VSYNCs. If `disallow` is true, future calls to
103     // enableHardwareVsync are ineffective until isHardwareVsyncAllowed is
104     // called with `makeAllowed` set to true.
105     void disableHardwareVsync(bool disallow) EXCLUDES(mHwVsyncLock);
106 
107     // If true, enableHardwareVsync can enable hardware VSYNC (if not already
108     // enabled). If false, enableHardwareVsync does nothing.
109     bool isHardwareVsyncAllowed(bool makeAllowed) EXCLUDES(mHwVsyncLock);
110 
111     void setPendingHardwareVsyncState(bool enabled) REQUIRES(kMainThreadContext);
112 
113     bool getPendingHardwareVsyncState() const REQUIRES(kMainThreadContext);
114 
115 protected:
116     using ControllerPtr = std::unique_ptr<VsyncController>;
117 
NoOpRequestHardwareVsync(PhysicalDisplayId,bool)118     static void NoOpRequestHardwareVsync(PhysicalDisplayId, bool) {}
119 
120     // For tests.
121     VsyncSchedule(PhysicalDisplayId, TrackerPtr, DispatchPtr, ControllerPtr,
122                   RequestHardwareVsync = NoOpRequestHardwareVsync);
123 
124 private:
125     friend class TestableScheduler;
126     friend class android::EventThreadTest;
127     friend class android::VsyncScheduleTest;
128     friend class android::fuzz::SchedulerFuzzer;
129 
130     static TrackerPtr createTracker(ftl::NonNull<DisplayModePtr> modePtr);
131     static DispatchPtr createDispatch(TrackerPtr);
132     static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);
133 
134     void enableHardwareVsyncLocked() REQUIRES(mHwVsyncLock);
135 
136     mutable std::mutex mHwVsyncLock;
137     enum class HwVsyncState {
138         // Hardware VSYNCs are currently enabled.
139         Enabled,
140 
141         // Hardware VSYNCs are currently disabled. They can be enabled by a call
142         // to `enableHardwareVsync`.
143         Disabled,
144 
145         // Hardware VSYNCs are not currently allowed (e.g. because the display
146         // is off).
147         Disallowed,
148 
149         ftl_last = Disallowed,
150     };
151     HwVsyncState mHwVsyncState GUARDED_BY(mHwVsyncLock) = HwVsyncState::Disallowed;
152 
153     // Pending state, in case an attempt is made to set the state while the
154     // device is off.
155     HwVsyncState mPendingHwVsyncState GUARDED_BY(kMainThreadContext) = HwVsyncState::Disabled;
156 
157     class PredictedVsyncTracer;
158     using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
159 
160     const PhysicalDisplayId mId;
161     const RequestHardwareVsync mRequestHardwareVsync;
162     const TrackerPtr mTracker;
163     const DispatchPtr mDispatch;
164     const ControllerPtr mController;
165     const TracerPtr mTracer;
166 };
167 
168 } // namespace android::scheduler
169