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. 4 5 #include "base/message_loop/message_pump_android.h" 6 7 #include <jni.h> 8 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/time.h" 15 #include "jni/SystemMessageHandler_jni.h" 16 17 using base::android::ScopedJavaLocalRef; 18 19 // ---------------------------------------------------------------------------- 20 // Native JNI methods called by Java. 21 // ---------------------------------------------------------------------------- 22 // This method can not move to anonymous namespace as it has been declared as 23 // 'static' in system_message_handler_jni.h. 24 static void DoRunLoopOnce(JNIEnv* env, jobject obj, jint native_delegate) { 25 base::MessagePump::Delegate* delegate = 26 reinterpret_cast<base::MessagePump::Delegate*>(native_delegate); 27 DCHECK(delegate); 28 // This is based on MessagePumpForUI::DoRunLoop() from desktop. 29 // Note however that our system queue is handled in the java side. 30 // In desktop we inspect and process a single system message and then 31 // we call DoWork() / DoDelayedWork(). 32 // On Android, the java message queue may contain messages for other handlers 33 // that will be processed before calling here again. 34 bool did_work = delegate->DoWork(); 35 36 // This is the time when we need to do delayed work. 37 base::TimeTicks delayed_work_time; 38 did_work |= delegate->DoDelayedWork(&delayed_work_time); 39 40 // Always call this if there is a delayed message waiting in the queue 41 // since is at most one delayed message in the Java message handler, and this 42 // function call may be the result of that message being handled. 43 if (!delayed_work_time.is_null()) { 44 Java_SystemMessageHandler_setDelayedTimer(env, obj, 45 (delayed_work_time - base::TimeTicks::Now()).InMillisecondsRoundedUp()); 46 } 47 48 // This is a major difference between android and other platforms: since we 49 // can't inspect it and process just one single message, instead we'll yeld 50 // the callstack. 51 if (did_work) 52 return; 53 54 delegate->DoIdleWork(); 55 } 56 57 namespace base { 58 59 MessagePumpForUI::MessagePumpForUI() 60 : run_loop_(NULL) { 61 } 62 63 MessagePumpForUI::~MessagePumpForUI() { 64 } 65 66 void MessagePumpForUI::Run(Delegate* delegate) { 67 NOTREACHED() << "UnitTests should rely on MessagePumpForUIStub in" 68 " test_stub_android.h"; 69 } 70 71 void MessagePumpForUI::Start(Delegate* delegate) { 72 run_loop_ = new RunLoop(); 73 // Since the RunLoop was just created above, BeforeRun should be guaranteed to 74 // return true (it only returns false if the RunLoop has been Quit already). 75 if (!run_loop_->BeforeRun()) 76 NOTREACHED(); 77 78 DCHECK(system_message_handler_obj_.is_null()); 79 80 JNIEnv* env = base::android::AttachCurrentThread(); 81 DCHECK(env); 82 83 system_message_handler_obj_.Reset( 84 Java_SystemMessageHandler_create(env, reinterpret_cast<jint>(delegate))); 85 } 86 87 void MessagePumpForUI::Quit() { 88 if (!system_message_handler_obj_.is_null()) { 89 JNIEnv* env = base::android::AttachCurrentThread(); 90 DCHECK(env); 91 92 Java_SystemMessageHandler_removeTimer(env, 93 system_message_handler_obj_.obj()); 94 system_message_handler_obj_.Reset(); 95 } 96 97 if (run_loop_) { 98 run_loop_->AfterRun(); 99 delete run_loop_; 100 run_loop_ = NULL; 101 } 102 } 103 104 void MessagePumpForUI::ScheduleWork() { 105 DCHECK(!system_message_handler_obj_.is_null()); 106 107 JNIEnv* env = base::android::AttachCurrentThread(); 108 DCHECK(env); 109 110 Java_SystemMessageHandler_setTimer(env, 111 system_message_handler_obj_.obj()); 112 } 113 114 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 115 DCHECK(!system_message_handler_obj_.is_null()); 116 117 JNIEnv* env = base::android::AttachCurrentThread(); 118 DCHECK(env); 119 120 jlong millis = 121 (delayed_work_time - TimeTicks::Now()).InMillisecondsRoundedUp(); 122 // Note that we're truncating to milliseconds as required by the java side, 123 // even though delayed_work_time is microseconds resolution. 124 Java_SystemMessageHandler_setDelayedTimer(env, 125 system_message_handler_obj_.obj(), millis); 126 } 127 128 // static 129 bool MessagePumpForUI::RegisterBindings(JNIEnv* env) { 130 return RegisterNativesImpl(env); 131 } 132 133 } // namespace base 134