android_os_MessageQueue.cpp revision 864693461b6223a995038847591b17abe2de647e
1fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate/* 2fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * Copyright (C) 2010 The Android Open Source Project 3fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * 4fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * Licensed under the Apache License, Version 2.0 (the "License"); 5fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * you may not use this file except in compliance with the License. 6fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * You may obtain a copy of the License at 7fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * 8fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * http://www.apache.org/licenses/LICENSE-2.0 9fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * 10fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * Unless required by applicable law or agreed to in writing, software 11fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * distributed under the License is distributed on an "AS IS" BASIS, 12fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * See the License for the specific language governing permissions and 14fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate * limitations under the License. 15fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate */ 16fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 1746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define LOG_TAG "MessageQueue-JNI" 18fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 19fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate#include "JNIHelp.h" 20603b44589682db3ff33ade172facb0c5e309f1beJeff Brown#include <android_runtime/AndroidRuntime.h> 21fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 224fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown#include <utils/Looper.h> 23fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate#include <utils/Log.h> 2446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_os_MessageQueue.h" 25fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 2646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android { 27fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 28fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic struct { 2946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jfieldID mPtr; // native object attached to the DVM MessageQueue 3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gMessageQueueClassInfo; 31fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 32fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 33603b44589682db3ff33ade172facb0c5e309f1beJeff Brownclass NativeMessageQueue : public MessageQueue { 34fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatepublic: 3546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue(); 36603b44589682db3ff33ade172facb0c5e309f1beJeff Brown virtual ~NativeMessageQueue(); 37603b44589682db3ff33ade172facb0c5e309f1beJeff Brown 38603b44589682db3ff33ade172facb0c5e309f1beJeff Brown virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj); 39fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 40603b44589682db3ff33ade172facb0c5e309f1beJeff Brown void pollOnce(JNIEnv* env, int timeoutMillis); 41fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 4246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown void wake(); 43fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 44fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateprivate: 45603b44589682db3ff33ade172facb0c5e309f1beJeff Brown bool mInCallback; 46603b44589682db3ff33ade172facb0c5e309f1beJeff Brown jthrowable mExceptionObj; 47fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}; 48fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 49fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 50603b44589682db3ff33ade172facb0c5e309f1beJeff BrownMessageQueue::MessageQueue() { 51603b44589682db3ff33ade172facb0c5e309f1beJeff Brown} 52603b44589682db3ff33ade172facb0c5e309f1beJeff Brown 53603b44589682db3ff33ade172facb0c5e309f1beJeff BrownMessageQueue::~MessageQueue() { 54603b44589682db3ff33ade172facb0c5e309f1beJeff Brown} 55603b44589682db3ff33ade172facb0c5e309f1beJeff Brown 56603b44589682db3ff33ade172facb0c5e309f1beJeff Brownbool MessageQueue::raiseAndClearException(JNIEnv* env, const char* msg) { 57603b44589682db3ff33ade172facb0c5e309f1beJeff Brown jthrowable exceptionObj = env->ExceptionOccurred(); 58603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (exceptionObj) { 59603b44589682db3ff33ade172facb0c5e309f1beJeff Brown env->ExceptionClear(); 60603b44589682db3ff33ade172facb0c5e309f1beJeff Brown raiseException(env, msg, exceptionObj); 61603b44589682db3ff33ade172facb0c5e309f1beJeff Brown env->DeleteLocalRef(exceptionObj); 62603b44589682db3ff33ade172facb0c5e309f1beJeff Brown return true; 63603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } 64603b44589682db3ff33ade172facb0c5e309f1beJeff Brown return false; 65603b44589682db3ff33ade172facb0c5e309f1beJeff Brown} 66603b44589682db3ff33ade172facb0c5e309f1beJeff Brown 67603b44589682db3ff33ade172facb0c5e309f1beJeff BrownNativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) { 684fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper = Looper::getForThread(); 694fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown if (mLooper == NULL) { 704fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper = new Looper(false); 714fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown Looper::setForThread(mLooper); 72682674154e3fe88f6061245145f934f25f1a2eb8Dianne Hackborn } 73fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 74fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 7546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeMessageQueue::~NativeMessageQueue() { 76fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 77fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 78603b44589682db3ff33ade172facb0c5e309f1beJeff Brownvoid NativeMessageQueue::raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) { 79603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (exceptionObj) { 80603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (mInCallback) { 81603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (mExceptionObj) { 82603b44589682db3ff33ade172facb0c5e309f1beJeff Brown env->DeleteLocalRef(mExceptionObj); 83603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } 84603b44589682db3ff33ade172facb0c5e309f1beJeff Brown mExceptionObj = jthrowable(env->NewLocalRef(exceptionObj)); 85603b44589682db3ff33ade172facb0c5e309f1beJeff Brown ALOGE("Exception in MessageQueue callback: %s", msg); 86603b44589682db3ff33ade172facb0c5e309f1beJeff Brown jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj); 87603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } else { 88603b44589682db3ff33ade172facb0c5e309f1beJeff Brown ALOGE("Exception: %s", msg); 89603b44589682db3ff33ade172facb0c5e309f1beJeff Brown jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj); 90603b44589682db3ff33ade172facb0c5e309f1beJeff Brown LOG_ALWAYS_FATAL("raiseException() was called when not in a callback, exiting."); 91603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } 92603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } 93603b44589682db3ff33ade172facb0c5e309f1beJeff Brown} 94603b44589682db3ff33ade172facb0c5e309f1beJeff Brown 95603b44589682db3ff33ade172facb0c5e309f1beJeff Brownvoid NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) { 96603b44589682db3ff33ade172facb0c5e309f1beJeff Brown mInCallback = true; 97415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown mLooper->pollOnce(timeoutMillis); 98603b44589682db3ff33ade172facb0c5e309f1beJeff Brown mInCallback = false; 99603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (mExceptionObj) { 100603b44589682db3ff33ade172facb0c5e309f1beJeff Brown env->Throw(mExceptionObj); 101603b44589682db3ff33ade172facb0c5e309f1beJeff Brown env->DeleteLocalRef(mExceptionObj); 102603b44589682db3ff33ade172facb0c5e309f1beJeff Brown mExceptionObj = NULL; 103603b44589682db3ff33ade172facb0c5e309f1beJeff Brown } 104fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 105fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 10646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid NativeMessageQueue::wake() { 1074fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper->wake(); 108fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 109fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 11046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 111fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 112864693461b6223a995038847591b17abe2de647eJeff Brownsp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) { 11346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr); 11446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return reinterpret_cast<NativeMessageQueue*>(intPtr); 115fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 116fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 117864693461b6223a995038847591b17abe2de647eJeff Brownstatic jint android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) { 11846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); 119603b44589682db3ff33ade172facb0c5e309f1beJeff Brown if (!nativeMessageQueue) { 12046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowRuntimeException(env, "Unable to allocate native queue"); 121864693461b6223a995038847591b17abe2de647eJeff Brown return 0; 122fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate } 123fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 124603b44589682db3ff33ade172facb0c5e309f1beJeff Brown nativeMessageQueue->incStrong(env); 125864693461b6223a995038847591b17abe2de647eJeff Brown return reinterpret_cast<jint>(nativeMessageQueue); 126fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 127fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 128864693461b6223a995038847591b17abe2de647eJeff Brownstatic void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jclass clazz, jint ptr) { 129864693461b6223a995038847591b17abe2de647eJeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 130864693461b6223a995038847591b17abe2de647eJeff Brown nativeMessageQueue->decStrong(env); 131fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 132fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 133864693461b6223a995038847591b17abe2de647eJeff Brownstatic void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jclass clazz, 134415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown jint ptr, jint timeoutMillis) { 135415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 136603b44589682db3ff33ade172facb0c5e309f1beJeff Brown nativeMessageQueue->pollOnce(env, timeoutMillis); 137fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 138fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 139864693461b6223a995038847591b17abe2de647eJeff Brownstatic void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jint ptr) { 140415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 14146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return nativeMessageQueue->wake(); 142fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 143fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 144fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ---------------------------------------------------------------------------- 145fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 146fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic JNINativeMethod gMessageQueueMethods[] = { 147fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate /* name, signature, funcPtr */ 148864693461b6223a995038847591b17abe2de647eJeff Brown { "nativeInit", "()I", (void*)android_os_MessageQueue_nativeInit }, 149864693461b6223a995038847591b17abe2de647eJeff Brown { "nativeDestroy", "(I)V", (void*)android_os_MessageQueue_nativeDestroy }, 150415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce }, 151415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake } 152fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}; 153fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 15446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \ 15546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->FindClass(className); \ 15617cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro LOG_FATAL_IF(! var, "Unable to find class " className); 15746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 15846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 15946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 16046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 16146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 162fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateint register_android_os_MessageQueue(JNIEnv* env) { 16346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 16446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown gMessageQueueMethods, NELEM(gMessageQueueMethods)); 16546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 16646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 16717cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro jclass clazz; 16817cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro FIND_CLASS(clazz, "android/os/MessageQueue"); 169fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 17017cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz, 17146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "mPtr", "I"); 172fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 17346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return 0; 174fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 175fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 17646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android 177