1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/message_pump_android.h"
9 #include "base/android/jni_android.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/run_loop.h"
14 #include "base/time.h"
15 #include "jni/SystemMessageHandler_jni.h"
17 using base::android::ScopedJavaLocalRef
;
21 base::LazyInstance
<base::android::ScopedJavaGlobalRef
<jobject
> >
22 g_system_message_handler_obj
= LAZY_INSTANCE_INITIALIZER
;
26 // ----------------------------------------------------------------------------
27 // Native JNI methods called by Java.
28 // ----------------------------------------------------------------------------
29 // This method can not move to anonymous namespace as it has been declared as
30 // 'static' in system_message_handler_jni.h.
31 static jboolean
DoRunLoopOnce(JNIEnv
* env
, jobject obj
, jint native_delegate
) {
32 base::MessagePump::Delegate
* delegate
=
33 reinterpret_cast<base::MessagePump::Delegate
*>(native_delegate
);
35 // This is based on MessagePumpForUI::DoRunLoop() from desktop.
36 // Note however that our system queue is handled in the java side.
37 // In desktop we inspect and process a single system message and then
38 // we call DoWork() / DoDelayedWork().
39 // On Android, the java message queue may contain messages for other handlers
40 // that will be processed before calling here again.
41 bool more_work_is_plausible
= delegate
->DoWork();
43 // This is the time when we need to do delayed work.
44 base::TimeTicks delayed_work_time
;
45 more_work_is_plausible
|= delegate
->DoDelayedWork(&delayed_work_time
);
47 // This is a major difference between android and other platforms: since we
48 // can't inspect it and process just one single message, instead we'll yeld
49 // the callstack, and post a message to call us back soon.
50 if (more_work_is_plausible
)
53 more_work_is_plausible
= delegate
->DoIdleWork();
54 if (!more_work_is_plausible
&& !delayed_work_time
.is_null()) {
55 // We only set the timer here as returning true would post a message.
57 (delayed_work_time
- base::TimeTicks::Now()).InMillisecondsRoundedUp();
58 Java_SystemMessageHandler_setDelayedTimer(env
, obj
, millis
);
60 return more_work_is_plausible
;
65 MessagePumpForUI::MessagePumpForUI()
69 MessagePumpForUI::~MessagePumpForUI() {
72 void MessagePumpForUI::Run(Delegate
* delegate
) {
73 NOTREACHED() << "UnitTests should rely on MessagePumpForUIStub in"
74 " test_stub_android.h";
77 void MessagePumpForUI::Start(Delegate
* delegate
) {
78 run_loop_
= new base::RunLoop();
79 // Since the RunLoop was just created above, BeforeRun should be guaranteed to
80 // return true (it only returns false if the RunLoop has been Quit already).
81 if (!run_loop_
->BeforeRun())
84 DCHECK(g_system_message_handler_obj
.Get().is_null());
86 JNIEnv
* env
= base::android::AttachCurrentThread();
89 g_system_message_handler_obj
.Get().Reset(
90 Java_SystemMessageHandler_create(env
, reinterpret_cast<jint
>(delegate
)));
93 void MessagePumpForUI::Quit() {
94 if (!g_system_message_handler_obj
.Get().is_null()) {
95 JNIEnv
* env
= base::android::AttachCurrentThread();
98 Java_SystemMessageHandler_removeTimer(env
,
99 g_system_message_handler_obj
.Get().obj());
100 g_system_message_handler_obj
.Get().Reset();
104 run_loop_
->AfterRun();
110 void MessagePumpForUI::ScheduleWork() {
111 DCHECK(!g_system_message_handler_obj
.Get().is_null());
113 JNIEnv
* env
= base::android::AttachCurrentThread();
116 Java_SystemMessageHandler_setTimer(env
,
117 g_system_message_handler_obj
.Get().obj());
120 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks
& delayed_work_time
) {
121 DCHECK(!g_system_message_handler_obj
.Get().is_null());
123 JNIEnv
* env
= base::android::AttachCurrentThread();
127 (delayed_work_time
- base::TimeTicks::Now()).InMillisecondsRoundedUp();
128 // Note that we're truncating to milliseconds as required by the java side,
129 // even though delayed_work_time is microseconds resolution.
130 Java_SystemMessageHandler_setDelayedTimer(env
,
131 g_system_message_handler_obj
.Get().obj(), millis
);
135 bool MessagePumpForUI::RegisterBindings(JNIEnv
* env
) {
136 return RegisterNativesImpl(env
);