1 /*
2  * Copyright (C) 2015 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 #include <android-base/thread_annotations.h>
18 #include <android/gui/ISurfaceComposer.h>
19 #include <gui/Choreographer.h>
20 #include <jni.h>
21 #include <private/android/choreographer.h>
22 #include <utils/Looper.h>
23 #include <utils/Timers.h>
24 
25 #include <cinttypes>
26 #include <mutex>
27 #include <optional>
28 #include <queue>
29 #include <thread>
30 
31 #undef LOG_TAG
32 #define LOG_TAG "AChoreographer"
33 
34 using namespace android;
35 
AChoreographer_to_Choreographer(AChoreographer * choreographer)36 static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) {
37     return reinterpret_cast<Choreographer*>(choreographer);
38 }
39 
AChoreographer_to_Choreographer(const AChoreographer * choreographer)40 static inline const Choreographer* AChoreographer_to_Choreographer(
41         const AChoreographer* choreographer) {
42     return reinterpret_cast<const Choreographer*>(choreographer);
43 }
44 
45 static inline const ChoreographerFrameCallbackDataImpl*
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(const AChoreographerFrameCallbackData * data)46 AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(
47         const AChoreographerFrameCallbackData* data) {
48     return reinterpret_cast<const ChoreographerFrameCallbackDataImpl*>(data);
49 }
50 
51 // Glue for private C api
52 namespace android {
AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod)53 void AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod) {
54     Choreographer::signalRefreshRateCallbacks(vsyncPeriod);
55 }
56 
AChoreographer_initJVM(JNIEnv * env)57 void AChoreographer_initJVM(JNIEnv* env) {
58     Choreographer::initJVM(env);
59 }
60 
AChoreographer_routeGetInstance()61 AChoreographer* AChoreographer_routeGetInstance() {
62     return AChoreographer_getInstance();
63 }
AChoreographer_routePostFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)64 void AChoreographer_routePostFrameCallback(AChoreographer* choreographer,
65                                            AChoreographer_frameCallback callback, void* data) {
66 #pragma clang diagnostic push
67 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
68     return AChoreographer_postFrameCallback(choreographer, callback, data);
69 #pragma clang diagnostic pop
70 }
AChoreographer_routePostFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)71 void AChoreographer_routePostFrameCallbackDelayed(AChoreographer* choreographer,
72                                                   AChoreographer_frameCallback callback, void* data,
73                                                   long delayMillis) {
74 #pragma clang diagnostic push
75 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
76     return AChoreographer_postFrameCallbackDelayed(choreographer, callback, data, delayMillis);
77 #pragma clang diagnostic pop
78 }
AChoreographer_routePostFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)79 void AChoreographer_routePostFrameCallback64(AChoreographer* choreographer,
80                                              AChoreographer_frameCallback64 callback, void* data) {
81     return AChoreographer_postFrameCallback64(choreographer, callback, data);
82 }
AChoreographer_routePostFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)83 void AChoreographer_routePostFrameCallbackDelayed64(AChoreographer* choreographer,
84                                                     AChoreographer_frameCallback64 callback,
85                                                     void* data, uint32_t delayMillis) {
86     return AChoreographer_postFrameCallbackDelayed64(choreographer, callback, data, delayMillis);
87 }
AChoreographer_routePostVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)88 void AChoreographer_routePostVsyncCallback(AChoreographer* choreographer,
89                                            AChoreographer_vsyncCallback callback, void* data) {
90     return AChoreographer_postVsyncCallback(choreographer, callback, data);
91 }
AChoreographer_routeRegisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)92 void AChoreographer_routeRegisterRefreshRateCallback(AChoreographer* choreographer,
93                                                      AChoreographer_refreshRateCallback callback,
94                                                      void* data) {
95     return AChoreographer_registerRefreshRateCallback(choreographer, callback, data);
96 }
AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)97 void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreographer,
98                                                        AChoreographer_refreshRateCallback callback,
99                                                        void* data) {
100     return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data);
101 }
AChoreographerFrameCallbackData_routeGetFrameTimeNanos(const AChoreographerFrameCallbackData * data)102 int64_t AChoreographerFrameCallbackData_routeGetFrameTimeNanos(
103         const AChoreographerFrameCallbackData* data) {
104     return AChoreographerFrameCallbackData_getFrameTimeNanos(data);
105 }
AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(const AChoreographerFrameCallbackData * data)106 size_t AChoreographerFrameCallbackData_routeGetFrameTimelinesLength(
107         const AChoreographerFrameCallbackData* data) {
108     return AChoreographerFrameCallbackData_getFrameTimelinesLength(data);
109 }
AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)110 size_t AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex(
111         const AChoreographerFrameCallbackData* data) {
112     return AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(data);
113 }
AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)114 AVsyncId AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(
115         const AChoreographerFrameCallbackData* data, size_t index) {
116     return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index);
117 }
AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)118 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentationTimeNanos(
119         const AChoreographerFrameCallbackData* data, size_t index) {
120     return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(data,
121                                                                                          index);
122 }
AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)123 int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
124         const AChoreographerFrameCallbackData* data, size_t index) {
125     return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index);
126 }
127 
AChoreographer_getFrameInterval(const AChoreographer * choreographer)128 int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
129     return AChoreographer_to_Choreographer(choreographer)->getFrameInterval();
130 }
131 
AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId)132 int64_t AChoreographer_getStartTimeNanosForVsyncId(AVsyncId vsyncId) {
133     return Choreographer::getStartTimeNanosForVsyncId(vsyncId);
134 }
135 
136 } // namespace android
137 
138 /* Glue for the NDK interface */
139 
Choreographer_to_AChoreographer(Choreographer * choreographer)140 static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) {
141     return reinterpret_cast<AChoreographer*>(choreographer);
142 }
143 
AChoreographer_getInstance()144 AChoreographer* AChoreographer_getInstance() {
145     return Choreographer_to_AChoreographer(Choreographer::getForThread());
146 }
147 
AChoreographer_postFrameCallback(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data)148 void AChoreographer_postFrameCallback(AChoreographer* choreographer,
149                                       AChoreographer_frameCallback callback, void* data) {
150     AChoreographer_to_Choreographer(choreographer)
151             ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, 0, CALLBACK_ANIMATION);
152 }
AChoreographer_postFrameCallbackDelayed(AChoreographer * choreographer,AChoreographer_frameCallback callback,void * data,long delayMillis)153 void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
154                                              AChoreographer_frameCallback callback, void* data,
155                                              long delayMillis) {
156     AChoreographer_to_Choreographer(choreographer)
157             ->postFrameCallbackDelayed(callback, nullptr, nullptr, data, ms2ns(delayMillis),
158                                        CALLBACK_ANIMATION);
159 }
AChoreographer_postVsyncCallback(AChoreographer * choreographer,AChoreographer_vsyncCallback callback,void * data)160 void AChoreographer_postVsyncCallback(AChoreographer* choreographer,
161                                       AChoreographer_vsyncCallback callback, void* data) {
162     AChoreographer_to_Choreographer(choreographer)
163             ->postFrameCallbackDelayed(nullptr, nullptr, callback, data, 0, CALLBACK_ANIMATION);
164 }
AChoreographer_postFrameCallback64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data)165 void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
166                                         AChoreographer_frameCallback64 callback, void* data) {
167     AChoreographer_to_Choreographer(choreographer)
168             ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, 0, CALLBACK_ANIMATION);
169 }
AChoreographer_postFrameCallbackDelayed64(AChoreographer * choreographer,AChoreographer_frameCallback64 callback,void * data,uint32_t delayMillis)170 void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
171                                                AChoreographer_frameCallback64 callback, void* data,
172                                                uint32_t delayMillis) {
173     AChoreographer_to_Choreographer(choreographer)
174             ->postFrameCallbackDelayed(nullptr, callback, nullptr, data, ms2ns(delayMillis),
175                                        CALLBACK_ANIMATION);
176 }
AChoreographer_registerRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)177 void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer,
178                                                 AChoreographer_refreshRateCallback callback,
179                                                 void* data) {
180     AChoreographer_to_Choreographer(choreographer)->registerRefreshRateCallback(callback, data);
181 }
AChoreographer_unregisterRefreshRateCallback(AChoreographer * choreographer,AChoreographer_refreshRateCallback callback,void * data)182 void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
183                                                   AChoreographer_refreshRateCallback callback,
184                                                   void* data) {
185     AChoreographer_to_Choreographer(choreographer)->unregisterRefreshRateCallback(callback, data);
186 }
187 
AChoreographerFrameCallbackData_getFrameTimeNanos(const AChoreographerFrameCallbackData * data)188 int64_t AChoreographerFrameCallbackData_getFrameTimeNanos(
189         const AChoreographerFrameCallbackData* data) {
190     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
191             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
192     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
193                         "Data is only valid in callback");
194     return frameCallbackData->frameTimeNanos;
195 }
AChoreographerFrameCallbackData_getFrameTimelinesLength(const AChoreographerFrameCallbackData * data)196 size_t AChoreographerFrameCallbackData_getFrameTimelinesLength(
197         const AChoreographerFrameCallbackData* data) {
198     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
199             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
200     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
201                         "Data is only valid in callback");
202     return frameCallbackData->vsyncEventData.frameTimelinesLength;
203 }
AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(const AChoreographerFrameCallbackData * data)204 size_t AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex(
205         const AChoreographerFrameCallbackData* data) {
206     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
207             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
208     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
209                         "Data is only valid in callback");
210     return frameCallbackData->vsyncEventData.preferredFrameTimelineIndex;
211 }
AChoreographerFrameCallbackData_getFrameTimelineVsyncId(const AChoreographerFrameCallbackData * data,size_t index)212 AVsyncId AChoreographerFrameCallbackData_getFrameTimelineVsyncId(
213         const AChoreographerFrameCallbackData* data, size_t index) {
214     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
215             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
216     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
217                         "Data is only valid in callback");
218     LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
219     return frameCallbackData->vsyncEventData.frameTimelines[index].vsyncId;
220 }
AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(const AChoreographerFrameCallbackData * data,size_t index)221 int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentationTimeNanos(
222         const AChoreographerFrameCallbackData* data, size_t index) {
223     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
224             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
225     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
226                         "Data is only valid in callback");
227     LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
228     return frameCallbackData->vsyncEventData.frameTimelines[index].expectedPresentationTime;
229 }
AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(const AChoreographerFrameCallbackData * data,size_t index)230 int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
231         const AChoreographerFrameCallbackData* data, size_t index) {
232     const ChoreographerFrameCallbackDataImpl* frameCallbackData =
233             AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
234     LOG_ALWAYS_FATAL_IF(!frameCallbackData->choreographer->inCallback(),
235                         "Data is only valid in callback");
236     LOG_ALWAYS_FATAL_IF(index >= VsyncEventData::kFrameTimelinesCapacity, "Index out of bounds");
237     return frameCallbackData->vsyncEventData.frameTimelines[index].deadlineTimestamp;
238 }
239 
AChoreographer_create()240 AChoreographer* AChoreographer_create() {
241     Choreographer* choreographer = new Choreographer(nullptr);
242     status_t result = choreographer->initialize();
243     if (result != OK) {
244         ALOGW("Failed to initialize");
245         return nullptr;
246     }
247     return Choreographer_to_AChoreographer(choreographer);
248 }
249 
AChoreographer_destroy(AChoreographer * choreographer)250 void AChoreographer_destroy(AChoreographer* choreographer) {
251     if (choreographer == nullptr) {
252         return;
253     }
254 
255     delete AChoreographer_to_Choreographer(choreographer);
256 }
257 
AChoreographer_getFd(const AChoreographer * choreographer)258 int AChoreographer_getFd(const AChoreographer* choreographer) {
259     return AChoreographer_to_Choreographer(choreographer)->getFd();
260 }
261 
AChoreographer_handlePendingEvents(AChoreographer * choreographer,void * data)262 void AChoreographer_handlePendingEvents(AChoreographer* choreographer, void* data) {
263     // Pass dummy fd and events args to handleEvent, since the underlying
264     // DisplayEventDispatcher doesn't need them outside of validating that a
265     // Looper instance didn't break, but these args circumvent those checks.
266     Choreographer* impl = AChoreographer_to_Choreographer(choreographer);
267     impl->handleEvent(-1, Looper::EVENT_INPUT, data);
268 }
269