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;
42e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    jmethodID dispatchHotplug;
430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} gDisplayEventReceiverClassInfo;
440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
4680a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownclass NativeDisplayEventReceiver : public LooperCallback {
470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownpublic:
480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    NativeDisplayEventReceiver(JNIEnv* env,
49603b44589682db3ff33ade172facb0c5e309f1beJeff Brown            jobject receiverObj, const sp<MessageQueue>& messageQueue);
500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t initialize();
5280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    void dispose();
530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t scheduleVsync();
540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprotected:
560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    virtual ~NativeDisplayEventReceiver();
570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownprivate:
590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    jobject mReceiverObjGlobal;
60603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> mMessageQueue;
610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    DisplayEventReceiver mReceiver;
620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    bool mWaitingForVsync;
63bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown
6480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    virtual int handleEvent(int receiveFd, int events, void* data);
65e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    bool readLastVsyncMessage(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
66e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
67e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
72603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        jobject receiverObj, const sp<MessageQueue>& messageQueue) :
730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
74603b44589682db3ff33ade172facb0c5e309f1beJeff Brown        mMessageQueue(messageQueue), mWaitingForVsync(false) {
750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    ALOGV("receiver %p ~ Initializing input event receiver.", this);
760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
770a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
780a0a1248cfc03940174cbd9af677bafd7280a3bcJeff BrownNativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
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
90603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
9180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown            this, NULL);
9258aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    if (rc < 0) {
9358aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown        return UNKNOWN_ERROR;
9458aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    }
950a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
960a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
970a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
9880a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownvoid NativeDisplayEventReceiver::dispose() {
9980a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    ALOGV("receiver %p ~ Disposing display event receiver.", this);
10080a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
10180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    if (!mReceiver.initCheck()) {
10280a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown        mMessageQueue->getLooper()->removeFd(mReceiver.getFd());
10380a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    }
10480a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown}
10580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown
1060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatus_t NativeDisplayEventReceiver::scheduleVsync() {
1070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (!mWaitingForVsync) {
1080a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        ALOGV("receiver %p ~ Scheduling vsync.", this);
1090a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        // Drain all pending events.
111bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        nsecs_t vsyncTimestamp;
112e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        int32_t vsyncDisplayId;
113bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        uint32_t vsyncCount;
114e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
1150a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
1166779df2c28a68616134b1988f009221652d9f2adMathias Agopian        status_t status = mReceiver.requestNextVsync();
1176779df2c28a68616134b1988f009221652d9f2adMathias Agopian        if (status) {
1188564c8da817a845353d213acd8636b76f567b234Steve Block            ALOGW("Failed to request next vsync, status=%d", status);
1196779df2c28a68616134b1988f009221652d9f2adMathias Agopian            return status;
1206779df2c28a68616134b1988f009221652d9f2adMathias Agopian        }
1216779df2c28a68616134b1988f009221652d9f2adMathias Agopian
1220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        mWaitingForVsync = true;
1230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return OK;
1250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
12780a1de1007ddc62e1af2a4746008f499145aeaabJeff Brownint NativeDisplayEventReceiver::handleEvent(int receiveFd, int events, void* data) {
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.
141bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    nsecs_t vsyncTimestamp;
142e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    int32_t vsyncDisplayId;
143bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    uint32_t vsyncCount;
144e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    if (!readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
14580a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown        ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", this);
1460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 1; // keep the callback, did not obtain a vsync pulse
1470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
1480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
149e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
150e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
15180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    mWaitingForVsync = false;
1520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
153e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
15458aedbc9bea13415e2d42cf7c9fe8a7efd243e66Jeff Brown    return 1; // keep the callback
1550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
1560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
157bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brownbool NativeDisplayEventReceiver::readLastVsyncMessage(
158e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown        nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
159bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
160bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    ssize_t n;
161bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown    while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
162bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        ALOGV("receiver %p ~ Read %d events.", this, int(n));
163bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown        while (n-- > 0) {
164e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            const DisplayEventReceiver::Event& ev = buf[n];
165e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
166e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown                *outTimestamp = ev.header.timestamp;
167e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown                *outId = ev.header.id;
168e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown                *outCount = ev.vsync.count;
169bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown                return true; // stop at last vsync in the buffer
170bec0a8682c75a40df6d0dca17e23db2103a950f3Jeff Brown            }
171e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
172e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
173e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown                dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
174e87bf030766198bf5e1fe846167dba766e27fb3fJeff 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
183e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brownvoid NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
184e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
185e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
186e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    ALOGV("receiver %p ~ Invoking vsync handler.", this);
187e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    env->CallVoidMethod(mReceiverObjGlobal,
188e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            gDisplayEventReceiverClassInfo.dispatchVsync, timestamp, id, count);
189e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    ALOGV("receiver %p ~ Returned from vsync handler.", this);
190e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
191e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    mMessageQueue->raiseAndClearException(env, "dispatchVsync");
192e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown}
193e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
194e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brownvoid NativeDisplayEventReceiver::dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected) {
195e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    JNIEnv* env = AndroidRuntime::getJNIEnv();
196e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
197e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    ALOGV("receiver %p ~ Invoking hotplug handler.", this);
198e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    env->CallVoidMethod(mReceiverObjGlobal,
199e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            gDisplayEventReceiverClassInfo.dispatchHotplug, timestamp, id, connected);
200e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    ALOGV("receiver %p ~ Returned from hotplug handler.", this);
201e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
202e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    mMessageQueue->raiseAndClearException(env, "dispatchHotplug");
203e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown}
204e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown
2050a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2060a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
2070a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jobject messageQueueObj) {
208603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
209603b44589682db3ff33ade172facb0c5e309f1beJeff Brown    if (messageQueue == NULL) {
2100a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
2110a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
2120a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2130a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2140a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
215603b44589682db3ff33ade172facb0c5e309f1beJeff Brown            receiverObj, messageQueue);
2160a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->initialize();
2170a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
2180a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
2190a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to initialize display event receiver.  status=%d", status);
2200a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
2210a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        return 0;
2220a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2230a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2240a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
2250a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return reinterpret_cast<jint>(receiver.get());
2260a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2270a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2280a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
2290a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2300a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
23180a1de1007ddc62e1af2a4746008f499145aeaabJeff Brown    receiver->dispose();
2320a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
2330a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2340a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2350a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic void nativeScheduleVsync(JNIEnv* env, jclass clazz, jint receiverPtr) {
2360a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    sp<NativeDisplayEventReceiver> receiver =
2370a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
2380a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    status_t status = receiver->scheduleVsync();
2390a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    if (status) {
2400a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        String8 message;
2410a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        message.appendFormat("Failed to schedule next vertical sync pulse.  status=%d", status);
2420a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        jniThrowRuntimeException(env, message.string());
2430a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    }
2440a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2450a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2460a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2470a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownstatic JNINativeMethod gMethods[] = {
2480a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    /* name, signature, funcPtr */
2490a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeInit",
2500a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)I",
2510a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeInit },
2520a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeDispose",
2530a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            "(I)V",
2540a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeDispose },
2550a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    { "nativeScheduleVsync", "(I)V",
2560a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            (void*)nativeScheduleVsync }
2570a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown};
2580a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2590a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define FIND_CLASS(var, className) \
2600a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->FindClass(className); \
2610a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
2620a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = jclass(env->NewGlobalRef(var));
2630a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2640a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
2650a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        var = env->GetMethodID(clazz, methodName, methodDescriptor); \
2660a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown        LOG_FATAL_IF(! var, "Unable to find method " methodName);
2670a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2680a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brownint register_android_view_DisplayEventReceiver(JNIEnv* env) {
2690a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    int res = jniRegisterNativeMethods(env, "android/view/DisplayEventReceiver",
2700a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gMethods, NELEM(gMethods));
2710a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
2720a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2730a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    FIND_CLASS(gDisplayEventReceiverClassInfo.clazz, "android/view/DisplayEventReceiver");
2740a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2750a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchVsync,
2760a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown            gDisplayEventReceiverClassInfo.clazz,
277e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            "dispatchVsync", "(JII)V");
278e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown    GET_METHOD_ID(gDisplayEventReceiverClassInfo.dispatchHotplug,
279e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            gDisplayEventReceiverClassInfo.clazz,
280e87bf030766198bf5e1fe846167dba766e27fb3fJeff Brown            "dispatchHotplug", "(JIZ)V");
2810a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown    return 0;
2820a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown}
2830a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown
2840a0a1248cfc03940174cbd9af677bafd7280a3bcJeff Brown} // namespace android
285