android_os_MessageQueue.cpp revision 415d8c38199e258dfce92cdb0c69e056b3b51ef8
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    jclass clazz;
31fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
3246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jfieldID mPtr;   // native object attached to the DVM MessageQueue
3346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} gMessageQueueClassInfo;
34fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
35fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ----------------------------------------------------------------------------
36fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
3746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownclass NativeMessageQueue {
38fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatepublic:
3946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    NativeMessageQueue();
4046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    ~NativeMessageQueue();
41fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
424fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    inline sp<Looper> getLooper() { return mLooper; }
43fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
44415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    void pollOnce(int timeoutMillis);
4546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    void wake();
46fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
47fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateprivate:
484fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    sp<Looper> mLooper;
49fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate};
50fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
5146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
52fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
5346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeMessageQueue::NativeMessageQueue() {
544fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    mLooper = Looper::getForThread();
554fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    if (mLooper == NULL) {
564fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown        mLooper = new Looper(false);
574fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown        Looper::setForThread(mLooper);
58682674154e3fe88f6061245145f934f25f1a2eb8Dianne Hackborn    }
59fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
60fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
6146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff BrownNativeMessageQueue::~NativeMessageQueue() {
62fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
63fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
64415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownvoid NativeMessageQueue::pollOnce(int timeoutMillis) {
65415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    mLooper->pollOnce(timeoutMillis);
66fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
67fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
6846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid NativeMessageQueue::wake() {
694fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    mLooper->wake();
70fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
71fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
7246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// ----------------------------------------------------------------------------
73fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
7446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic NativeMessageQueue* android_os_MessageQueue_getNativeMessageQueue(JNIEnv* env,
7546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        jobject messageQueueObj) {
7646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr);
7746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    return reinterpret_cast<NativeMessageQueue*>(intPtr);
78fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
79fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
8046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj,
8146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        NativeMessageQueue* nativeMessageQueue) {
8246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr,
8346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown             reinterpret_cast<jint>(nativeMessageQueue));
84fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
85fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
864fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brownsp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) {
8746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    NativeMessageQueue* nativeMessageQueue =
8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj);
894fe6c3e51be77e35f40872cdbca6c80f8f8b7ecbJeff Brown    return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL;
9046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
91fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
9246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
9346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
9446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    if (! nativeMessageQueue) {
9546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        jniThrowRuntimeException(env, "Unable to allocate native queue");
9646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        return;
97fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate    }
98fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
9946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
100fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
101fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
10346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    NativeMessageQueue* nativeMessageQueue =
10446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            android_os_MessageQueue_getNativeMessageQueue(env, obj);
10546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    if (nativeMessageQueue) {
10646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
10746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        delete nativeMessageQueue;
108fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate    }
109fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
110fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
11146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownstatic void throwQueueNotInitialized(JNIEnv* env) {
11246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized");
113fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
114fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
115415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownstatic void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
116415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown        jint ptr, jint timeoutMillis) {
117415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
118415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    nativeMessageQueue->pollOnce(timeoutMillis);
119fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
120fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
121415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brownstatic void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
122415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
12346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    return nativeMessageQueue->wake();
124fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
125fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
126fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate// ----------------------------------------------------------------------------
127fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
128fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tatestatic JNINativeMethod gMessageQueueMethods[] = {
129fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate    /* name, signature, funcPtr */
13046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit },
13146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy },
132415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce },
133415d8c38199e258dfce92cdb0c69e056b3b51ef8Jeff Brown    { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake }
134fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate};
135fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
13646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define FIND_CLASS(var, className) \
13746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = env->FindClass(className); \
13846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className); \
13946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = jclass(env->NewGlobalRef(var));
14046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
14146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
14246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
14346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
14446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
145fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tateint register_android_os_MessageQueue(JNIEnv* env) {
14646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    int res = jniRegisterNativeMethods(env, "android/os/MessageQueue",
14746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            gMessageQueueMethods, NELEM(gMessageQueueMethods));
14846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
14946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
15046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    FIND_CLASS(gMessageQueueClassInfo.clazz, "android/os/MessageQueue");
151fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
15246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    GET_FIELD_ID(gMessageQueueClassInfo.mPtr, gMessageQueueClassInfo.clazz,
15346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            "mPtr", "I");
154fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
15546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    return 0;
156fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate}
157fa9e7c05c7be6891a6cf85a11dc635a6e6853078Christopher Tate
15846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android
159