1 // Copyright 2013 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 "content/public/test/nested_message_pump_android.h"
7 #include "base/android/jni_android.h"
8 #include "base/android/scoped_java_ref.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/time/time.h"
14 #include "jni/NestedSystemMessageHandler_jni.h"
18 base::LazyInstance
<base::android::ScopedJavaGlobalRef
<jobject
> >
19 g_message_handler_obj
= LAZY_INSTANCE_INITIALIZER
;
26 struct NestedMessagePumpAndroid::RunState
{
27 RunState(base::MessagePump::Delegate
* delegate
, int run_depth
)
31 waitable_event(false, false) {
34 base::MessagePump::Delegate
* delegate
;
36 // Used to count how many Run() invocations are on the stack.
39 // Used to flag that the current Run() invocation should return ASAP.
42 // Used to sleep until there is more work to do.
43 base::WaitableEvent waitable_event
;
45 // The time at which we should call DoDelayedWork.
46 base::TimeTicks delayed_work_time
;
49 NestedMessagePumpAndroid::NestedMessagePumpAndroid()
53 NestedMessagePumpAndroid::~NestedMessagePumpAndroid() {
56 void NestedMessagePumpAndroid::Run(Delegate
* delegate
) {
57 RunState
state(delegate
, state_
? state_
->run_depth
+ 1 : 1);
58 RunState
* previous_state
= state_
;
61 JNIEnv
* env
= base::android::AttachCurrentThread();
64 // Need to cap the wait time to allow task processing on the java
65 // side. Otherwise, a long wait time on the native will starve java
67 base::TimeDelta max_delay
= base::TimeDelta::FromMilliseconds(100);
70 if (state_
->should_quit
)
73 bool did_work
= state_
->delegate
->DoWork();
74 if (state_
->should_quit
)
77 did_work
|= state_
->delegate
->DoDelayedWork(&state_
->delayed_work_time
);
78 if (state_
->should_quit
)
85 did_work
= state_
->delegate
->DoIdleWork();
86 if (state_
->should_quit
)
92 // No native tasks to process right now. Process tasks from the Java
93 // System message handler. This will return when the java message queue
95 bool ret
= Java_NestedSystemMessageHandler_runNestedLoopTillIdle(env
,
96 g_message_handler_obj
.Get().obj());
97 CHECK(ret
) << "Error running java message loop, tests will likely fail.";
99 base::ThreadRestrictions::ScopedAllowWait allow_wait
;
100 if (state_
->delayed_work_time
.is_null()) {
101 state_
->waitable_event
.TimedWait(max_delay
);
103 base::TimeDelta delay
=
104 state_
->delayed_work_time
- base::TimeTicks::Now();
105 if (delay
> max_delay
)
107 if (delay
> base::TimeDelta()) {
108 state_
->waitable_event
.TimedWait(delay
);
110 // It looks like delayed_work_time indicates a time in the past, so we
111 // need to call DoDelayedWork now.
112 state_
->delayed_work_time
= base::TimeTicks();
117 state_
= previous_state
;
120 void NestedMessagePumpAndroid::Start(
121 base::MessagePump::Delegate
* delegate
) {
122 JNIEnv
* env
= base::android::AttachCurrentThread();
124 g_message_handler_obj
.Get().Reset(
125 Java_NestedSystemMessageHandler_create(env
));
127 base::MessagePumpForUI::Start(delegate
);
130 void NestedMessagePumpAndroid::Quit() {
132 state_
->should_quit
= true;
133 state_
->waitable_event
.Signal();
136 base::MessagePumpForUI::Quit();
139 void NestedMessagePumpAndroid::ScheduleWork() {
141 state_
->waitable_event
.Signal();
145 base::MessagePumpForUI::ScheduleWork();
148 void NestedMessagePumpAndroid::ScheduleDelayedWork(
149 const base::TimeTicks
& delayed_work_time
) {
151 // We know that we can't be blocked on Wait right now since this method can
152 // only be called on the same thread as Run, so we only need to update our
153 // record of how long to sleep when we do sleep.
154 state_
->delayed_work_time
= delayed_work_time
;
158 base::MessagePumpForUI::ScheduleDelayedWork(delayed_work_time
);
162 bool NestedMessagePumpAndroid::RegisterJni(JNIEnv
* env
) {
163 return RegisterNativesImpl(env
);
166 } // namespace content