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 jclass clazz; 31 32 jfieldID mPtr; // native object attached to the DVM MessageQueue 33 } gMessageQueueClassInfo; 34 35 // ---------------------------------------------------------------------------- 36 37 class NativeMessageQueue { 38 public: 39 NativeMessageQueue(); 40 ~NativeMessageQueue(); 41 42 inline sp<Looper> getLooper() { return mLooper; } 43 44 void pollOnce(int timeoutMillis); 45 void wake(); 46 47 private: 48 sp<Looper> mLooper; 49 }; 50 51 // ---------------------------------------------------------------------------- 52 53 NativeMessageQueue::NativeMessageQueue() { 54 mLooper = Looper::getForThread(); 55 if (mLooper == NULL) { 56 mLooper = new Looper(false); 57 Looper::setForThread(mLooper); 58 } 59 } 60 61 NativeMessageQueue::~NativeMessageQueue() { 62 } 63 64 void NativeMessageQueue::pollOnce(int timeoutMillis) { 65 mLooper->pollOnce(timeoutMillis); 66 } 67 68 void NativeMessageQueue::wake() { 69 mLooper->wake(); 70 } 71 72 // ---------------------------------------------------------------------------- 73 74 static 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 80 static 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 86 sp<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 92 static 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 102 static 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 111 static void throwQueueNotInitialized(JNIEnv* env) { 112 jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized"); 113 } 114 115 static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, 116 jint ptr, jint timeoutMillis) { 117 NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 118 nativeMessageQueue->pollOnce(timeoutMillis); 119 } 120 121 static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) { 122 NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 123 return nativeMessageQueue->wake(); 124 } 125 126 // ---------------------------------------------------------------------------- 127 128 static JNINativeMethod gMessageQueueMethods[] = { 129 /* name, signature, funcPtr */ 130 { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit }, 131 { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy }, 132 { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce }, 133 { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake } 134 }; 135 136 #define FIND_CLASS(var, className) \ 137 var = env->FindClass(className); \ 138 LOG_FATAL_IF(! var, "Unable to find class " className); \ 139 var = jclass(env->NewGlobalRef(var)); 140 141 #define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 142 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 143 LOG_FATAL_IF(! var, "Unable to find field " fieldName); 144 145 int register_android_os_MessageQueue(JNIEnv* env) { 146 int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 147 gMessageQueueMethods, NELEM(gMessageQueueMethods)); 148 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 149 150 FIND_CLASS(gMessageQueueClassInfo.clazz, "android/os/MessageQueue"); 151 152 GET_FIELD_ID(gMessageQueueClassInfo.mPtr, gMessageQueueClassInfo.clazz, 153 "mPtr", "I"); 154 155 return 0; 156 } 157 158 } // namespace android 159