1 /*
2  * Copyright 2022 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 <android/choreographer.h>
20 #include <gui/DisplayEventDispatcher.h>
21 #include <jni.h>
22 #include <utils/Looper.h>
23 
24 #include <mutex>
25 #include <queue>
26 #include <thread>
27 
28 namespace android {
29 using gui::VsyncEventData;
30 
31 enum CallbackType : int8_t {
32     CALLBACK_INPUT,
33     CALLBACK_ANIMATION,
34 };
35 
36 struct FrameCallback {
37     AChoreographer_frameCallback callback;
38     AChoreographer_frameCallback64 callback64;
39     AChoreographer_vsyncCallback vsyncCallback;
40     void* data;
41     nsecs_t dueTime;
42     CallbackType callbackType;
43 
44     inline bool operator<(const FrameCallback& rhs) const {
45         // Note that this is intentionally flipped because we want callbacks due sooner to be at
46         // the head of the queue
47         return dueTime > rhs.dueTime;
48     }
49 };
50 
51 struct RefreshRateCallback {
52     AChoreographer_refreshRateCallback callback;
53     void* data;
54     bool firstCallbackFired = false;
55 };
56 
57 class Choreographer;
58 
59 /**
60  * Implementation of AChoreographerFrameCallbackData.
61  */
62 struct ChoreographerFrameCallbackDataImpl {
63     int64_t frameTimeNanos{0};
64 
65     VsyncEventData vsyncEventData;
66 
67     const Choreographer* choreographer;
68 };
69 
70 class Choreographer : public DisplayEventDispatcher, public MessageHandler {
71 public:
72     struct Context {
73         std::mutex lock;
74         std::vector<Choreographer*> ptrs GUARDED_BY(lock);
75         std::map<AVsyncId, int64_t> startTimes GUARDED_BY(lock);
76         bool registeredToDisplayManager GUARDED_BY(lock) = false;
77 
78         std::atomic<nsecs_t> mLastKnownVsync = -1;
79     };
80     static Context gChoreographers;
81 
82     explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr)
83             EXCLUDES(gChoreographers.lock);
84     void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
85                                   AChoreographer_frameCallback64 cb64,
86                                   AChoreographer_vsyncCallback vsyncCallback, void* data,
87                                   nsecs_t delay, CallbackType callbackType);
88     void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
89             EXCLUDES(gChoreographers.lock);
90     void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
91     // Drains the queue of pending vsync periods and dispatches refresh rate
92     // updates to callbacks.
93     // The assumption is that this method is only called on a single
94     // processing thread, either by looper or by AChoreographer_handleEvents
95     void handleRefreshRateUpdates();
96     void scheduleLatestConfigRequest();
97 
98     enum {
99         MSG_SCHEDULE_CALLBACKS = 0,
100         MSG_SCHEDULE_VSYNC = 1,
101         MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
102     };
103     virtual void handleMessage(const Message& message) override;
104 
105     static void initJVM(JNIEnv* env);
106     static Choreographer* getForThread();
107     static void signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock);
108     static int64_t getStartTimeNanosForVsyncId(AVsyncId vsyncId) EXCLUDES(gChoreographers.lock);
109     virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
110     int64_t getFrameInterval() const;
111     bool inCallback() const;
112     const sp<Looper> getLooper();
113 
114 private:
115     Choreographer(const Choreographer&) = delete;
116 
117     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
118                        VsyncEventData vsyncEventData) override;
119     void dispatchCallbacks(const std::vector<FrameCallback>&, VsyncEventData vsyncEventData,
120                            nsecs_t timestamp);
121     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
122     void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) override;
123     void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
124                              nsecs_t vsyncPeriod) override;
125     void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
126     void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
127                                     std::vector<FrameRateOverride> overrides) override;
128     void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
129                                    int32_t maxLevel) override;
130 
131     void scheduleCallbacks();
132 
133     ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
134     void registerStartTime() const;
135 
136     std::mutex mLock;
137     // Protected by mLock
138     std::priority_queue<FrameCallback> mFrameCallbacks;
139     std::vector<RefreshRateCallback> mRefreshRateCallbacks;
140 
141     nsecs_t mLatestVsyncPeriod = -1;
142     VsyncEventData mLastVsyncEventData;
143     bool mInCallback = false;
144 
145     const sp<Looper> mLooper;
146     const std::thread::id mThreadId;
147 
148     // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
149     static constexpr size_t kMaxStartTimes = 250;
150 };
151 
152 } // namespace android
153