diff options
author | michaelbai@google.com <michaelbai@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-02 16:11:16 +0000 |
---|---|---|
committer | michaelbai@google.com <michaelbai@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-02 16:11:16 +0000 |
commit | 61c86c6a23ab32e81337f66f1b958d8ec3e8bd45 (patch) | |
tree | 64f18cd34be5ad9ec1140c3e334f5483af8af462 /base/message_pump_android.cc | |
parent | eccefee0229e222c0130dca22412b4dccfa3f181 (diff) | |
download | chromium_src-61c86c6a23ab32e81337f66f1b958d8ec3e8bd45.zip chromium_src-61c86c6a23ab32e81337f66f1b958d8ec3e8bd45.tar.gz chromium_src-61c86c6a23ab32e81337f66f1b958d8ec3e8bd45.tar.bz2 |
Android's paths and message loop implementation with JNI
BUG=
TEST=
Review URL: http://codereview.chromium.org/7518032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95085 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_pump_android.cc')
-rw-r--r-- | base/message_pump_android.cc | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/base/message_pump_android.cc b/base/message_pump_android.cc new file mode 100644 index 0000000..d9fdf9c --- /dev/null +++ b/base/message_pump_android.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/message_pump_android.h" + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/logging.h" +#include "jni/system_message_handler_jni.h" + +using base::android::AutoJObject; + +namespace { + +const char* kClassPathName = "com/android/chromeview/base/SystemMessageHandler"; + +jobject g_system_message_handler_obj = NULL; + +} // namespace + +// ---------------------------------------------------------------------------- +// Native JNI methods called by Java. +// ---------------------------------------------------------------------------- +// This method can not move to anonymous namespace as it has been declared as +// 'static' in system_message_handler_jni.h. +static jboolean DoRunLoopOnce(JNIEnv* env, jobject obj, jint native_delegate) { + base::MessagePump::Delegate* delegate = + reinterpret_cast<base::MessagePump::Delegate*>(native_delegate); + DCHECK(delegate); + // This is based on MessagePumpForUI::DoRunLoop() from desktop. + // Note however that our system queue is handled in the java side. + // In desktop we inspect and process a single system message and then + // we call DoWork() / DoDelayedWork(). + // On Android, the java message queue may contain messages for other handlers + // that will be processed before calling here again. + bool more_work_is_plausible = delegate->DoWork(); + + // This is the time when we need to do delayed work. + base::TimeTicks delayed_work_time; + more_work_is_plausible |= delegate->DoDelayedWork(&delayed_work_time); + + // This is a major difference between android and other platforms: since we + // can't inspect it and process just one single message, instead we'll yeld + // the callstack, and post a message to call us back soon. + if (more_work_is_plausible) + return true; + + more_work_is_plausible = delegate->DoIdleWork(); + if (!more_work_is_plausible && !delayed_work_time.is_null()) { + // We only set the timer here as returning true would post a message. + jlong millis = + (delayed_work_time - base::TimeTicks::Now()).InMillisecondsRoundedUp(); + Java_SystemMessageHandler_setDelayedTimer(env, obj, millis); + base::android::CheckException(env); + } + return more_work_is_plausible; +} + +namespace base { + +MessagePumpForUI::MessagePumpForUI() + : state_(NULL) { +} + +MessagePumpForUI::~MessagePumpForUI() { +} + +void MessagePumpForUI::Run(Delegate* delegate) { + NOTREACHED() << "UnitTests should rely on MessagePumpForUIStub in" + " test_stub_android.h"; +} + +void MessagePumpForUI::Start(Delegate* delegate) { + state_ = new MessageLoop::AutoRunState(MessageLoop::current()); + + DCHECK(!g_system_message_handler_obj); + + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + jclass clazz = env->FindClass(kClassPathName); + DCHECK(!clazz); + + jmethodID constructor = base::android::GetMethodID(env, clazz, "<init>", + "(I)V"); + AutoJObject client = AutoJObject::FromLocalRef( + env, env->NewObject(clazz, constructor, delegate)); + DCHECK(!client.obj()); + + g_system_message_handler_obj = env->NewGlobalRef(client.obj()); + + base::android::CheckException(env); +} + +void MessagePumpForUI::Quit() { + if (g_system_message_handler_obj) { + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_SystemMessageHandler_removeTimer(env, g_system_message_handler_obj); + env->DeleteGlobalRef(g_system_message_handler_obj); + base::android::CheckException(env); + g_system_message_handler_obj = NULL; + } + + if (state_) { + delete state_; + state_ = NULL; + } +} + +void MessagePumpForUI::ScheduleWork() { + if (!g_system_message_handler_obj) + return; + + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + Java_SystemMessageHandler_setTimer(env, g_system_message_handler_obj); + base::android::CheckException(env); + +} + +void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { + if (!g_system_message_handler_obj) + return; + + JNIEnv* env = base::android::AttachCurrentThread(); + DCHECK(env); + + jlong millis = + (delayed_work_time - base::TimeTicks::Now()).InMillisecondsRoundedUp(); + // Note that we're truncating to milliseconds as required by the java side, + // even though delayed_work_time is microseconds resolution. + Java_SystemMessageHandler_setDelayedTimer(env, g_system_message_handler_obj, + millis); + base::android::CheckException(env); +} + +// Register native methods +bool RegisterSystemMessageHandler(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace base |