android_os_MessageQueue.cpp revision 682674154e3fe88f6061245145f934f25f1a2eb8
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "MessageQueue-JNI" 18 19#include "JNIHelp.h" 20 21#include <utils/PollLoop.h> 22#include <utils/Log.h> 23#include "android_os_MessageQueue.h" 24 25namespace android { 26 27// ---------------------------------------------------------------------------- 28 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<PollLoop> getPollLoop() { return mPollLoop; } 43 44 bool pollOnce(int timeoutMillis); 45 void wake(); 46 47private: 48 sp<PollLoop> mPollLoop; 49}; 50 51// ---------------------------------------------------------------------------- 52 53NativeMessageQueue::NativeMessageQueue() { 54 mPollLoop = PollLoop::getForThread(); 55 if (mPollLoop == NULL) { 56 mPollLoop = new PollLoop(); 57 PollLoop::setForThread(mPollLoop); 58 } 59} 60 61NativeMessageQueue::~NativeMessageQueue() { 62} 63 64bool NativeMessageQueue::pollOnce(int timeoutMillis) { 65 return mPollLoop->pollOnce(timeoutMillis); 66} 67 68void NativeMessageQueue::wake() { 69 mPollLoop->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<PollLoop> android_os_MessageQueue_getPollLoop(JNIEnv* env, jobject messageQueueObj) { 87 NativeMessageQueue* nativeMessageQueue = 88 android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj); 89 return nativeMessageQueue != NULL ? nativeMessageQueue->getPollLoop() : 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