android_view_DisplayEventReceiver.cpp revision bec0a8682c75a40df6d0dca17e23db2103a950f3
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
530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprotected:
540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    virtual ~NativeDisplayEventReceiver();
550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprivate:
570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    jobject mReceiverObjGlobal;
580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<Looper> mLooper;
590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    DisplayEventReceiver mReceiver;
600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    bool mWaitingForVsync;
61bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown
62bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    static int handleReceiveCallback(int receiveFd, int events, void* data);
63bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    bool readLastVsyncMessage(nsecs_t* outTimestamp, uint32_t* outCount);
640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jobject receiverObj, const sp<Looper>& looper) :
690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
7058aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown        mLooper(looper), mWaitingForVsync(false) {
710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Initializing input event receiver.", this);
720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Disposing display event receiver.", this);
760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
7758aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    if (!mReceiver.initCheck()) {
780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mLooper->removeFd(mReceiver.getFd());
790a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
800a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    env->DeleteGlobalRef(mReceiverObjGlobal);
830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::initialize() {
860a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t result = mReceiver.initCheck();
870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (result) {
888564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("Failed to initialize display event receiver, status=%d", result);
890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return result;
900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
9258aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    int rc = mLooper->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
9358aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown            handleReceiveCallback, this);
9458aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    if (rc < 0) {
9558aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown        return UNKNOWN_ERROR;
9658aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    }
970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::scheduleVsync() {
1010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (!mWaitingForVsync) {
1020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ALOGV("receiver %p ~ Scheduling vsync.", this);
1030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        // Drain all pending events.
105bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        nsecs_t vsyncTimestamp;
106bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        uint32_t vsyncCount;
107bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        readLastVsyncMessage(&vsyncTimestamp, &vsyncCount);
1080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1096779df2c28a68616134b1988f009221652d9f2adMathias Agopian        status_t status = mReceiver.requestNextVsync();
1106779df2c28a68616134b1988f009221652d9f2adMathias Agopian        if (status) {
1118564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("Failed to request next vsync, status=%d", status);
1126779df2c28a68616134b1988f009221652d9f2adMathias Agopian            return status;
1136779df2c28a68616134b1988f009221652d9f2adMathias Agopian        }
1146779df2c28a68616134b1988f009221652d9f2adMathias Agopian
1150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mWaitingForVsync = true;
1160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
1180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint NativeDisplayEventReceiver::handleReceiveCallback(int receiveFd, int events, void* data) {
1210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> r = static_cast<NativeDisplayEventReceiver*>(data);
1220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
1243762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Display event receiver pipe was closed or an error occurred.  "
1250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                "events=0x%x", events);
1260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0; // remove the callback
1270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (!(events & ALOOPER_EVENT_INPUT)) {
1308564c8da817a845353d213acd8636b76f567b234Steve Block        ALOGW("Received spurious callback for unhandled poll event.  "
1310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown                "events=0x%x", events);
1320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 1; // keep the callback
1330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    // Drain all pending events, keep the last vsync.
136bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    nsecs_t vsyncTimestamp;
137bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    uint32_t vsyncCount;
138bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    if (!r->readLastVsyncMessage(&vsyncTimestamp, &vsyncCount)) {
13958aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown        ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", data);
1400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 1; // keep the callback, did not obtain a vsync pulse
1410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, count=%d",
14458aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown            data, vsyncTimestamp, vsyncCount);
1450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    r->mWaitingForVsync = false;
1460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
1480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
14958aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    ALOGV("receiver %p ~ Invoking vsync handler.", data);
1500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    env->CallVoidMethod(r->mReceiverObjGlobal,
1510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount);
15258aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    ALOGV("receiver %p ~ Returned from vsync handler.", data);
1530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (env->ExceptionCheck()) {
1553762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("An exception occurred while dispatching a vsync event.");
1560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOGE_EX(env);
1570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        env->ExceptionClear();
1580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
16058aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    return 1; // keep the callback
1610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
163bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brownbool NativeDisplayEventReceiver::readLastVsyncMessage(
164bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        nsecs_t* outTimestamp, uint32_t* outCount) {
165bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
166bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    ssize_t n;
167bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
168bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        ALOGV("receiver %p ~ Read %d events.", this, int(n));
169bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        while (n-- > 0) {
170bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown            if (buf[n].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
171bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown                *outTimestamp = buf[n].header.timestamp;
172bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown                *outCount = buf[n].vsync.count;
173bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown                return true; // stop at last vsync in the buffer
174bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown            }
175bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        }
176bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    }
177bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    if (n < 0) {
178bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
179bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    }
180bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    return false;
181bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown}
182bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown
1830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
1850a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jobject messageQueueObj) {
1860a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
1870a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (looper == NULL) {
1880a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1890a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
1900a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1910a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1920a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
1930a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            receiverObj, looper);
1940a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->initialize();
1950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
1960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
1970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
1980a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
1990a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
2000a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2010a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2020a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
2030a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return reinterpret_cast<jint>(receiver.get());
2040a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
2070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
2090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
2100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeScheduleVsync(JNIEnv* env, jclass clazz, jint receiverPtr) {
2130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
2150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->scheduleVsync();
2160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
2170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
2180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
2190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
2200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic JNINativeMethod gMethods[] = {
2250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /* name, signature, funcPtr */
2260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeInit",
2270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)I",
2280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeInit },
2290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeDispose",
2300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(I)V",
2310a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeDispose },
2320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeScheduleVsync", "(I)V",
2330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeScheduleVsync }
2340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
2350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define FIND_CLASS(var, className) \
2370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->FindClass(className); \
2380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
2390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = jclass(env->NewGlobalRef(var));
2400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
2440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint register_android_view_DisplayEventReceiver(JNIEnv* env) {
2460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/DisplayEventReceiver",
2470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gMethods, NELEM(gMethods));
2480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    FIND_CLASS(gDisplayEventReceiverClassInfo.clazz, "android/view/DisplayEventReceiver");
2510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchVsync,
2530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gDisplayEventReceiverClassInfo.clazz,
2540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "dispatchVsync", "(JI)V");
2550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return 0;
2560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} // namespace android
259