android_view_DisplayEventReceiver.cpp revision 0a0a1248cfc03940174cbd9af677bafd7280a3bc
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    bool mFdCallbackRegistered;
630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jobject receiverObj, const sp<Looper>& looper) :
680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mLooper(looper), mWaitingForVsync(false), mFdCallbackRegistered(false) {
700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Initializing input event receiver.", this);
710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Disposing display event receiver.", this);
750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (mFdCallbackRegistered) {
770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mLooper->removeFd(mReceiver.getFd());
780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
790a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
800a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    env->DeleteGlobalRef(mReceiverObjGlobal);
820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::initialize() {
850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t result = mReceiver.initCheck();
860a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (result) {
870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGW("Failed to initialize display event receiver, status=%d", result);
880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return result;
890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
920a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
930a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
940a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::scheduleVsync() {
950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (!mWaitingForVsync) {
960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ALOGV("receiver %p ~ Scheduling vsync.", this);
970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        // Drain all pending events.
990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
1000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ssize_t n;
1010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
1020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            ALOGV("receiver %p ~ Drained %d events.", this, int(n));
1030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
1040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (n < 0) {
1060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            LOGW("Failed to drain events from display event receiver, status=%d", status_t(n));
1070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            return status_t(n);
1080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
1090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        if (!mFdCallbackRegistered) {
1110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            int rc = mLooper->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
1120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                    handleReceiveCallback, this);
1130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            if (rc < 0) {
1140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                return UNKNOWN_ERROR;
1150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            }
1160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            mFdCallbackRegistered = true;
1170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        }
1180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mWaitingForVsync = true;
1200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
1220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint NativeDisplayEventReceiver::handleReceiveCallback(int receiveFd, int events, void* data) {
1250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> r = static_cast<NativeDisplayEventReceiver*>(data);
1260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
1280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGE("Display event receiver pipe was closed or an error occurred.  "
1290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                "events=0x%x", events);
1300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        r->mFdCallbackRegistered = false;
1310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0; // remove the callback
1320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
1350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGW("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) {
1470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ALOGV("receiver %p ~ Read %d events.", this, 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) {
1580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", this);
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",
1630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            this, vsyncTimestamp, vsyncCount);
1640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    r->mWaitingForVsync = false;
1650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
1670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Invoking vsync handler.", this);
1690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    env->CallVoidMethod(r->mReceiverObjGlobal,
1700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount);
1710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Returned from vsync handler.", this);
1720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (env->ExceptionCheck()) {
1740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGE("An exception occurred while dispatching a vsync event.");
1750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGE_EX(env);
1760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        env->ExceptionClear();
1770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1790a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // Check whether dispatchVsync called scheduleVsync reentrantly and set mWaitingForVsync.
1800a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // If so, keep the callback, otherwise remove it.
1810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (r->mWaitingForVsync) {
1820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 1; // keep the callback
1830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    r->mFdCallbackRegistered = false;
1850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return 0; // remove the callback
1860a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
1900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jobject messageQueueObj) {
1910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
1920a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (looper == NULL) {
1930a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1940a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
1950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
1980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            receiverObj, looper);
1990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->initialize();
2000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
2010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
2020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
2030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
2040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
2050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
2080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return reinterpret_cast<jint>(receiver.get());
2090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
2120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
2140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
2150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeScheduleVsync(JNIEnv* env, jclass clazz, jint receiverPtr) {
2180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
2200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->scheduleVsync();
2210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
2220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
2230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
2240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
2250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic JNINativeMethod gMethods[] = {
2300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /* name, signature, funcPtr */
2310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeInit",
2320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)I",
2330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeInit },
2340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeDispose",
2350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(I)V",
2360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeDispose },
2370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeScheduleVsync", "(I)V",
2380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeScheduleVsync }
2390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
2400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define FIND_CLASS(var, className) \
2420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->FindClass(className); \
2430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
2440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = jclass(env->NewGlobalRef(var));
2450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
2490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint register_android_view_DisplayEventReceiver(JNIEnv* env) {
2510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/DisplayEventReceiver",
2520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gMethods, NELEM(gMethods));
2530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    FIND_CLASS(gDisplayEventReceiverClassInfo.clazz, "android/view/DisplayEventReceiver");
2560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchVsync,
2580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gDisplayEventReceiverClassInfo.clazz,
2590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "dispatchVsync", "(JI)V");
2600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return 0;
2610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} // namespace android
264