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