1 /*
2  * Copyright 2019 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 <utils/Timers.h>
20 #include <functional>
21 #include <string>
22 
23 #include "StrongTyping.h"
24 
25 namespace android::scheduler {
26 class TimeKeeper;
27 class VSyncTracker;
28 
29 enum class ScheduleResult { Scheduled, CannotSchedule, Error };
30 enum class CancelResult { Cancelled, TooLate, Error };
31 
32 /*
33  * VSyncDispatch is a class that will dispatch callbacks relative to system vsync events.
34  */
35 class VSyncDispatch {
36 public:
37     using CallbackToken = StrongTyping<size_t, class CallbackTokenTag, Compare, Hash>;
38 
39     virtual ~VSyncDispatch();
40 
41     /*
42      * A callback that can be registered to be awoken at a given time relative to a vsync event.
43      * \param [in] vsyncTime The timestamp of the vsync the callback is for.
44      * \param [in] targetWakeupTime The timestamp of intended wakeup time of the cb.
45      *
46      */
47     using Callback = std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime)>;
48 
49     /*
50      * Registers a callback that will be called at designated points on the vsync timeline.
51      * The callback can be scheduled, rescheduled targeting vsync times, or cancelled.
52      * The token returned must be cleaned up via unregisterCallback.
53      *
54      * \param [in] callbackFn   A function to schedule for callback. The resources needed to invoke
55      *                          callbackFn must have lifetimes encompassing the lifetime of the
56      *                          CallbackToken returned.
57      * \param [in] callbackName A human-readable, unique name to identify the callback.
58      * \return                  A token that can be used to schedule, reschedule, or cancel the
59      *                          invocation of callbackFn.
60      *
61      */
62     virtual CallbackToken registerCallback(Callback const& callbackFn,
63                                            std::string callbackName) = 0;
64 
65     /*
66      * Unregisters a callback.
67      *
68      * \param [in] token        The callback to unregister.
69      *
70      */
71     virtual void unregisterCallback(CallbackToken token) = 0;
72 
73     /*
74      * Schedules the registered callback to be dispatched.
75      *
76      * The callback will be dispatched at 'workDuration' nanoseconds before a vsync event.
77      *
78      * The caller designates the earliest vsync event that should be targeted by the earliestVsync
79      * parameter.
80      * The callback will be scheduled at (workDuration - predictedVsync), where predictedVsync
81      * is the first vsync event time where ( predictedVsync >= earliestVsync ).
82      *
83      * If (workDuration - earliestVsync) is in the past, or if a callback has already been
84      * dispatched for the predictedVsync, an error will be returned.
85      *
86      * It is valid to reschedule a callback to a different time.
87      *
88      * \param [in] token           The callback to schedule.
89      * \param [in] workDuration    The time before the actual vsync time to invoke the callback
90      *                             associated with token.
91      * \param [in] earliestVsync   The targeted display time. This will be snapped to the closest
92      *                             predicted vsync time after earliestVsync.
93      * \return                     A ScheduleResult::Scheduled if callback was scheduled.
94      *                             A ScheduleResult::CannotSchedule
95      *                             if (workDuration - earliestVsync) is in the past, or
96      *                             if a callback was dispatched for the predictedVsync already.
97      *                             A ScheduleResult::Error if there was another error.
98      */
99     virtual ScheduleResult schedule(CallbackToken token, nsecs_t workDuration,
100                                     nsecs_t earliestVsync) = 0;
101 
102     /* Cancels a scheduled callback, if possible.
103      *
104      * \param [in] token    The callback to cancel.
105      * \return              A CancelResult::TooLate if the callback was already dispatched.
106      *                      A CancelResult::Cancelled if the callback was successfully cancelled.
107      *                      A CancelResult::Error if there was an pre-condition violation.
108      */
109     virtual CancelResult cancel(CallbackToken token) = 0;
110 
111     virtual void dump(std::string& result) const = 0;
112 
113 protected:
114     VSyncDispatch() = default;
115     VSyncDispatch(VSyncDispatch const&) = delete;
116     VSyncDispatch& operator=(VSyncDispatch const&) = delete;
117 };
118 
119 /*
120  * Helper class to operate on registered callbacks. It is up to user of the class to ensure
121  * that VsyncDispatch lifetime exceeds the lifetime of VSyncCallbackRegistation.
122  */
123 class VSyncCallbackRegistration {
124 public:
125     VSyncCallbackRegistration(VSyncDispatch&, VSyncDispatch::Callback const& callbackFn,
126                               std::string const& callbackName);
127     VSyncCallbackRegistration(VSyncCallbackRegistration&&);
128     VSyncCallbackRegistration& operator=(VSyncCallbackRegistration&&);
129     ~VSyncCallbackRegistration();
130 
131     // See documentation for VSyncDispatch::schedule.
132     ScheduleResult schedule(nsecs_t workDuration, nsecs_t earliestVsync);
133 
134     // See documentation for VSyncDispatch::cancel.
135     CancelResult cancel();
136 
137 private:
138     VSyncCallbackRegistration(VSyncCallbackRegistration const&) = delete;
139     VSyncCallbackRegistration& operator=(VSyncCallbackRegistration const&) = delete;
140 
141     std::reference_wrapper<VSyncDispatch> mDispatch;
142     VSyncDispatch::CallbackToken mToken;
143     bool mValidToken;
144 };
145 
146 } // namespace android::scheduler
147