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