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/Looper.h> 22 #include <utils/Log.h> 23 #include "android_os_MessageQueue.h" 24 25 namespace android { 26 27 // ---------------------------------------------------------------------------- 28 29 static struct { 30 jfieldID mPtr; // native object attached to the DVM MessageQueue 31 } gMessageQueueClassInfo; 32 33 // ---------------------------------------------------------------------------- 34 35 class NativeMessageQueue { 36 public: 37 NativeMessageQueue(); 38 ~NativeMessageQueue(); 39 40 inline sp<Looper> getLooper() { return mLooper; } 41 42 void pollOnce(int timeoutMillis); 43 void wake(); 44 45 private: 46 sp<Looper> mLooper; 47 }; 48 49 // ---------------------------------------------------------------------------- 50 51 NativeMessageQueue::NativeMessageQueue() { 52 mLooper = Looper::getForThread(); 53 if (mLooper == NULL) { 54 mLooper = new Looper(false); 55 Looper::setForThread(mLooper); 56 } 57 } 58 59 NativeMessageQueue::~NativeMessageQueue() { 60 } 61 62 void NativeMessageQueue::pollOnce(int timeoutMillis) { 63 mLooper->pollOnce(timeoutMillis); 64 } 65 66 void NativeMessageQueue::wake() { 67 mLooper->wake(); 68 } 69 70 // ---------------------------------------------------------------------------- 71 72 static NativeMessageQueue* android_os_MessageQueue_getNativeMessageQueue(JNIEnv* env, 73 jobject messageQueueObj) { 74 jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr); 75 return reinterpret_cast<NativeMessageQueue*>(intPtr); 76 } 77 78 static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, 79 NativeMessageQueue* nativeMessageQueue) { 80 env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, 81 reinterpret_cast<jint>(nativeMessageQueue)); 82 } 83 84 sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) { 85 NativeMessageQueue* nativeMessageQueue = 86 android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj); 87 return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL; 88 } 89 90 static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) { 91 NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); 92 if (! nativeMessageQueue) { 93 jniThrowRuntimeException(env, "Unable to allocate native queue"); 94 return; 95 } 96 97 android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue); 98 } 99 100 static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) { 101 NativeMessageQueue* nativeMessageQueue = 102 android_os_MessageQueue_getNativeMessageQueue(env, obj); 103 if (nativeMessageQueue) { 104 android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL); 105 delete nativeMessageQueue; 106 } 107 } 108 109 static void throwQueueNotInitialized(JNIEnv* env) { 110 jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized"); 111 } 112 113 static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, 114 jint ptr, jint timeoutMillis) { 115 NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 116 nativeMessageQueue->pollOnce(timeoutMillis); 117 } 118 119 static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) { 120 NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 121 return nativeMessageQueue->wake(); 122 } 123 124 // ---------------------------------------------------------------------------- 125 126 static JNINativeMethod gMessageQueueMethods[] = { 127 /* name, signature, funcPtr */ 128 { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit }, 129 { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy }, 130 { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce }, 131 { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake } 132 }; 133 134 #define FIND_CLASS(var, className) \ 135 var = env->FindClass(className); \ 136 LOG_FATAL_IF(! var, "Unable to find class " className); 137 138 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 139 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 140 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 141 142 int register_android_os_MessageQueue(JNIEnv* env) { 143 int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 144 gMessageQueueMethods, NELEM(gMessageQueueMethods)); 145 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 146 147 jclass clazz; 148 FIND_CLASS(clazz, "android/os/MessageQueue"); 149 150 GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz, 151 "mPtr", "I"); 152 153 return 0; 154 } 155 156 } // namespace android 157