From 864693461b6223a995038847591b17abe2de647e Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Mon, 28 Jan 2013 14:25:53 -0800 Subject: [PATCH] Optimize Looper JNI code. Use static native methods. Release the native looper objects as soon as the Looper quits instead of waiting until the GC finalizer to take care of it. Change-Id: I02783e48782a8f972ec2138862f700ade33d8e78 --- core/java/android/os/MessageQueue.java | 20 ++++++--- core/jni/android_os_MessageQueue.cpp | 43 +++++-------------- ...droid_server_input_InputManagerService.cpp | 5 +++ 3 files changed, 30 insertions(+), 38 deletions(-) diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java index 5ad60ec0e7ee6..222578a955130 100644 --- a/core/java/android/os/MessageQueue.java +++ b/core/java/android/os/MessageQueue.java @@ -48,10 +48,10 @@ public class MessageQueue { // Barriers are indicated by messages with a null target whose arg1 field carries the token. private int mNextBarrierToken; - private native void nativeInit(); - private native void nativeDestroy(); - private native void nativePollOnce(int ptr, int timeoutMillis); - private native void nativeWake(int ptr); + private native static int nativeInit(); + private native static void nativeDestroy(int ptr); + private native static void nativePollOnce(int ptr, int timeoutMillis); + private native static void nativeWake(int ptr); /** * Callback interface for discovering when a thread is going to block @@ -102,18 +102,25 @@ public class MessageQueue { MessageQueue(boolean quitAllowed) { mQuitAllowed = quitAllowed; - nativeInit(); + mPtr = nativeInit(); } @Override protected void finalize() throws Throwable { try { - nativeDestroy(); + dispose(); } finally { super.finalize(); } } + private void dispose() { + if (mPtr != 0) { + nativeDestroy(mPtr); + mPtr = 0; + } + } + final Message next() { int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; @@ -126,6 +133,7 @@ public class MessageQueue { synchronized (this) { if (mQuiting) { + dispose(); return null; } diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp index a4dcac6d886a1..75406458c177f 100644 --- a/core/jni/android_os_MessageQueue.cpp +++ b/core/jni/android_os_MessageQueue.cpp @@ -109,55 +109,34 @@ void NativeMessageQueue::wake() { // ---------------------------------------------------------------------------- -static NativeMessageQueue* android_os_MessageQueue_getNativeMessageQueue(JNIEnv* env, - jobject messageQueueObj) { +sp android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) { jint intPtr = env->GetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr); return reinterpret_cast(intPtr); } -static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, - NativeMessageQueue* nativeMessageQueue) { - env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, - reinterpret_cast(nativeMessageQueue)); -} - -sp android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) { - NativeMessageQueue* nativeMessageQueue = - android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj); - return nativeMessageQueue; -} - -static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) { +static jint android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) { NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue(); if (!nativeMessageQueue) { jniThrowRuntimeException(env, "Unable to allocate native queue"); - return; + return 0; } nativeMessageQueue->incStrong(env); - android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue); + return reinterpret_cast(nativeMessageQueue); } -static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) { - NativeMessageQueue* nativeMessageQueue = - android_os_MessageQueue_getNativeMessageQueue(env, obj); - if (nativeMessageQueue) { - android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL); - nativeMessageQueue->decStrong(env); - } +static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jclass clazz, jint ptr) { + NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); + nativeMessageQueue->decStrong(env); } -static void throwQueueNotInitialized(JNIEnv* env) { - jniThrowException(env, "java/lang/IllegalStateException", "Message queue not initialized"); -} - -static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj, +static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jclass clazz, jint ptr, jint timeoutMillis) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); nativeMessageQueue->pollOnce(env, timeoutMillis); } -static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) { +static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jint ptr) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); return nativeMessageQueue->wake(); } @@ -166,8 +145,8 @@ static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint pt static JNINativeMethod gMessageQueueMethods[] = { /* name, signature, funcPtr */ - { "nativeInit", "()V", (void*)android_os_MessageQueue_nativeInit }, - { "nativeDestroy", "()V", (void*)android_os_MessageQueue_nativeDestroy }, + { "nativeInit", "()I", (void*)android_os_MessageQueue_nativeInit }, + { "nativeDestroy", "(I)V", (void*)android_os_MessageQueue_nativeDestroy }, { "nativePollOnce", "(II)V", (void*)android_os_MessageQueue_nativePollOnce }, { "nativeWake", "(I)V", (void*)android_os_MessageQueue_nativeWake } }; diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index a97becfd64741..57803e362c17d 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -975,6 +975,11 @@ void NativeInputManager::loadPointerResources(PointerResources* outResources) { static jint nativeInit(JNIEnv* env, jclass clazz, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); + if (messageQueue == NULL) { + jniThrowRuntimeException(env, "MessageQueue is not initialized."); + return 0; + } + NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(serviceObj);