| OLD | NEW |
| (Empty) |
| 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 <stdarg.h> | |
| 6 #include <string.h> | |
| 7 | |
| 8 #include "base/file_path.h" | |
| 9 #include "base/logging.h" | |
| 10 #include "base/memory/singleton.h" | |
| 11 #include "base/message_pump_android.h" | |
| 12 #include "base/path_service.h" | |
| 13 #include "base/synchronization/waitable_event.h" | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // The test implementation of AndroidOS stores everything in the following | |
| 18 // directory. | |
| 19 const char* kAndroidTestTempDirectory = "/data/local/tmp"; | |
| 20 | |
| 21 struct RunState { | |
| 22 RunState(base::MessagePump::Delegate* delegate, int run_depth) | |
| 23 : delegate(delegate), | |
| 24 run_depth(run_depth), | |
| 25 should_quit(false) { | |
| 26 } | |
| 27 | |
| 28 base::MessagePump::Delegate* delegate; | |
| 29 | |
| 30 // Used to count how many Run() invocations are on the stack. | |
| 31 int run_depth; | |
| 32 | |
| 33 // Used to flag that the current Run() invocation should return ASAP. | |
| 34 bool should_quit; | |
| 35 }; | |
| 36 | |
| 37 RunState* g_state = NULL; | |
| 38 | |
| 39 // A singleton WaitableEvent wrapper so we avoid a busy loop in | |
| 40 // MessagePumpForUIStub. Other platforms use the native event loop which blocks | |
| 41 // when there are no pending messages. | |
| 42 class Waitable { | |
| 43 public: | |
| 44 static Waitable* GetInstance() { | |
| 45 return Singleton<Waitable>::get(); | |
| 46 } | |
| 47 | |
| 48 // Signals that there are more work to do. | |
| 49 void Signal() { | |
| 50 waitable_event_.Signal(); | |
| 51 } | |
| 52 | |
| 53 // Blocks until more work is scheduled. | |
| 54 void Block() { | |
| 55 waitable_event_.Wait(); | |
| 56 } | |
| 57 | |
| 58 void Quit() { | |
| 59 g_state->should_quit = true; | |
| 60 Signal(); | |
| 61 } | |
| 62 | |
| 63 private: | |
| 64 friend struct DefaultSingletonTraits<Waitable>; | |
| 65 | |
| 66 Waitable() | |
| 67 : waitable_event_(false, false) { | |
| 68 } | |
| 69 | |
| 70 base::WaitableEvent waitable_event_; | |
| 71 }; | |
| 72 | |
| 73 // The MessagePumpForUI implementation for test purpose. | |
| 74 class MessagePumpForUIStub : public base::MessagePumpForUI { | |
| 75 void Start(base::MessagePump::Delegate* delegate) { | |
| 76 NOTREACHED() << "The Start() method shouldn't be called in test, using" | |
| 77 " Run() method should be used."; | |
| 78 } | |
| 79 | |
| 80 void Run(base::MessagePump::Delegate* delegate) { | |
| 81 // The following was based on message_pump_glib.cc, except we're using a | |
| 82 // WaitableEvent since there are no native message loop to use. | |
| 83 RunState state(delegate, g_state ? g_state->run_depth + 1 : 1); | |
| 84 | |
| 85 RunState* previous_state = g_state; | |
| 86 g_state = &state; | |
| 87 | |
| 88 bool more_work_is_plausible = true; | |
| 89 | |
| 90 for (;;) { | |
| 91 if (!more_work_is_plausible) { | |
| 92 Waitable::GetInstance()->Block(); | |
| 93 if (g_state->should_quit) | |
| 94 break; | |
| 95 } | |
| 96 | |
| 97 more_work_is_plausible = g_state->delegate->DoWork(); | |
| 98 if (g_state->should_quit) | |
| 99 break; | |
| 100 | |
| 101 base::TimeTicks delayed_work_time; | |
| 102 more_work_is_plausible |= | |
| 103 g_state->delegate->DoDelayedWork(&delayed_work_time); | |
| 104 if (g_state->should_quit) | |
| 105 break; | |
| 106 | |
| 107 if (more_work_is_plausible) | |
| 108 continue; | |
| 109 | |
| 110 more_work_is_plausible = g_state->delegate->DoIdleWork(); | |
| 111 if (g_state->should_quit) | |
| 112 break; | |
| 113 | |
| 114 more_work_is_plausible |= !delayed_work_time.is_null(); | |
| 115 } | |
| 116 | |
| 117 g_state = previous_state; | |
| 118 } | |
| 119 | |
| 120 void Quit() { | |
| 121 Waitable::GetInstance()->Quit(); | |
| 122 } | |
| 123 | |
| 124 void ScheduleWork() { | |
| 125 Waitable::GetInstance()->Signal(); | |
| 126 } | |
| 127 | |
| 128 void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) { | |
| 129 Waitable::GetInstance()->Signal(); | |
| 130 } | |
| 131 }; | |
| 132 | |
| 133 // Provides the test path for DIR_MODULE, DIR_CACHE and DIR_ANDROID_APP_DATA. | |
| 134 bool PathTestProviderAndroid(int key, FilePath* result) { | |
| 135 switch (key) { | |
| 136 case base::DIR_MODULE: { | |
| 137 *result = FilePath(kAndroidTestTempDirectory); | |
| 138 return true; | |
| 139 } | |
| 140 #if !defined(ANDROID_APK_TEST_TARGET) | |
| 141 // When running as executable we need to use /data/local/tmp as the | |
| 142 // cache directory. | |
| 143 case base::DIR_CACHE: { | |
| 144 *result = FilePath(kAndroidTestTempDirectory); | |
| 145 return true; | |
| 146 } | |
| 147 #endif // !defined(ANDROID_APK_TEST_TARGET) | |
| 148 case base::DIR_ANDROID_APP_DATA: { | |
| 149 *result = FilePath(kAndroidTestTempDirectory); | |
| 150 return true; | |
| 151 } | |
| 152 default: | |
| 153 return false; | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // The factory method to create a MessagePumpForUI. | |
| 158 base::MessagePump* CreateMessagePumpForUIStub() { | |
| 159 return new MessagePumpForUIStub(); | |
| 160 } | |
| 161 | |
| 162 } // namespace | |
| 163 | |
| 164 void InitAndroidOSPathStub() { | |
| 165 PathService::Override(base::DIR_MODULE, FilePath(kAndroidTestTempDirectory)); | |
| 166 PathService::Override(base::DIR_CACHE, FilePath(kAndroidTestTempDirectory)); | |
| 167 PathService::Override(base::DIR_ANDROID_APP_DATA, | |
| 168 FilePath(kAndroidTestTempDirectory)); | |
| 169 } | |
| 170 | |
| 171 void InitAndroidTestStub() { | |
| 172 logging::InitLogging(NULL, | |
| 173 logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, | |
| 174 logging::DONT_LOCK_LOG_FILE, | |
| 175 logging::DELETE_OLD_LOG_FILE, | |
| 176 logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); | |
| 177 // To view log output with IDs and timestamps use "adb logcat -v threadtime". | |
| 178 logging::SetLogItems(false, // Process ID | |
| 179 false, // Thread ID | |
| 180 false, // Timestamp | |
| 181 false); // Tick count | |
| 182 | |
| 183 PathService::RegisterProvider(&PathTestProviderAndroid, base::DIR_MODULE, | |
| 184 base::DIR_MODULE + 1); | |
| 185 PathService::RegisterProvider(&PathTestProviderAndroid, base::DIR_CACHE, | |
| 186 base::DIR_CACHE + 1); | |
| 187 PathService::RegisterProvider(&PathTestProviderAndroid, | |
| 188 base::DIR_ANDROID_APP_DATA, base::DIR_ANDROID_APP_DATA + 1); | |
| 189 | |
| 190 MessageLoop::InitMessagePumpForUIFactory(&CreateMessagePumpForUIStub); | |
| 191 } | |
| OLD | NEW |