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