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