15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_android.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <jni.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/jni_android.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/android/scoped_java_ref.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jni/SystemMessageHandler_jni.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::ScopedJavaLocalRef;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Native JNI methods called by Java.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method can not move to anonymous namespace as it has been declared as
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'static' in system_message_handler_jni.h.
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void DoRunLoopOnce(JNIEnv* env, jobject obj, jlong native_delegate,
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    jlong delayed_scheduled_time_ticks) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::MessagePump::Delegate* delegate =
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<base::MessagePump::Delegate*>(native_delegate);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is based on MessagePumpForUI::DoRunLoop() from desktop.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note however that our system queue is handled in the java side.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In desktop we inspect and process a single system message and then
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we call DoWork() / DoDelayedWork().
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Android, the java message queue may contain messages for other handlers
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that will be processed before calling here again.
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool did_work = delegate->DoWork();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // In the java side, |SystemMessageHandler| keeps a single "delayed" message.
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // It's an expensive operation to |removeMessage| there, so this is optimized
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // to avoid those calls.
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // At this stage, |next_delayed_work_time| can be:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 1) The same as previously scheduled: nothing to be done, move along. This
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // is the typical case, since this method is called for every single message.
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 2) Not previously scheduled: just post a new message in java.
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 3) Shorter than previously scheduled: far less common. In this case,
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |removeMessage| and post a new one.
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 4) Longer than previously scheduled (or null): nothing to be done, move
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // along.
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  //
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Side note: base::TimeTicks is a C++ representation and can't be
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // compared in java. When calling |scheduleDelayedWork|, pass the
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |InternalValue()| to java and then back to C++ so the comparisons can be
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // done here.
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This roundtrip allows comparing TimeTicks directly (cheap) and
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // avoid comparisons with TimeDelta / Now() (expensive).
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TimeTicks next_delayed_work_time;
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  did_work |= delegate->DoDelayedWork(&next_delayed_work_time);
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!next_delayed_work_time.is_null()) {
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Schedule a new message if there's nothing already scheduled or there's a
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // shorter delay than previously scheduled (see (2) and (3) above).
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (delayed_scheduled_time_ticks == 0 ||
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        next_delayed_work_time < base::TimeTicks::FromInternalValue(
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            delayed_scheduled_time_ticks)) {
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      Java_SystemMessageHandler_scheduleDelayedWork(env, obj,
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          next_delayed_work_time.ToInternalValue(),
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          (next_delayed_work_time -
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           base::TimeTicks::Now()).InMillisecondsRoundedUp());
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a major difference between android and other platforms: since we
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can't inspect it and process just one single message, instead we'll yeld
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // the callstack.
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (did_work)
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  delegate->DoIdleWork();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpForUI::MessagePumpForUI()
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : run_loop_(NULL) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpForUI::~MessagePumpForUI() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpForUI::Run(Delegate* delegate) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "UnitTests should rely on MessagePumpForUIStub in"
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      " test_stub_android.h";
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpForUI::Start(Delegate* delegate) {
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  run_loop_ = new RunLoop();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since the RunLoop was just created above, BeforeRun should be guaranteed to
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return true (it only returns false if the RunLoop has been Quit already).
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!run_loop_->BeforeRun())
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(system_message_handler_obj_.is_null());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(env);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  system_message_handler_obj_.Reset(
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Java_SystemMessageHandler_create(
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          env, reinterpret_cast<intptr_t>(delegate)));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpForUI::Quit() {
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!system_message_handler_obj_.is_null()) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JNIEnv* env = base::android::AttachCurrentThread();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(env);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Java_SystemMessageHandler_removeAllPendingMessages(env,
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        system_message_handler_obj_.obj());
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    system_message_handler_obj_.Reset();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (run_loop_) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop_->AfterRun();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete run_loop_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run_loop_ = NULL;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpForUI::ScheduleWork() {
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!system_message_handler_obj_.is_null());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(env);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Java_SystemMessageHandler_scheduleWork(env,
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      system_message_handler_obj_.obj());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!system_message_handler_obj_.is_null());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JNIEnv* env = base::android::AttachCurrentThread();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(env);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  jlong millis =
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      (delayed_work_time - TimeTicks::Now()).InMillisecondsRoundedUp();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we're truncating to milliseconds as required by the java side,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // even though delayed_work_time is microseconds resolution.
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Java_SystemMessageHandler_scheduleDelayedWork(env,
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      system_message_handler_obj_.obj(),
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      delayed_work_time.ToInternalValue(), millis);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessagePumpForUI::RegisterBindings(JNIEnv* env) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return RegisterNativesImpl(env);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
163