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" 20fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 214fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown#include <utils/Looper.h> 22fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate#include <utils/Log.h> 2346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include "android_os_MessageQueue.h" 24fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 2546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android { 26fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 27fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ---------------------------------------------------------------------------- 28fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 29fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic struct { 3046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jfieldID mPtr; // native object attached to the DVM MessageQueue 3146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gMessageQueueClassInfo; 32fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 33fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ---------------------------------------------------------------------------- 34fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 3546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownclass NativeMessageQueue { 36fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatepublic: 3746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue(); 3846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown ~NativeMessageQueue(); 39fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 404fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown inline sp<Looper> getLooper() { return mLooper; } 41fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 42415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown void pollOnce(int timeoutMillis); 4346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown void wake(); 44fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 45fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateprivate: 464fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown sp<Looper> mLooper; 47fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}; 48fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 4946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 50fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 5146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeMessageQueue::NativeMessageQueue() { 524fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper = Looper::getForThread(); 534fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown if (mLooper == NULL) { 544fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper = new Looper(false); 554fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown Looper::setForThread(mLooper); 56682674154e3fe88f6061245145f934f25f1a2eb8Dianne Hackborn } 57fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 58fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 5946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeMessageQueue::~NativeMessageQueue() { 60fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 61fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 62415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownvoid NativeMessageQueue::pollOnce(int timeoutMillis) { 63415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown mLooper->pollOnce(timeoutMillis); 64fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 65fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 6646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid NativeMessageQueue::wake() { 674fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown mLooper->wake(); 68fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 69fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 7046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ---------------------------------------------------------------------------- 71fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 7246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic NativeMessageQueue* android_os_MessageQueue_getNativeMessageQueue(JNIEnv* env, 7346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jobject messageQueueObj) { 7446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr); 7546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return reinterpret_cast<NativeMessageQueue*>(intPtr); 76fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 77fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 7846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, 7946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue* nativeMessageQueue) { 8046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, 8146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown reinterpret_cast<jint>(nativeMessageQueue)); 82fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 83fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 844fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brownsp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) { 8546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue* nativeMessageQueue = 8646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj); 874fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL; 8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} 89fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 9046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) { 9146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); 9246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (! nativeMessageQueue) { 9346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowRuntimeException(env, "Unable to allocate native queue"); 9446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return; 95fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate } 96fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 9746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue); 98fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 99fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 10046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) { 10146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown NativeMessageQueue* nativeMessageQueue = 10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_os_MessageQueue_getNativeMessageQueue(env, obj); 10346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown if (nativeMessageQueue) { 10446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL); 10546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown delete nativeMessageQueue; 106fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate } 107fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 108fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 10946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void throwQueueNotInitialized(JNIEnv* env) { 11046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized"); 111fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 112fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 113415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownstatic void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, 114415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown jint ptr, jint timeoutMillis) { 115415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 116415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown nativeMessageQueue->pollOnce(timeoutMillis); 117fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 118fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 119415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownstatic void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) { 120415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr); 12146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return nativeMessageQueue->wake(); 122fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 123fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 124fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ---------------------------------------------------------------------------- 125fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 126fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic JNINativeMethod gMessageQueueMethods[] = { 127fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate /* name, signature, funcPtr */ 12846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit }, 12946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy }, 130415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce }, 131415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake } 132fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}; 133fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 13446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \ 13546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->FindClass(className); \ 13617cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro LOG_FATAL_IF(! var, "Unable to find class " className); 13746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 13846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \ 13946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \ 14046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(! var, "Unable to find field " fieldName); 14146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 142fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateint register_android_os_MessageQueue(JNIEnv* env) { 14346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown int res = jniRegisterNativeMethods(env, "android/os/MessageQueue", 14446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown gMessageQueueMethods, NELEM(gMessageQueueMethods)); 14546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown LOG_FATAL_IF(res < 0, "Unable to register native methods."); 14646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown 14717cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro jclass clazz; 14817cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro FIND_CLASS(clazz, "android/os/MessageQueue"); 149fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 15017cc33a35729733aaa0a7706f38b1c45f0b1590aCarl Shapiro GET_FIELD_ID(gMessageQueueClassInfo.mPtr, clazz, 15146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown "mPtr", "I"); 152fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 15346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown return 0; 154fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate} 155fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate 15646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android 157