android_os_MessageQueue.cpp revision 4fe6c3e51be77e35f40872cdbca6c80f8f8b7ecb
1e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams/* 2e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * Copyright (C) 2010 The Android Open Source Project 3e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * 4e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * you may not use this file except in compliance with the License. 6e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * You may obtain a copy of the License at 7e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * 8e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * http://www.apache.org/licenses/LICENSE-2.0 9e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * 10e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * Unless required by applicable law or agreed to in writing, software 11e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * See the License for the specific language governing permissions and 14e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams * limitations under the License. 15e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams */ 16e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams 17e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams#define LOG_TAG "MessageQueue-JNI" 18e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams 19e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams#include "JNIHelp.h" 2010efb53234d214ac414605e8e52b68e3d40f6f3fStephen Hines 21e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams#include <utils/Looper.h> 22e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams#include <utils/Log.h> 23e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams#include "android_os_MessageQueue.h" 24e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams 25e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Samsnamespace android { 26b2cb8e41f93e8a26241e3de20e862ffa66dedaa4Tim Murray 27e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams// ---------------------------------------------------------------------------- 28e5f2f66f8c802d64ecf869081036ae13d4e9e19cJason Sams 29static struct { 30 jclass clazz; 31 32 jfieldID mPtr; // native object attached to the DVM MessageQueue 33} gMessageQueueClassInfo; 34 35// ---------------------------------------------------------------------------- 36 37class NativeMessageQueue { 38public: 39 NativeMessageQueue(); 40 ~NativeMessageQueue(); 41 42 inline sp<Looper> getLooper() { return mLooper; } 43 44 bool pollOnce(int timeoutMillis); 45 void wake(); 46 47private: 48 sp<Looper> mLooper; 49}; 50 51// ---------------------------------------------------------------------------- 52 53NativeMessageQueue::NativeMessageQueue() { 54 mLooper = Looper::getForThread(); 55 if (mLooper == NULL) { 56 mLooper = new Looper(false); 57 Looper::setForThread(mLooper); 58 } 59} 60 61NativeMessageQueue::~NativeMessageQueue() { 62} 63 64bool NativeMessageQueue::pollOnce(int timeoutMillis) { 65 return mLooper->pollOnce(timeoutMillis) != ALOOPER_POLL_TIMEOUT; 66} 67 68void NativeMessageQueue::wake() { 69 mLooper->wake(); 70} 71 72// ---------------------------------------------------------------------------- 73 74static NativeMessageQueue* android_os_MessageQueue_getNativeMessageQueue(JNIEnv* env, 75 jobject messageQueueObj) { 76 jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr); 77 return reinterpret_cast<NativeMessageQueue*>(intPtr); 78} 79 80static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, 81 NativeMessageQueue* nativeMessageQueue) { 82 env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, 83 reinterpret_cast<jint>(nativeMessageQueue)); 84} 85 86sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) { 87 NativeMessageQueue* nativeMessageQueue = 88 android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj); 89 return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL; 90} 91 92static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) { 93 NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); 94 if (! nativeMessageQueue) { 95 jniThrowRuntimeException(env, "Unable to allocate native queue"); 96 return; 97 } 98 99 android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue); 100} 101 102static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) { 103 NativeMessageQueue* nativeMessageQueue = 104 android_os_MessageQueue_getNativeMessageQueue(env, obj); 105 if (nativeMessageQueue) { 106 android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL); 107 delete nativeMessageQueue; 108 } 109} 110 111static void throwQueueNotInitialized(JNIEnv* env) { 112 jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized"); 113} 114 115static jboolean android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, 116 jint timeoutMillis) { 117 NativeMessageQueue* nativeMessageQueue = 118 android_os_MessageQueue_getNativeMessageQueue(env, obj); 119 if (! nativeMessageQueue) { 120 throwQueueNotInitialized(env); 121 return false; 122 } 123 return nativeMessageQueue->pollOnce(timeoutMillis); 124} 125 126static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj) { 127 NativeMessageQueue* nativeMessageQueue = 128 android_os_MessageQueue_getNativeMessageQueue(env, obj); 129 if (! nativeMessageQueue) { 130 throwQueueNotInitialized(env); 131 return; 132 } 133 return nativeMessageQueue->wake(); 134} 135 136// ---------------------------------------------------------------------------- 137 138static JNINativeMethod gMessageQueueMethods[] = { 139 /* name, signature, funcPtr */ 140 { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit }, 141 { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy }, 142 { "nativePollOnce", "(I)Z", (void*)android_os_MessageQueue_nativePollOnce }, 143 { "nativeWake", "()V", (void*)android_os_MessageQueue_nativeWake } 144}; 145 146#define FIND_CLASS(var, className) \ 147 var = env->FindClass(className); \ 148 LOG_FATAL_IF(! var, "Unable to find class " className); \ 149 var = jclass(env->NewGlobalRef(var)); 150 151#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 152 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 153 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 154 155int register_android_os_MessageQueue(JNIEnv* env) { 156 int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 157 gMessageQueueMethods, NELEM(gMessageQueueMethods)); 158 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 159 160 FIND_CLASS(gMessageQueueClassInfo.clazz, "android/os/MessageQueue"); 161 162 GET_FIELD_ID(gMessageQueueClassInfo.mPtr, gMessageQueueClassInfo.clazz, 163 "mPtr", "I"); 164 165 return 0; 166} 167 168} // namespace android 169