android_view_DisplayEventReceiver.cpp revision 58aedbc9bea13415e2d42cf7c9fe8a7efd243e66
10a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown/* 20a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Copyright (C) 2011 The Android Open Source Project 30a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * 40a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 50a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * you may not use this file except in compliance with the License. 60a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * You may obtain a copy of the License at 70a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * 80a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * http://www.apache.org/licenses/LICENSE-2.0 90a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * 100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * Unless required by applicable law or agreed to in writing, software 110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * See the License for the specific language governing permissions and 140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown * limitations under the License. 150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown */ 160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define LOG_TAG "DisplayEventReceiver" 180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown//#define LOG_NDEBUG 0 200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include "JNIHelp.h" 230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include <android_runtime/AndroidRuntime.h> 250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include <utils/Log.h> 260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include <utils/Looper.h> 270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include <utils/threads.h> 280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include <gui/DisplayEventReceiver.h> 290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#include "android_os_MessageQueue.h" 300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownnamespace android { 320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown// Number of events to read at a time from the DisplayEventReceiver pipe. 340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown// The value should be large enough that we can quickly drain the pipe 350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown// using just a few large reads. 360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic const size_t EVENT_BUFFER_SIZE = 100; 370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic struct { 390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jclass clazz; 400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jmethodID dispatchVsync; 420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} gDisplayEventReceiverClassInfo; 430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownclass NativeDisplayEventReceiver : public RefBase { 460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownpublic: 470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown NativeDisplayEventReceiver(JNIEnv* env, 480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jobject receiverObj, const sp<Looper>& looper); 490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown status_t initialize(); 510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown status_t scheduleVsync(); 520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown static int handleReceiveCallback(int receiveFd, int events, void* data); 530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprotected: 550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown virtual ~NativeDisplayEventReceiver(); 560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprivate: 580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jobject mReceiverObjGlobal; 590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<Looper> mLooper; 600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown DisplayEventReceiver mReceiver; 610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown bool mWaitingForVsync; 620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}; 630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env, 660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jobject receiverObj, const sp<Looper>& looper) : 670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown mReceiverObjGlobal(env->NewGlobalRef(receiverObj)), 6858aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown mLooper(looper), mWaitingForVsync(false) { 690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ALOGV("receiver %p ~ Initializing input event receiver.", this); 700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::~NativeDisplayEventReceiver() { 730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ALOGV("receiver %p ~ Disposing display event receiver.", this); 740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 7558aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown if (!mReceiver.initCheck()) { 760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown mLooper->removeFd(mReceiver.getFd()); 770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 790a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 800a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown env->DeleteGlobalRef(mReceiverObjGlobal); 810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::initialize() { 840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown status_t result = mReceiver.initCheck(); 850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (result) { 868564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Failed to initialize display event receiver, status=%d", result); 870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return result; 880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 9058aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown int rc = mLooper->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT, 9158aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown handleReceiveCallback, this); 9258aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown if (rc < 0) { 9358aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown return UNKNOWN_ERROR; 9458aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown } 950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return OK; 960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::scheduleVsync() { 990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (!mWaitingForVsync) { 1000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ALOGV("receiver %p ~ Scheduling vsync.", this); 1010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown // Drain all pending events. 1030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; 1040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ssize_t n; 1050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { 1060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ALOGV("receiver %p ~ Drained %d events.", this, int(n)); 1070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (n < 0) { 1108564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Failed to drain events from display event receiver, status=%d", status_t(n)); 1110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return status_t(n); 1120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1146779df2c28a68616134b1988f009221652d9f2adMathias Agopian status_t status = mReceiver.requestNextVsync(); 1156779df2c28a68616134b1988f009221652d9f2adMathias Agopian if (status) { 1168564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Failed to request next vsync, status=%d", status); 1176779df2c28a68616134b1988f009221652d9f2adMathias Agopian return status; 1186779df2c28a68616134b1988f009221652d9f2adMathias Agopian } 1196779df2c28a68616134b1988f009221652d9f2adMathias Agopian 1200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown mWaitingForVsync = true; 1210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return OK; 1230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 1240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint NativeDisplayEventReceiver::handleReceiveCallback(int receiveFd, int events, void* data) { 1260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<NativeDisplayEventReceiver> r = static_cast<NativeDisplayEventReceiver*>(data); 1270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { 1293762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("Display event receiver pipe was closed or an error occurred. " 1300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown "events=0x%x", events); 1310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 0; // remove the callback 1320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (!(events & ALOOPER_EVENT_INPUT)) { 1358564c8da817a845353d213acd8636b76f567b234Steve Block ALOGW("Received spurious callback for unhandled poll event. " 1360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown "events=0x%x", events); 1370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 1; // keep the callback 1380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown // Drain all pending events, keep the last vsync. 1410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown nsecs_t vsyncTimestamp = -1; 1420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown uint32_t vsyncCount = 0; 1430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; 1450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ssize_t n; 1460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown while ((n = r->mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { 14758aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown ALOGV("receiver %p ~ Read %d events.", data, int(n)); 1480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown while (n-- > 0) { 1490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (buf[n].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { 1500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown vsyncTimestamp = buf[n].header.timestamp; 1510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown vsyncCount = buf[n].vsync.count; 1520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown break; // stop at last vsync in the buffer 1530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (vsyncTimestamp < 0) { 15858aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", data); 1590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 1; // keep the callback, did not obtain a vsync pulse 1600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, count=%d", 16358aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown data, vsyncTimestamp, vsyncCount); 1640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown r->mWaitingForVsync = false; 1650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown JNIEnv* env = AndroidRuntime::getJNIEnv(); 1670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 16858aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown ALOGV("receiver %p ~ Invoking vsync handler.", data); 1690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown env->CallVoidMethod(r->mReceiverObjGlobal, 1700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount); 17158aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown ALOGV("receiver %p ~ Returned from vsync handler.", data); 1720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (env->ExceptionCheck()) { 1743762c311729fe9f3af085c14c5c1fb471d994c03Steve Block ALOGE("An exception occurred while dispatching a vsync event."); 1750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown LOGE_EX(env); 1760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown env->ExceptionClear(); 1770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 17958aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown return 1; // keep the callback 1800a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 1810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj, 1840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jobject messageQueueObj) { 1850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj); 1860a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (looper == NULL) { 1870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jniThrowRuntimeException(env, "MessageQueue is not initialized."); 1880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 0; 1890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 1900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 1910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env, 1920a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown receiverObj, looper); 1930a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown status_t status = receiver->initialize(); 1940a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (status) { 1950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown String8 message; 1960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown message.appendFormat("Failed to initialize display event receiver. status=%d", status); 1970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jniThrowRuntimeException(env, message.string()); 1980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 0; 1990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 2000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object 2020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return reinterpret_cast<jint>(receiver.get()); 2030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 2040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) { 2060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<NativeDisplayEventReceiver> receiver = 2070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr); 2080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object 2090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 2100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeScheduleVsync(JNIEnv* env, jclass clazz, jint receiverPtr) { 2120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown sp<NativeDisplayEventReceiver> receiver = 2130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr); 2140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown status_t status = receiver->scheduleVsync(); 2150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown if (status) { 2160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown String8 message; 2170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown message.appendFormat("Failed to schedule next vertical sync pulse. status=%d", status); 2180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown jniThrowRuntimeException(env, message.string()); 2190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown } 2200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 2210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic JNINativeMethod gMethods[] = { 2240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown /* name, signature, funcPtr */ 2250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown { "nativeInit", 2260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)I", 2270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown (void*)nativeInit }, 2280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown { "nativeDispose", 2290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown "(I)V", 2300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown (void*)nativeDispose }, 2310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown { "nativeScheduleVsync", "(I)V", 2320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown (void*)nativeScheduleVsync } 2330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}; 2340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define FIND_CLASS(var, className) \ 2360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown var = env->FindClass(className); \ 2370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown LOG_FATAL_IF(! var, "Unable to find class " className); \ 2380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown var = jclass(env->NewGlobalRef(var)); 2390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 2410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 2420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown LOG_FATAL_IF(! var, "Unable to find method " methodName); 2430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint register_android_view_DisplayEventReceiver(JNIEnv* env) { 2450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown int res = jniRegisterNativeMethods(env, "android/view/DisplayEventReceiver", 2460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown gMethods, NELEM(gMethods)); 2470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 2480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown FIND_CLASS(gDisplayEventReceiverClassInfo.clazz, "android/view/DisplayEventReceiver"); 2500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchVsync, 2520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown gDisplayEventReceiverClassInfo.clazz, 2530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown "dispatchVsync", "(JI)V"); 2540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown return 0; 2550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} 2560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown 2570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} // namespace android 258