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, jlong 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( 85 env, reinterpret_cast<intptr_t>(delegate))); 86 } 87 88 void MessagePumpForUI::Quit() { 89 if (!system_message_handler_obj_.is_null()) { 90 JNIEnv* env = base::android::AttachCurrentThread(); 91 DCHECK(env); 92 93 Java_SystemMessageHandler_removeTimer(env, 94 system_message_handler_obj_.obj()); 95 system_message_handler_obj_.Reset(); 96 } 97 98 if (run_loop_) { 99 run_loop_->AfterRun(); 100 delete run_loop_; 101 run_loop_ = NULL; 102 } 103 } 104 105 void MessagePumpForUI::ScheduleWork() { 106 DCHECK(!system_message_handler_obj_.is_null()); 107 108 JNIEnv* env = base::android::AttachCurrentThread(); 109 DCHECK(env); 110 111 Java_SystemMessageHandler_setTimer(env, 112 system_message_handler_obj_.obj()); 113 } 114 115 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 116 DCHECK(!system_message_handler_obj_.is_null()); 117 118 JNIEnv* env = base::android::AttachCurrentThread(); 119 DCHECK(env); 120 121 jlong millis = 122 (delayed_work_time - TimeTicks::Now()).InMillisecondsRoundedUp(); 123 // Note that we're truncating to milliseconds as required by the java side, 124 // even though delayed_work_time is microseconds resolution. 125 Java_SystemMessageHandler_setDelayedTimer(env, 126 system_message_handler_obj_.obj(), millis); 127 } 128 129 // static 130 bool MessagePumpForUI::RegisterBindings(JNIEnv* env) { 131 return RegisterNativesImpl(env); 132 } 133 134 } // namespace base 135