xref: /aosp_15_r20/frameworks/native/include/gui/Choreographer.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright 2022 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <android/choreographer.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <gui/DisplayEventDispatcher.h>
21*38e8c45fSAndroid Build Coastguard Worker #include <jni.h>
22*38e8c45fSAndroid Build Coastguard Worker #include <utils/Looper.h>
23*38e8c45fSAndroid Build Coastguard Worker 
24*38e8c45fSAndroid Build Coastguard Worker #include <mutex>
25*38e8c45fSAndroid Build Coastguard Worker #include <queue>
26*38e8c45fSAndroid Build Coastguard Worker #include <thread>
27*38e8c45fSAndroid Build Coastguard Worker 
28*38e8c45fSAndroid Build Coastguard Worker namespace android {
29*38e8c45fSAndroid Build Coastguard Worker using gui::VsyncEventData;
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker enum CallbackType : int8_t {
32*38e8c45fSAndroid Build Coastguard Worker     CALLBACK_INPUT,
33*38e8c45fSAndroid Build Coastguard Worker     CALLBACK_ANIMATION,
34*38e8c45fSAndroid Build Coastguard Worker };
35*38e8c45fSAndroid Build Coastguard Worker 
36*38e8c45fSAndroid Build Coastguard Worker struct FrameCallback {
37*38e8c45fSAndroid Build Coastguard Worker     AChoreographer_frameCallback callback;
38*38e8c45fSAndroid Build Coastguard Worker     AChoreographer_frameCallback64 callback64;
39*38e8c45fSAndroid Build Coastguard Worker     AChoreographer_vsyncCallback vsyncCallback;
40*38e8c45fSAndroid Build Coastguard Worker     void* data;
41*38e8c45fSAndroid Build Coastguard Worker     nsecs_t dueTime;
42*38e8c45fSAndroid Build Coastguard Worker     CallbackType callbackType;
43*38e8c45fSAndroid Build Coastguard Worker 
44*38e8c45fSAndroid Build Coastguard Worker     inline bool operator<(const FrameCallback& rhs) const {
45*38e8c45fSAndroid Build Coastguard Worker         // Note that this is intentionally flipped because we want callbacks due sooner to be at
46*38e8c45fSAndroid Build Coastguard Worker         // the head of the queue
47*38e8c45fSAndroid Build Coastguard Worker         return dueTime > rhs.dueTime;
48*38e8c45fSAndroid Build Coastguard Worker     }
49*38e8c45fSAndroid Build Coastguard Worker };
50*38e8c45fSAndroid Build Coastguard Worker 
51*38e8c45fSAndroid Build Coastguard Worker struct RefreshRateCallback {
52*38e8c45fSAndroid Build Coastguard Worker     AChoreographer_refreshRateCallback callback;
53*38e8c45fSAndroid Build Coastguard Worker     void* data;
54*38e8c45fSAndroid Build Coastguard Worker     bool firstCallbackFired = false;
55*38e8c45fSAndroid Build Coastguard Worker };
56*38e8c45fSAndroid Build Coastguard Worker 
57*38e8c45fSAndroid Build Coastguard Worker class Choreographer;
58*38e8c45fSAndroid Build Coastguard Worker 
59*38e8c45fSAndroid Build Coastguard Worker /**
60*38e8c45fSAndroid Build Coastguard Worker  * Implementation of AChoreographerFrameCallbackData.
61*38e8c45fSAndroid Build Coastguard Worker  */
62*38e8c45fSAndroid Build Coastguard Worker struct ChoreographerFrameCallbackDataImpl {
63*38e8c45fSAndroid Build Coastguard Worker     int64_t frameTimeNanos{0};
64*38e8c45fSAndroid Build Coastguard Worker 
65*38e8c45fSAndroid Build Coastguard Worker     VsyncEventData vsyncEventData;
66*38e8c45fSAndroid Build Coastguard Worker 
67*38e8c45fSAndroid Build Coastguard Worker     const Choreographer* choreographer;
68*38e8c45fSAndroid Build Coastguard Worker };
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker class Choreographer : public DisplayEventDispatcher, public MessageHandler {
71*38e8c45fSAndroid Build Coastguard Worker public:
72*38e8c45fSAndroid Build Coastguard Worker     struct Context {
73*38e8c45fSAndroid Build Coastguard Worker         std::mutex lock;
74*38e8c45fSAndroid Build Coastguard Worker         std::vector<Choreographer*> ptrs GUARDED_BY(lock);
75*38e8c45fSAndroid Build Coastguard Worker         std::map<AVsyncId, int64_t> startTimes GUARDED_BY(lock);
76*38e8c45fSAndroid Build Coastguard Worker         bool registeredToDisplayManager GUARDED_BY(lock) = false;
77*38e8c45fSAndroid Build Coastguard Worker 
78*38e8c45fSAndroid Build Coastguard Worker         std::atomic<nsecs_t> mLastKnownVsync = -1;
79*38e8c45fSAndroid Build Coastguard Worker     };
80*38e8c45fSAndroid Build Coastguard Worker     static Context gChoreographers;
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker     explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr)
83*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(gChoreographers.lock);
84*38e8c45fSAndroid Build Coastguard Worker     void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
85*38e8c45fSAndroid Build Coastguard Worker                                   AChoreographer_frameCallback64 cb64,
86*38e8c45fSAndroid Build Coastguard Worker                                   AChoreographer_vsyncCallback vsyncCallback, void* data,
87*38e8c45fSAndroid Build Coastguard Worker                                   nsecs_t delay, CallbackType callbackType);
88*38e8c45fSAndroid Build Coastguard Worker     void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
89*38e8c45fSAndroid Build Coastguard Worker             EXCLUDES(gChoreographers.lock);
90*38e8c45fSAndroid Build Coastguard Worker     void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
91*38e8c45fSAndroid Build Coastguard Worker     // Drains the queue of pending vsync periods and dispatches refresh rate
92*38e8c45fSAndroid Build Coastguard Worker     // updates to callbacks.
93*38e8c45fSAndroid Build Coastguard Worker     // The assumption is that this method is only called on a single
94*38e8c45fSAndroid Build Coastguard Worker     // processing thread, either by looper or by AChoreographer_handleEvents
95*38e8c45fSAndroid Build Coastguard Worker     void handleRefreshRateUpdates();
96*38e8c45fSAndroid Build Coastguard Worker     void scheduleLatestConfigRequest();
97*38e8c45fSAndroid Build Coastguard Worker 
98*38e8c45fSAndroid Build Coastguard Worker     enum {
99*38e8c45fSAndroid Build Coastguard Worker         MSG_SCHEDULE_CALLBACKS = 0,
100*38e8c45fSAndroid Build Coastguard Worker         MSG_SCHEDULE_VSYNC = 1,
101*38e8c45fSAndroid Build Coastguard Worker         MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
102*38e8c45fSAndroid Build Coastguard Worker     };
103*38e8c45fSAndroid Build Coastguard Worker     virtual void handleMessage(const Message& message) override;
104*38e8c45fSAndroid Build Coastguard Worker 
105*38e8c45fSAndroid Build Coastguard Worker     static void initJVM(JNIEnv* env);
106*38e8c45fSAndroid Build Coastguard Worker     static Choreographer* getForThread();
107*38e8c45fSAndroid Build Coastguard Worker     static void signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock);
108*38e8c45fSAndroid Build Coastguard Worker     static int64_t getStartTimeNanosForVsyncId(AVsyncId vsyncId) EXCLUDES(gChoreographers.lock);
109*38e8c45fSAndroid Build Coastguard Worker     virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
110*38e8c45fSAndroid Build Coastguard Worker     int64_t getFrameInterval() const;
111*38e8c45fSAndroid Build Coastguard Worker     bool inCallback() const;
112*38e8c45fSAndroid Build Coastguard Worker     const sp<Looper> getLooper();
113*38e8c45fSAndroid Build Coastguard Worker 
114*38e8c45fSAndroid Build Coastguard Worker private:
115*38e8c45fSAndroid Build Coastguard Worker     Choreographer(const Choreographer&) = delete;
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
118*38e8c45fSAndroid Build Coastguard Worker                        VsyncEventData vsyncEventData) override;
119*38e8c45fSAndroid Build Coastguard Worker     void dispatchCallbacks(const std::vector<FrameCallback>&, VsyncEventData vsyncEventData,
120*38e8c45fSAndroid Build Coastguard Worker                            nsecs_t timestamp);
121*38e8c45fSAndroid Build Coastguard Worker     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
122*38e8c45fSAndroid Build Coastguard Worker     void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) override;
123*38e8c45fSAndroid Build Coastguard Worker     void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
124*38e8c45fSAndroid Build Coastguard Worker                              nsecs_t vsyncPeriod) override;
125*38e8c45fSAndroid Build Coastguard Worker     void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
126*38e8c45fSAndroid Build Coastguard Worker     void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
127*38e8c45fSAndroid Build Coastguard Worker                                     std::vector<FrameRateOverride> overrides) override;
128*38e8c45fSAndroid Build Coastguard Worker     void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
129*38e8c45fSAndroid Build Coastguard Worker                                    int32_t maxLevel) override;
130*38e8c45fSAndroid Build Coastguard Worker     void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) override;
131*38e8c45fSAndroid Build Coastguard Worker 
132*38e8c45fSAndroid Build Coastguard Worker     void scheduleCallbacks();
133*38e8c45fSAndroid Build Coastguard Worker 
134*38e8c45fSAndroid Build Coastguard Worker     ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
135*38e8c45fSAndroid Build Coastguard Worker     void registerStartTime() const;
136*38e8c45fSAndroid Build Coastguard Worker 
137*38e8c45fSAndroid Build Coastguard Worker     std::mutex mLock;
138*38e8c45fSAndroid Build Coastguard Worker     // Protected by mLock
139*38e8c45fSAndroid Build Coastguard Worker     std::priority_queue<FrameCallback> mFrameCallbacks;
140*38e8c45fSAndroid Build Coastguard Worker     std::vector<RefreshRateCallback> mRefreshRateCallbacks;
141*38e8c45fSAndroid Build Coastguard Worker 
142*38e8c45fSAndroid Build Coastguard Worker     nsecs_t mLatestVsyncPeriod = -1;
143*38e8c45fSAndroid Build Coastguard Worker     VsyncEventData mLastVsyncEventData;
144*38e8c45fSAndroid Build Coastguard Worker     bool mInCallback = false;
145*38e8c45fSAndroid Build Coastguard Worker 
146*38e8c45fSAndroid Build Coastguard Worker     const sp<Looper> mLooper;
147*38e8c45fSAndroid Build Coastguard Worker     const std::thread::id mThreadId;
148*38e8c45fSAndroid Build Coastguard Worker 
149*38e8c45fSAndroid Build Coastguard Worker     // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
150*38e8c45fSAndroid Build Coastguard Worker     static constexpr size_t kMaxStartTimes = 250;
151*38e8c45fSAndroid Build Coastguard Worker };
152*38e8c45fSAndroid Build Coastguard Worker 
153*38e8c45fSAndroid Build Coastguard Worker } // namespace android
154