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) { 11363a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat jlong ptr = env->GetLongField(messageQueueObj, gMessageQueueClassInfo.mPtr); 11463a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat return reinterpret_cast<NativeMessageQueue*>(ptr); 115fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 116fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 11763a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhatstatic jlong 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); 12563a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat return reinterpret_cast<jlong>(nativeMessageQueue); 126fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 127fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 12863a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhatstatic void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jclass clazz, jlong 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, 13463a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat jlong ptr, jint timeoutMillis) { 135415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 136603b44589682db3ff33ade172facb0c5e309f1beJeff Brown nativeMessageQueue->pollOnce(env, timeoutMillis); 137fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 138fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 13963a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhatstatic void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) { 140415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 14146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return nativeMessageQueue->wake(); 142fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 143fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 14463a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhatstatic jboolean android_os_MessageQueue_nativeIsIdling(JNIEnv* env, jclass clazz, jlong ptr) { 145efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 146efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn return nativeMessageQueue->getLooper()->isIdling(); 147efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn} 148efa92b2182ab581873aa8e75d596e2e363bd5e6dDianne Hackborn 149fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ---------------------------------------------------------------------------- 150fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 151fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic JNINativeMethod gMessageQueueMethods[] = { 152fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate /* name, signature, funcPtr */ 15363a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit }, 15463a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy }, 15563a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce }, 15663a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake }, 15763a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat { "nativeIsIdling", "(J)Z", (void*)android_os_MessageQueue_nativeIsIdling } 158fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}; 159fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 16046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \ 16146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->FindClass(className); \ 16217cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro LOG_FATAL_IF(! var, "Unable to find class " className); 16346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 16446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 16546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 16646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 16746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 168fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateint register_android_os_MessageQueue(JNIEnv* env) { 16946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 17046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown gMessageQueueMethods, NELEM(gMessageQueueMethods)); 17146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 17246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 17317cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro jclass clazz; 17417cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro FIND_CLASS(clazz, "android/os/MessageQueue"); 175fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 17617cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz, 17763a37153238d95cf8897939e6d6e8fbc56e9ec7fAshok Bhat "mPtr", "J"); 178fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 17946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return 0; 180fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 181fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 18246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android 183