1 /*
2 * Copyright (C) 2011 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 #define LOG_TAG "DisplayEventReceiver"
18
19 //#define LOG_NDEBUG 0
20
21 #include <android_runtime/AndroidRuntime.h>
22 #include <android_runtime/Log.h>
23 #include <gui/DisplayEventDispatcher.h>
24 #include <inttypes.h>
25 #include <nativehelper/JNIHelp.h>
26 #include <nativehelper/ScopedLocalRef.h>
27 #include <utils/Log.h>
28 #include <utils/Looper.h>
29 #include <utils/threads.h>
30
31 #include "android_os_MessageQueue.h"
32 #include "core_jni_helpers.h"
33
34 namespace android {
35
36 static struct {
37 jclass clazz;
38
39 jmethodID dispatchVsync;
40 jmethodID dispatchHotplug;
41 jmethodID dispatchHotplugConnectionError;
42 jmethodID dispatchModeChanged;
43 jmethodID dispatchFrameRateOverrides;
44 jmethodID dispatchHdcpLevelsChanged;
45
46 struct {
47 jclass clazz;
48 jmethodID init;
49 } frameRateOverrideClassInfo;
50
51 struct {
52 jclass clazz;
53
54 jmethodID init;
55
56 jfieldID vsyncId;
57 jfieldID expectedPresentationTime;
58 jfieldID deadline;
59 } frameTimelineClassInfo;
60
61 struct {
62 jclass clazz;
63
64 jmethodID init;
65
66 jfieldID frameInterval;
67 jfieldID preferredFrameTimelineIndex;
68 jfieldID frameTimelinesLength;
69 jfieldID frameTimelines;
70 } vsyncEventDataClassInfo;
71
72 } gDisplayEventReceiverClassInfo;
73
74
75 class NativeDisplayEventReceiver : public DisplayEventDispatcher {
76 public:
77 NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak, jobject vsyncEventDataWeak,
78 const sp<MessageQueue>& messageQueue, jint vsyncSource,
79 jint eventRegistration, jlong layerHandle);
80
81 void dispose();
82
83 protected:
84 virtual ~NativeDisplayEventReceiver();
85
86 private:
87 jobject mReceiverWeakGlobal;
88 jobject mVsyncEventDataWeakGlobal;
89 sp<MessageQueue> mMessageQueue;
90
91 void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
92 VsyncEventData vsyncEventData) override;
93 void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
94 void dispatchHotplugConnectionError(nsecs_t timestamp, int errorCode) override;
95 void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
96 nsecs_t renderPeriod) override;
97 void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
98 std::vector<FrameRateOverride> overrides) override;
dispatchNullEvent(nsecs_t timestamp,PhysicalDisplayId displayId)99 void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) override {}
100 void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int connectedLevel,
101 int maxLevel) override;
102 };
103
NativeDisplayEventReceiver(JNIEnv * env,jobject receiverWeak,jobject vsyncEventDataWeak,const sp<MessageQueue> & messageQueue,jint vsyncSource,jint eventRegistration,jlong layerHandle)104 NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, jobject receiverWeak,
105 jobject vsyncEventDataWeak,
106 const sp<MessageQueue>& messageQueue,
107 jint vsyncSource, jint eventRegistration,
108 jlong layerHandle)
109 : DisplayEventDispatcher(messageQueue->getLooper(),
110 static_cast<gui::ISurfaceComposer::VsyncSource>(vsyncSource),
111 static_cast<gui::ISurfaceComposer::EventRegistration>(
112 eventRegistration),
113 layerHandle != 0 ? sp<IBinder>::fromExisting(
114 reinterpret_cast<IBinder*>(layerHandle))
115 : nullptr),
116 mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
117 mVsyncEventDataWeakGlobal(env->NewGlobalRef(vsyncEventDataWeak)),
118 mMessageQueue(messageQueue) {
119 ALOGV("receiver %p ~ Initializing display event receiver.", this);
120 }
121
~NativeDisplayEventReceiver()122 NativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
123 JNIEnv* env = AndroidRuntime::getJNIEnv();
124 env->DeleteGlobalRef(mReceiverWeakGlobal);
125 ALOGV("receiver %p ~ dtor display event receiver.", this);
126 }
127
dispose()128 void NativeDisplayEventReceiver::dispose() {
129 ALOGV("receiver %p ~ Disposing display event receiver.", this);
130 DisplayEventDispatcher::dispose();
131 }
132
createJavaVsyncEventData(JNIEnv * env,VsyncEventData vsyncEventData)133 static jobject createJavaVsyncEventData(JNIEnv* env, VsyncEventData vsyncEventData) {
134 ScopedLocalRef<jobjectArray>
135 frameTimelineObjs(env,
136 env->NewObjectArray(vsyncEventData.frameTimelinesLength,
137 gDisplayEventReceiverClassInfo
138 .frameTimelineClassInfo.clazz,
139 /*initial element*/ NULL));
140 if (!frameTimelineObjs.get() || env->ExceptionCheck()) {
141 ALOGW("%s: Failed to create FrameTimeline array", __func__);
142 LOGW_EX(env);
143 env->ExceptionClear();
144 return NULL;
145 }
146 for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
147 VsyncEventData::FrameTimeline frameTimeline = vsyncEventData.frameTimelines[i];
148 ScopedLocalRef<jobject>
149 frameTimelineObj(env,
150 env->NewObject(gDisplayEventReceiverClassInfo
151 .frameTimelineClassInfo.clazz,
152 gDisplayEventReceiverClassInfo
153 .frameTimelineClassInfo.init,
154 frameTimeline.vsyncId,
155 frameTimeline.expectedPresentationTime,
156 frameTimeline.deadlineTimestamp));
157 if (!frameTimelineObj.get() || env->ExceptionCheck()) {
158 ALOGW("%s: Failed to create FrameTimeline object", __func__);
159 LOGW_EX(env);
160 env->ExceptionClear();
161 return NULL;
162 }
163 env->SetObjectArrayElement(frameTimelineObjs.get(), i, frameTimelineObj.get());
164 }
165 return env->NewObject(gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
166 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.init,
167 frameTimelineObjs.get(), vsyncEventData.preferredFrameTimelineIndex,
168 vsyncEventData.frameTimelinesLength, vsyncEventData.frameInterval);
169 }
170
dispatchVsync(nsecs_t timestamp,PhysicalDisplayId displayId,uint32_t count,VsyncEventData vsyncEventData)171 void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId,
172 uint32_t count, VsyncEventData vsyncEventData) {
173 JNIEnv* env = AndroidRuntime::getJNIEnv();
174
175 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
176 ScopedLocalRef<jobject> vsyncEventDataObj(env, GetReferent(env, mVsyncEventDataWeakGlobal));
177 if (receiverObj.get() && vsyncEventDataObj.get()) {
178 ALOGV("receiver %p ~ Invoking vsync handler.", this);
179
180 env->SetIntField(vsyncEventDataObj.get(),
181 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
182 .preferredFrameTimelineIndex,
183 vsyncEventData.preferredFrameTimelineIndex);
184 env->SetIntField(vsyncEventDataObj.get(),
185 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo
186 .frameTimelinesLength,
187 vsyncEventData.frameTimelinesLength);
188 env->SetLongField(vsyncEventDataObj.get(),
189 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval,
190 vsyncEventData.frameInterval);
191
192 ScopedLocalRef<jobjectArray>
193 frameTimelinesObj(env,
194 reinterpret_cast<jobjectArray>(
195 env->GetObjectField(vsyncEventDataObj.get(),
196 gDisplayEventReceiverClassInfo
197 .vsyncEventDataClassInfo
198 .frameTimelines)));
199 for (size_t i = 0; i < vsyncEventData.frameTimelinesLength; i++) {
200 VsyncEventData::FrameTimeline& frameTimeline = vsyncEventData.frameTimelines[i];
201 ScopedLocalRef<jobject>
202 frameTimelineObj(env, env->GetObjectArrayElement(frameTimelinesObj.get(), i));
203 env->SetLongField(frameTimelineObj.get(),
204 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.vsyncId,
205 frameTimeline.vsyncId);
206 env->SetLongField(frameTimelineObj.get(),
207 gDisplayEventReceiverClassInfo.frameTimelineClassInfo
208 .expectedPresentationTime,
209 frameTimeline.expectedPresentationTime);
210 env->SetLongField(frameTimelineObj.get(),
211 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.deadline,
212 frameTimeline.deadlineTimestamp);
213 }
214
215 env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchVsync,
216 timestamp, displayId.value, count);
217 ALOGV("receiver %p ~ Returned from vsync handler.", this);
218 }
219
220 mMessageQueue->raiseAndClearException(env, "dispatchVsync");
221 }
222
dispatchHotplug(nsecs_t timestamp,PhysicalDisplayId displayId,bool connected)223 void NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
224 bool connected) {
225 JNIEnv* env = AndroidRuntime::getJNIEnv();
226
227 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
228 if (receiverObj.get()) {
229 ALOGV("receiver %p ~ Invoking hotplug handler.", this);
230 env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchHotplug,
231 timestamp, displayId.value, connected);
232 ALOGV("receiver %p ~ Returned from hotplug handler.", this);
233 }
234
235 mMessageQueue->raiseAndClearException(env, "dispatchHotplug");
236 }
237
dispatchHotplugConnectionError(nsecs_t timestamp,int connectionError)238 void NativeDisplayEventReceiver::dispatchHotplugConnectionError(nsecs_t timestamp,
239 int connectionError) {
240 JNIEnv* env = AndroidRuntime::getJNIEnv();
241
242 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
243 if (receiverObj.get()) {
244 ALOGV("receiver %p ~ Invoking hotplug dispatchHotplugConnectionError handler.", this);
245 env->CallVoidMethod(receiverObj.get(),
246 gDisplayEventReceiverClassInfo.dispatchHotplugConnectionError,
247 timestamp, connectionError);
248 ALOGV("receiver %p ~ Returned from hotplug dispatchHotplugConnectionError handler.", this);
249 }
250
251 mMessageQueue->raiseAndClearException(env, "dispatchHotplugConnectionError");
252 }
253
dispatchModeChanged(nsecs_t timestamp,PhysicalDisplayId displayId,int32_t modeId,nsecs_t renderPeriod)254 void NativeDisplayEventReceiver::dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
255 int32_t modeId, nsecs_t renderPeriod) {
256 JNIEnv* env = AndroidRuntime::getJNIEnv();
257
258 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
259 if (receiverObj.get()) {
260 ALOGV("receiver %p ~ Invoking mode changed handler.", this);
261 env->CallVoidMethod(receiverObj.get(), gDisplayEventReceiverClassInfo.dispatchModeChanged,
262 timestamp, displayId.value, modeId, renderPeriod);
263 ALOGV("receiver %p ~ Returned from mode changed handler.", this);
264 }
265
266 mMessageQueue->raiseAndClearException(env, "dispatchModeChanged");
267 }
268
dispatchFrameRateOverrides(nsecs_t timestamp,PhysicalDisplayId displayId,std::vector<FrameRateOverride> overrides)269 void NativeDisplayEventReceiver::dispatchFrameRateOverrides(
270 nsecs_t timestamp, PhysicalDisplayId displayId, std::vector<FrameRateOverride> overrides) {
271 JNIEnv* env = AndroidRuntime::getJNIEnv();
272
273 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
274 if (receiverObj.get()) {
275 ALOGV("receiver %p ~ Invoking FrameRateOverride handler.", this);
276 const auto frameRateOverrideClass =
277 gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.clazz;
278 const auto frameRateOverrideInit =
279 gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.init;
280 auto frameRateOverrideInitObject =
281 env->NewObject(frameRateOverrideClass, frameRateOverrideInit, 0, 0);
282 auto frameRateOverrideArray = env->NewObjectArray(overrides.size(), frameRateOverrideClass,
283 frameRateOverrideInitObject);
284 for (size_t i = 0; i < overrides.size(); i++) {
285 auto FrameRateOverrideObject =
286 env->NewObject(frameRateOverrideClass, frameRateOverrideInit, overrides[i].uid,
287 overrides[i].frameRateHz);
288 env->SetObjectArrayElement(frameRateOverrideArray, i, FrameRateOverrideObject);
289 }
290
291 env->CallVoidMethod(receiverObj.get(),
292 gDisplayEventReceiverClassInfo.dispatchFrameRateOverrides, timestamp,
293 displayId.value, frameRateOverrideArray);
294 ALOGV("receiver %p ~ Returned from FrameRateOverride handler.", this);
295 }
296
297 mMessageQueue->raiseAndClearException(env, "dispatchModeChanged");
298 }
299
dispatchHdcpLevelsChanged(PhysicalDisplayId displayId,int connectedLevel,int maxLevel)300 void NativeDisplayEventReceiver::dispatchHdcpLevelsChanged(PhysicalDisplayId displayId,
301 int connectedLevel, int maxLevel) {
302 JNIEnv* env = AndroidRuntime::getJNIEnv();
303
304 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
305 if (receiverObj.get()) {
306 ALOGV("receiver %p ~ Invoking hdcp levels changed handler.", this);
307 env->CallVoidMethod(receiverObj.get(),
308 gDisplayEventReceiverClassInfo.dispatchHdcpLevelsChanged,
309 displayId.value, connectedLevel, maxLevel);
310 ALOGV("receiver %p ~ Returned from hdcp levels changed handler.", this);
311 }
312
313 mMessageQueue->raiseAndClearException(env, "dispatchHdcpLevelsChanged");
314 }
315
nativeInit(JNIEnv * env,jclass clazz,jobject receiverWeak,jobject vsyncEventDataWeak,jobject messageQueueObj,jint vsyncSource,jint eventRegistration,jlong layerHandle)316 static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak, jobject vsyncEventDataWeak,
317 jobject messageQueueObj, jint vsyncSource, jint eventRegistration,
318 jlong layerHandle) {
319 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
320 if (messageQueue == NULL) {
321 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
322 return 0;
323 }
324
325 sp<NativeDisplayEventReceiver> receiver =
326 new NativeDisplayEventReceiver(env, receiverWeak, vsyncEventDataWeak, messageQueue,
327 vsyncSource, eventRegistration, layerHandle);
328 status_t status = receiver->initialize();
329 if (status) {
330 String8 message;
331 message.appendFormat("Failed to initialize display event receiver. status=%d", status);
332 jniThrowRuntimeException(env, message.c_str());
333 return 0;
334 }
335
336 receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
337 return reinterpret_cast<jlong>(receiver.get());
338 }
339
release(NativeDisplayEventReceiver * receiver)340 static void release(NativeDisplayEventReceiver* receiver) {
341 receiver->dispose();
342 receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
343 }
344
nativeGetDisplayEventReceiverFinalizer(JNIEnv *,jclass)345 static jlong nativeGetDisplayEventReceiverFinalizer(JNIEnv*, jclass) {
346 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&release));
347 }
348
nativeScheduleVsync(JNIEnv * env,jclass clazz,jlong receiverPtr)349 static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
350 sp<NativeDisplayEventReceiver> receiver =
351 reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
352 status_t status = receiver->scheduleVsync();
353 if (status) {
354 String8 message;
355 message.appendFormat("Failed to schedule next vertical sync pulse. status=%d", status);
356 jniThrowRuntimeException(env, message.c_str());
357 }
358 }
359
nativeGetLatestVsyncEventData(JNIEnv * env,jclass clazz,jlong receiverPtr)360 static jobject nativeGetLatestVsyncEventData(JNIEnv* env, jclass clazz, jlong receiverPtr) {
361 sp<NativeDisplayEventReceiver> receiver =
362 reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
363 gui::ParcelableVsyncEventData parcelableVsyncEventData;
364 status_t status = receiver->getLatestVsyncEventData(&parcelableVsyncEventData);
365 if (status) {
366 ALOGW("Failed to get latest vsync event data from surface flinger");
367 return NULL;
368 }
369 return createJavaVsyncEventData(env, parcelableVsyncEventData.vsync);
370 }
371
372 static const JNINativeMethod gMethods[] = {
373 /* name, signature, funcPtr */
374 {"nativeInit",
375 "(Ljava/lang/ref/WeakReference;Ljava/lang/ref/WeakReference;Landroid/os/"
376 "MessageQueue;IIJ)J",
377 (void*)nativeInit},
378 {"nativeGetDisplayEventReceiverFinalizer", "()J",
379 (void*)nativeGetDisplayEventReceiverFinalizer},
380 // @FastNative
381 {"nativeScheduleVsync", "(J)V", (void*)nativeScheduleVsync},
382 {"nativeGetLatestVsyncEventData", "(J)Landroid/view/DisplayEventReceiver$VsyncEventData;",
383 (void*)nativeGetLatestVsyncEventData}};
384
register_android_view_DisplayEventReceiver(JNIEnv * env)385 int register_android_view_DisplayEventReceiver(JNIEnv* env) {
386 int res = RegisterMethodsOrDie(env, "android/view/DisplayEventReceiver", gMethods,
387 NELEM(gMethods));
388
389 jclass clazz = FindClassOrDie(env, "android/view/DisplayEventReceiver");
390 gDisplayEventReceiverClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
391
392 gDisplayEventReceiverClassInfo.dispatchVsync =
393 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchVsync", "(JJI)V");
394 gDisplayEventReceiverClassInfo.dispatchHotplug =
395 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchHotplug",
396 "(JJZ)V");
397 gDisplayEventReceiverClassInfo.dispatchHotplugConnectionError =
398 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz,
399 "dispatchHotplugConnectionError", "(JI)V");
400 gDisplayEventReceiverClassInfo.dispatchModeChanged =
401 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchModeChanged",
402 "(JJIJ)V");
403 gDisplayEventReceiverClassInfo.dispatchFrameRateOverrides =
404 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz,
405 "dispatchFrameRateOverrides",
406 "(JJ[Landroid/view/DisplayEventReceiver$FrameRateOverride;)V");
407 gDisplayEventReceiverClassInfo.dispatchHdcpLevelsChanged =
408 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.clazz, "dispatchHdcpLevelsChanged",
409 "(JII)V");
410
411 jclass frameRateOverrideClazz =
412 FindClassOrDie(env, "android/view/DisplayEventReceiver$FrameRateOverride");
413 gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.clazz =
414 MakeGlobalRefOrDie(env, frameRateOverrideClazz);
415 gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.init =
416 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.frameRateOverrideClassInfo.clazz,
417 "<init>", "(IF)V");
418
419 jclass frameTimelineClazz =
420 FindClassOrDie(env, "android/view/DisplayEventReceiver$VsyncEventData$FrameTimeline");
421 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz =
422 MakeGlobalRefOrDie(env, frameTimelineClazz);
423 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.init =
424 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
425 "<init>", "(JJJ)V");
426 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.vsyncId =
427 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
428 "vsyncId", "J");
429 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.expectedPresentationTime =
430 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
431 "expectedPresentationTime", "J");
432 gDisplayEventReceiverClassInfo.frameTimelineClassInfo.deadline =
433 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.frameTimelineClassInfo.clazz,
434 "deadline", "J");
435
436 jclass vsyncEventDataClazz =
437 FindClassOrDie(env, "android/view/DisplayEventReceiver$VsyncEventData");
438 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz =
439 MakeGlobalRefOrDie(env, vsyncEventDataClazz);
440 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.init =
441 GetMethodIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
442 "<init>",
443 "([Landroid/view/"
444 "DisplayEventReceiver$VsyncEventData$FrameTimeline;IIJ)V");
445
446 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.preferredFrameTimelineIndex =
447 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
448 "preferredFrameTimelineIndex", "I");
449 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameTimelinesLength =
450 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
451 "frameTimelinesLength", "I");
452 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameInterval =
453 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
454 "frameInterval", "J");
455 gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.frameTimelines =
456 GetFieldIDOrDie(env, gDisplayEventReceiverClassInfo.vsyncEventDataClassInfo.clazz,
457 "frameTimelines",
458 "[Landroid/view/DisplayEventReceiver$VsyncEventData$FrameTimeline;");
459
460 return res;
461 }
462
463 } // namespace android
464