Merge "Ensure that apps crash if they throw exceptions."
This commit is contained in:
@@ -416,8 +416,8 @@ struct NativeCode : public ANativeActivity {
|
||||
if (env != NULL && clazz != NULL) {
|
||||
env->DeleteGlobalRef(clazz);
|
||||
}
|
||||
if (looper != NULL && mainWorkRead >= 0) {
|
||||
looper->removeFd(mainWorkRead);
|
||||
if (messageQueue != NULL && mainWorkRead >= 0) {
|
||||
messageQueue->getLooper()->removeFd(mainWorkRead);
|
||||
}
|
||||
if (nativeInputQueue != NULL) {
|
||||
nativeInputQueue->mWorkWrite = -1;
|
||||
@@ -481,7 +481,7 @@ struct NativeCode : public ANativeActivity {
|
||||
// These are used to wake up the main thread to process work.
|
||||
int mainWorkRead;
|
||||
int mainWorkWrite;
|
||||
sp<Looper> looper;
|
||||
sp<MessageQueue> messageQueue;
|
||||
};
|
||||
|
||||
void android_NativeActivity_finish(ANativeActivity* activity) {
|
||||
@@ -515,16 +515,6 @@ void android_NativeActivity_hideSoftInput(
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for handling native events on the application's main thread.
|
||||
*/
|
||||
@@ -551,7 +541,8 @@ static int mainWorkCallback(int fd, int events, void* data) {
|
||||
if (inputEventObj) {
|
||||
handled = code->env->CallBooleanMethod(code->clazz,
|
||||
gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj);
|
||||
checkAndClearExceptionFromCallback(code->env, "dispatchUnhandledKeyEvent");
|
||||
code->messageQueue->raiseAndClearException(
|
||||
code->env, "dispatchUnhandledKeyEvent");
|
||||
code->env->DeleteLocalRef(inputEventObj);
|
||||
} else {
|
||||
ALOGE("Failed to obtain key event for dispatchUnhandledKeyEvent.");
|
||||
@@ -566,7 +557,7 @@ static int mainWorkCallback(int fd, int events, void* data) {
|
||||
if (inputEventObj) {
|
||||
code->env->CallVoidMethod(code->clazz,
|
||||
gNativeActivityClassInfo.preDispatchKeyEvent, inputEventObj, seq);
|
||||
checkAndClearExceptionFromCallback(code->env, "preDispatchKeyEvent");
|
||||
code->messageQueue->raiseAndClearException(code->env, "preDispatchKeyEvent");
|
||||
code->env->DeleteLocalRef(inputEventObj);
|
||||
} else {
|
||||
ALOGE("Failed to obtain key event for preDispatchKeyEvent.");
|
||||
@@ -575,27 +566,27 @@ static int mainWorkCallback(int fd, int events, void* data) {
|
||||
} break;
|
||||
case CMD_FINISH: {
|
||||
code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
|
||||
checkAndClearExceptionFromCallback(code->env, "finish");
|
||||
code->messageQueue->raiseAndClearException(code->env, "finish");
|
||||
} break;
|
||||
case CMD_SET_WINDOW_FORMAT: {
|
||||
code->env->CallVoidMethod(code->clazz,
|
||||
gNativeActivityClassInfo.setWindowFormat, work.arg1);
|
||||
checkAndClearExceptionFromCallback(code->env, "setWindowFormat");
|
||||
code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
|
||||
} break;
|
||||
case CMD_SET_WINDOW_FLAGS: {
|
||||
code->env->CallVoidMethod(code->clazz,
|
||||
gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
|
||||
checkAndClearExceptionFromCallback(code->env, "setWindowFlags");
|
||||
code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
|
||||
} break;
|
||||
case CMD_SHOW_SOFT_INPUT: {
|
||||
code->env->CallVoidMethod(code->clazz,
|
||||
gNativeActivityClassInfo.showIme, work.arg1);
|
||||
checkAndClearExceptionFromCallback(code->env, "showIme");
|
||||
code->messageQueue->raiseAndClearException(code->env, "showIme");
|
||||
} break;
|
||||
case CMD_HIDE_SOFT_INPUT: {
|
||||
code->env->CallVoidMethod(code->clazz,
|
||||
gNativeActivityClassInfo.hideIme, work.arg1);
|
||||
checkAndClearExceptionFromCallback(code->env, "hideIme");
|
||||
code->messageQueue->raiseAndClearException(code->env, "hideIme");
|
||||
} break;
|
||||
default:
|
||||
ALOGW("Unknown work command: %d", work.cmd);
|
||||
@@ -634,9 +625,9 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
|
||||
return 0;
|
||||
}
|
||||
|
||||
code->looper = android_os_MessageQueue_getLooper(env, messageQueue);
|
||||
if (code->looper == NULL) {
|
||||
ALOGW("Unable to retrieve MessageQueue's Looper");
|
||||
code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
|
||||
if (code->messageQueue == NULL) {
|
||||
ALOGW("Unable to retrieve native MessageQueue");
|
||||
delete code;
|
||||
return 0;
|
||||
}
|
||||
@@ -655,7 +646,8 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
|
||||
result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
|
||||
SLOGW_IF(result != 0, "Could not make main work write pipe "
|
||||
"non-blocking: %s", strerror(errno));
|
||||
code->looper->addFd(code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
|
||||
code->messageQueue->getLooper()->addFd(
|
||||
code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
|
||||
|
||||
code->ANativeActivity::callbacks = &code->callbacks;
|
||||
if (env->GetJavaVM(&code->vm) < 0) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define LOG_TAG "MessageQueue-JNI"
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include <utils/Looper.h>
|
||||
#include <utils/Log.h>
|
||||
@@ -24,31 +25,46 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static struct {
|
||||
jfieldID mPtr; // native object attached to the DVM MessageQueue
|
||||
} gMessageQueueClassInfo;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class NativeMessageQueue {
|
||||
class NativeMessageQueue : public MessageQueue {
|
||||
public:
|
||||
NativeMessageQueue();
|
||||
~NativeMessageQueue();
|
||||
virtual ~NativeMessageQueue();
|
||||
|
||||
inline sp<Looper> getLooper() { return mLooper; }
|
||||
virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);
|
||||
|
||||
void pollOnce(JNIEnv* env, int timeoutMillis);
|
||||
|
||||
void pollOnce(int timeoutMillis);
|
||||
void wake();
|
||||
|
||||
private:
|
||||
sp<Looper> mLooper;
|
||||
bool mInCallback;
|
||||
jthrowable mExceptionObj;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
NativeMessageQueue::NativeMessageQueue() {
|
||||
MessageQueue::MessageQueue() {
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
}
|
||||
|
||||
bool MessageQueue::raiseAndClearException(JNIEnv* env, const char* msg) {
|
||||
jthrowable exceptionObj = env->ExceptionOccurred();
|
||||
if (exceptionObj) {
|
||||
env->ExceptionClear();
|
||||
raiseException(env, msg, exceptionObj);
|
||||
env->DeleteLocalRef(exceptionObj);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
|
||||
mLooper = Looper::getForThread();
|
||||
if (mLooper == NULL) {
|
||||
mLooper = new Looper(false);
|
||||
@@ -59,8 +75,32 @@ NativeMessageQueue::NativeMessageQueue() {
|
||||
NativeMessageQueue::~NativeMessageQueue() {
|
||||
}
|
||||
|
||||
void NativeMessageQueue::pollOnce(int timeoutMillis) {
|
||||
void NativeMessageQueue::raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) {
|
||||
if (exceptionObj) {
|
||||
if (mInCallback) {
|
||||
if (mExceptionObj) {
|
||||
env->DeleteLocalRef(mExceptionObj);
|
||||
}
|
||||
mExceptionObj = jthrowable(env->NewLocalRef(exceptionObj));
|
||||
ALOGE("Exception in MessageQueue callback: %s", msg);
|
||||
jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
|
||||
} else {
|
||||
ALOGE("Exception: %s", msg);
|
||||
jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
|
||||
LOG_ALWAYS_FATAL("raiseException() was called when not in a callback, exiting.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
|
||||
mInCallback = true;
|
||||
mLooper->pollOnce(timeoutMillis);
|
||||
mInCallback = false;
|
||||
if (mExceptionObj) {
|
||||
env->Throw(mExceptionObj);
|
||||
env->DeleteLocalRef(mExceptionObj);
|
||||
mExceptionObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMessageQueue::wake() {
|
||||
@@ -81,19 +121,20 @@ static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject m
|
||||
reinterpret_cast<jint>(nativeMessageQueue));
|
||||
}
|
||||
|
||||
sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) {
|
||||
sp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {
|
||||
NativeMessageQueue* nativeMessageQueue =
|
||||
android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj);
|
||||
return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL;
|
||||
return nativeMessageQueue;
|
||||
}
|
||||
|
||||
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
|
||||
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
|
||||
if (! nativeMessageQueue) {
|
||||
if (!nativeMessageQueue) {
|
||||
jniThrowRuntimeException(env, "Unable to allocate native queue");
|
||||
return;
|
||||
}
|
||||
|
||||
nativeMessageQueue->incStrong(env);
|
||||
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
|
||||
}
|
||||
|
||||
@@ -102,7 +143,7 @@ static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
|
||||
android_os_MessageQueue_getNativeMessageQueue(env, obj);
|
||||
if (nativeMessageQueue) {
|
||||
android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
|
||||
delete nativeMessageQueue;
|
||||
nativeMessageQueue->decStrong(env);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +154,7 @@ static void throwQueueNotInitialized(JNIEnv* env) {
|
||||
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
|
||||
jint ptr, jint timeoutMillis) {
|
||||
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
|
||||
nativeMessageQueue->pollOnce(timeoutMillis);
|
||||
nativeMessageQueue->pollOnce(env, timeoutMillis);
|
||||
}
|
||||
|
||||
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
|
||||
|
||||
@@ -18,12 +18,53 @@
|
||||
#define _ANDROID_OS_MESSAGEQUEUE_H
|
||||
|
||||
#include "jni.h"
|
||||
#include <utils/Looper.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class Looper;
|
||||
class MessageQueue : public RefBase {
|
||||
public:
|
||||
/* Gets the message queue's looper. */
|
||||
inline sp<Looper> getLooper() const {
|
||||
return mLooper;
|
||||
}
|
||||
|
||||
extern sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj);
|
||||
/* Checks whether the JNI environment has a pending exception.
|
||||
*
|
||||
* If an exception occurred, logs it together with the specified message,
|
||||
* and calls raiseException() to ensure the exception will be raised when
|
||||
* the callback returns, clears the pending exception from the environment,
|
||||
* then returns true.
|
||||
*
|
||||
* If no exception occurred, returns false.
|
||||
*/
|
||||
bool raiseAndClearException(JNIEnv* env, const char* msg);
|
||||
|
||||
/* Raises an exception from within a callback function.
|
||||
* The exception will be rethrown when control returns to the message queue which
|
||||
* will typically cause the application to crash.
|
||||
*
|
||||
* This message can only be called from within a callback function. If it is called
|
||||
* at any other time, the process will simply be killed.
|
||||
*
|
||||
* Does nothing if exception is NULL.
|
||||
*
|
||||
* (This method does not take ownership of the exception object reference.
|
||||
* The caller is responsible for releasing its reference when it is done.)
|
||||
*/
|
||||
virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) = 0;
|
||||
|
||||
protected:
|
||||
MessageQueue();
|
||||
virtual ~MessageQueue();
|
||||
|
||||
protected:
|
||||
sp<Looper> mLooper;
|
||||
};
|
||||
|
||||
/* Gets the native object associated with a MessageQueue. */
|
||||
extern sp<MessageQueue> android_os_MessageQueue_getMessageQueue(
|
||||
JNIEnv* env, jobject messageQueueObj);
|
||||
|
||||
} // namespace android
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ static struct {
|
||||
class NativeDisplayEventReceiver : public RefBase {
|
||||
public:
|
||||
NativeDisplayEventReceiver(JNIEnv* env,
|
||||
jobject receiverObj, const sp<Looper>& looper);
|
||||
jobject receiverObj, const sp<MessageQueue>& messageQueue);
|
||||
|
||||
status_t initialize();
|
||||
status_t scheduleVsync();
|
||||
@@ -55,7 +55,7 @@ protected:
|
||||
|
||||
private:
|
||||
jobject mReceiverObjGlobal;
|
||||
sp<Looper> mLooper;
|
||||
sp<MessageQueue> mMessageQueue;
|
||||
DisplayEventReceiver mReceiver;
|
||||
bool mWaitingForVsync;
|
||||
|
||||
@@ -65,9 +65,9 @@ private:
|
||||
|
||||
|
||||
NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
|
||||
jobject receiverObj, const sp<Looper>& looper) :
|
||||
jobject receiverObj, const sp<MessageQueue>& messageQueue) :
|
||||
mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
|
||||
mLooper(looper), mWaitingForVsync(false) {
|
||||
mMessageQueue(messageQueue), mWaitingForVsync(false) {
|
||||
ALOGV("receiver %p ~ Initializing input event receiver.", this);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ NativeDisplayEventReceiver::~NativeDisplayEventReceiver() {
|
||||
ALOGV("receiver %p ~ Disposing display event receiver.", this);
|
||||
|
||||
if (!mReceiver.initCheck()) {
|
||||
mLooper->removeFd(mReceiver.getFd());
|
||||
mMessageQueue->getLooper()->removeFd(mReceiver.getFd());
|
||||
}
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
@@ -89,7 +89,7 @@ status_t NativeDisplayEventReceiver::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
int rc = mLooper->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
|
||||
int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
|
||||
handleReceiveCallback, this);
|
||||
if (rc < 0) {
|
||||
return UNKNOWN_ERROR;
|
||||
@@ -151,12 +151,7 @@ int NativeDisplayEventReceiver::handleReceiveCallback(int receiveFd, int events,
|
||||
gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount);
|
||||
ALOGV("receiver %p ~ Returned from vsync handler.", data);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("An exception occurred while dispatching a vsync event.");
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
|
||||
r->mMessageQueue->raiseAndClearException(env, "dispatchVsync");
|
||||
return 1; // keep the callback
|
||||
}
|
||||
|
||||
@@ -183,14 +178,14 @@ bool NativeDisplayEventReceiver::readLastVsyncMessage(
|
||||
|
||||
static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
|
||||
jobject messageQueueObj) {
|
||||
sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
|
||||
if (looper == NULL) {
|
||||
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
|
||||
if (messageQueue == NULL) {
|
||||
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
|
||||
receiverObj, looper);
|
||||
receiverObj, messageQueue);
|
||||
status_t status = receiver->initialize();
|
||||
if (status) {
|
||||
String8 message;
|
||||
|
||||
@@ -48,7 +48,7 @@ class NativeInputEventReceiver : public RefBase {
|
||||
public:
|
||||
NativeInputEventReceiver(JNIEnv* env,
|
||||
jobject receiverObj, const sp<InputChannel>& inputChannel,
|
||||
const sp<Looper>& looper);
|
||||
const sp<MessageQueue>& messageQueue);
|
||||
|
||||
status_t initialize();
|
||||
status_t finishInputEvent(uint32_t seq, bool handled);
|
||||
@@ -61,7 +61,7 @@ protected:
|
||||
private:
|
||||
jobject mReceiverObjGlobal;
|
||||
InputConsumer mInputConsumer;
|
||||
sp<Looper> mLooper;
|
||||
sp<MessageQueue> mMessageQueue;
|
||||
PreallocatedInputEventFactory mInputEventFactory;
|
||||
bool mBatchedInputEventPending;
|
||||
|
||||
@@ -72,9 +72,10 @@ private:
|
||||
|
||||
|
||||
NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
|
||||
jobject receiverObj, const sp<InputChannel>& inputChannel, const sp<Looper>& looper) :
|
||||
jobject receiverObj, const sp<InputChannel>& inputChannel,
|
||||
const sp<MessageQueue>& messageQueue) :
|
||||
mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
|
||||
mInputConsumer(inputChannel), mLooper(looper),
|
||||
mInputConsumer(inputChannel), mMessageQueue(messageQueue),
|
||||
mBatchedInputEventPending(false) {
|
||||
#if DEBUG_DISPATCH_CYCLE
|
||||
ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
|
||||
@@ -86,7 +87,7 @@ NativeInputEventReceiver::~NativeInputEventReceiver() {
|
||||
ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
|
||||
#endif
|
||||
|
||||
mLooper->removeFd(mInputConsumer.getChannel()->getFd());
|
||||
mMessageQueue->getLooper()->removeFd(mInputConsumer.getChannel()->getFd());
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
env->DeleteGlobalRef(mReceiverObjGlobal);
|
||||
@@ -94,7 +95,8 @@ NativeInputEventReceiver::~NativeInputEventReceiver() {
|
||||
|
||||
status_t NativeInputEventReceiver::initialize() {
|
||||
int receiveFd = mInputConsumer.getChannel()->getFd();
|
||||
mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
|
||||
mMessageQueue->getLooper()->addFd(
|
||||
receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -157,12 +159,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
|
||||
#endif
|
||||
env->CallVoidMethod(mReceiverObjGlobal,
|
||||
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("channel '%s' ~ An exception occurred while dispatching that "
|
||||
"batched input events are pending.", getInputChannelName());
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
if (mMessageQueue->raiseAndClearException(
|
||||
env, "dispatchBatchedInputEventPending")) {
|
||||
mBatchedInputEventPending = false; // try again later
|
||||
}
|
||||
}
|
||||
@@ -182,6 +180,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
|
||||
#endif
|
||||
inputEventObj = android_view_KeyEvent_fromNative(env,
|
||||
static_cast<KeyEvent*>(inputEvent));
|
||||
mMessageQueue->raiseAndClearException(env, "new KeyEvent");
|
||||
break;
|
||||
|
||||
case AINPUT_EVENT_TYPE_MOTION:
|
||||
@@ -190,6 +189,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
|
||||
#endif
|
||||
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
|
||||
static_cast<MotionEvent*>(inputEvent));
|
||||
mMessageQueue->raiseAndClearException(env, "new MotionEvent");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -200,7 +200,7 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
|
||||
if (!inputEventObj) {
|
||||
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
|
||||
mInputConsumer.sendFinishedSignal(seq, false);
|
||||
return NO_MEMORY;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if DEBUG_DISPATCH_CYCLE
|
||||
@@ -211,14 +211,8 @@ status_t NativeInputEventReceiver::consumeEvents(bool consumeBatches) {
|
||||
|
||||
env->DeleteLocalRef(inputEventObj);
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
ALOGE("channel '%s' ~ An exception occurred while dispatching an event.",
|
||||
getInputChannelName());
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
|
||||
if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) {
|
||||
mInputConsumer.sendFinishedSignal(seq, false);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,14 +227,14 @@ static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
|
||||
if (looper == NULL) {
|
||||
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
|
||||
if (messageQueue == NULL) {
|
||||
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
|
||||
receiverObj, inputChannel, looper);
|
||||
receiverObj, inputChannel, messageQueue);
|
||||
status_t status = receiver->initialize();
|
||||
if (status) {
|
||||
String8 message;
|
||||
|
||||
@@ -950,8 +950,9 @@ void NativeInputManager::loadPointerResources(PointerResources* outResources) {
|
||||
|
||||
static jint nativeInit(JNIEnv* env, jclass clazz,
|
||||
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
|
||||
sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
|
||||
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, looper);
|
||||
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
|
||||
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
|
||||
messageQueue->getLooper());
|
||||
im->incStrong(serviceObj);
|
||||
return reinterpret_cast<jint>(im);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user