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