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