• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
85     void postFrameCallbackDelayed(AChoreographer_frameCallback cb,
86                                   AChoreographer_frameCallback64 cb64,
87                                   AChoreographer_vsyncCallback vsyncCallback, void* data,
88                                   nsecs_t delay, CallbackType callbackType);
89     void registerRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data)
90             EXCLUDES(gChoreographers.lock);
91     void unregisterRefreshRateCallback(AChoreographer_refreshRateCallback cb, void* data);
92     // Drains the queue of pending vsync periods and dispatches refresh rate
93     // updates to callbacks.
94     // The assumption is that this method is only called on a single
95     // processing thread, either by looper or by AChoreographer_handleEvents
96     void handleRefreshRateUpdates();
97     void scheduleLatestConfigRequest();
98 
99     enum {
100         MSG_SCHEDULE_CALLBACKS = 0,
101         MSG_SCHEDULE_VSYNC = 1,
102         MSG_HANDLE_REFRESH_RATE_UPDATES = 2,
103     };
104     virtual void handleMessage(const Message& message) override;
105 
106     static void initJVM(JNIEnv* env);
107     static sp<Choreographer> getForThread();
108     static void signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock);
109     static int64_t getStartTimeNanosForVsyncId(AVsyncId vsyncId) EXCLUDES(gChoreographers.lock);
110     virtual ~Choreographer() override EXCLUDES(gChoreographers.lock);
111     int64_t getFrameInterval() const;
112     bool inCallback() const;
113     const sp<Looper> getLooper();
114 
115 private:
116     Choreographer(const Choreographer&) = delete;
117 
118     void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
119                        VsyncEventData vsyncEventData) override;
120     void dispatchCallbacks(const std::vector<FrameCallback>&, VsyncEventData vsyncEventData,
121                            nsecs_t timestamp);
122     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
123     void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) override;
124     void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
125                              nsecs_t vsyncPeriod) override;
126     void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
127     void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
128                                     std::vector<FrameRateOverride> overrides) override;
129     void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel,
130                                    int32_t maxLevel) override;
131     void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) override;
132 
133     void scheduleCallbacks();
134 
135     ChoreographerFrameCallbackDataImpl createFrameCallbackData(nsecs_t timestamp) const;
136     void registerStartTime() const;
137 
138     std::mutex mLock;
139     // Protected by mLock
140     std::priority_queue<FrameCallback> mFrameCallbacks;
141     std::vector<RefreshRateCallback> mRefreshRateCallbacks;
142 
143     nsecs_t mLatestVsyncPeriod = -1;
144     VsyncEventData mLastVsyncEventData;
145     bool mInCallback = false;
146 
147     const sp<Looper> mLooper;
148     const std::thread::id mThreadId;
149 
150     // Approximation of num_threads_using_choreographer * num_frames_of_history with leeway.
151     static constexpr size_t kMaxStartTimes = 250;
152 };
153 
154 } // namespace android
155