android_os_MessageQueue.cpp revision 4fe6c3e51be77e35f40872cdbca6c80f8f8b7ecb
1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/*
2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2010 The Android Open Source Project
3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License");
5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License.
6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at
7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *      http://www.apache.org/licenses/LICENSE-2.0
9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks *
10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software
11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS,
12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and
14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License.
15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */
16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#define LOG_TAG "MessageQueue-JNI"
18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "JNIHelp.h"
20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <utils/Looper.h>
22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include <utils/Log.h>
23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks#include "android_os_MessageQueue.h"
24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksnamespace android {
26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// ----------------------------------------------------------------------------
28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksstatic struct {
30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    jclass clazz;
31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    jfieldID mPtr;   // native object attached to the DVM MessageQueue
33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} gMessageQueueClassInfo;
34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// ----------------------------------------------------------------------------
36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksclass NativeMessageQueue {
38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic:
39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    NativeMessageQueue();
40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    ~NativeMessageQueue();
41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    inline sp<Looper> getLooper() { return mLooper; }
43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    bool pollOnce(int timeoutMillis);
45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    void wake();
46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksprivate:
48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks    sp<Looper> mLooper;
49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks};
50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks
51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks// ----------------------------------------------------------------------------
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