Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / android / java_handler_thread.cc
1 // Copyright 2013 The Chromium Authors
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/android/java_handler_thread.h"
6
7 #include <jni.h>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/base_jni/JavaHandlerThread_jni.h"
12 #include "base/functional/bind.h"
13 #include "base/message_loop/message_pump.h"
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/run_loop.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/task/sequence_manager/sequence_manager_impl.h"
18 #include "base/threading/platform_thread_internal_posix.h"
19 #include "base/threading/thread_id_name_manager.h"
20 #include "base/threading/thread_restrictions.h"
21
22 using base::android::AttachCurrentThread;
23
24 namespace base {
25
26 namespace android {
27
28 JavaHandlerThread::JavaHandlerThread(const char* name,
29                                      base::ThreadType thread_type)
30     : JavaHandlerThread(
31           name,
32           Java_JavaHandlerThread_create(
33               AttachCurrentThread(),
34               ConvertUTF8ToJavaString(AttachCurrentThread(), name),
35               base::internal::ThreadTypeToNiceValue(thread_type))) {}
36
37 JavaHandlerThread::JavaHandlerThread(
38     const char* name,
39     const base::android::ScopedJavaLocalRef<jobject>& obj)
40     : name_(name), java_thread_(obj) {}
41
42 JavaHandlerThread::~JavaHandlerThread() {
43   JNIEnv* env = base::android::AttachCurrentThread();
44   DCHECK(!Java_JavaHandlerThread_isAlive(env, java_thread_));
45   DCHECK(!state_ || state_->pump->IsAborted());
46   // TODO(mthiesse): We shouldn't leak the MessageLoop as this could affect
47   // future tests.
48   if (state_ && state_->pump->IsAborted()) {
49     // When the Pump has been aborted due to a crash, we intentionally leak the
50     // SequenceManager because the SequenceManager hasn't been shut down
51     // properly and would trigger DCHECKS. This should only happen in tests,
52     // where we handle the exception instead of letting it take down the
53     // process.
54     state_.release();
55   }
56 }
57
58 void JavaHandlerThread::Start() {
59   // Check the thread has not already been started.
60   DCHECK(!state_);
61
62   JNIEnv* env = base::android::AttachCurrentThread();
63   base::WaitableEvent initialize_event(
64       WaitableEvent::ResetPolicy::AUTOMATIC,
65       WaitableEvent::InitialState::NOT_SIGNALED);
66   Java_JavaHandlerThread_startAndInitialize(
67       env, java_thread_, reinterpret_cast<intptr_t>(this),
68       reinterpret_cast<intptr_t>(&initialize_event));
69   // Wait for thread to be initialized so it is ready to be used when Start
70   // returns.
71   base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait_allowed;
72   initialize_event.Wait();
73 }
74
75 void JavaHandlerThread::Stop() {
76   DCHECK(!task_runner()->BelongsToCurrentThread());
77   task_runner()->PostTask(
78       FROM_HERE,
79       base::BindOnce(&JavaHandlerThread::StopOnThread, base::Unretained(this)));
80   JNIEnv* env = base::android::AttachCurrentThread();
81   Java_JavaHandlerThread_joinThread(env, java_thread_);
82 }
83
84 void JavaHandlerThread::InitializeThread(JNIEnv* env,
85                                          jlong event) {
86   base::ThreadIdNameManager::GetInstance()->RegisterThread(
87       base::PlatformThread::CurrentHandle().platform_handle(),
88       base::PlatformThread::CurrentId());
89
90   if (name_)
91     PlatformThread::SetName(name_);
92
93   thread_id_ = base::PlatformThread::CurrentId();
94   state_ = std::make_unique<State>();
95 #if DCHECK_IS_ON()
96   initialized_ = true;
97 #endif
98   Init();
99   reinterpret_cast<base::WaitableEvent*>(event)->Signal();
100 }
101
102 void JavaHandlerThread::OnLooperStopped(JNIEnv* env) {
103   DCHECK(task_runner()->BelongsToCurrentThread());
104   state_.reset();
105
106   CleanUp();
107
108   base::ThreadIdNameManager::GetInstance()->RemoveName(
109       base::PlatformThread::CurrentHandle().platform_handle(),
110       base::PlatformThread::CurrentId());
111 }
112
113 void JavaHandlerThread::StopSequenceManagerForTesting() {
114   DCHECK(task_runner()->BelongsToCurrentThread());
115   StopOnThread();
116 }
117
118 void JavaHandlerThread::JoinForTesting() {
119   DCHECK(!task_runner()->BelongsToCurrentThread());
120   JNIEnv* env = base::android::AttachCurrentThread();
121   Java_JavaHandlerThread_joinThread(env, java_thread_);
122 }
123
124 void JavaHandlerThread::ListenForUncaughtExceptionsForTesting() {
125   DCHECK(!task_runner()->BelongsToCurrentThread());
126   JNIEnv* env = base::android::AttachCurrentThread();
127   Java_JavaHandlerThread_listenForUncaughtExceptionsForTesting(env,
128                                                                java_thread_);
129 }
130
131 ScopedJavaLocalRef<jthrowable> JavaHandlerThread::GetUncaughtExceptionIfAny() {
132   DCHECK(!task_runner()->BelongsToCurrentThread());
133   JNIEnv* env = base::android::AttachCurrentThread();
134   return Java_JavaHandlerThread_getUncaughtExceptionIfAny(env, java_thread_);
135 }
136
137 PlatformThreadId JavaHandlerThread::GetThreadId() const {
138 #if DCHECK_IS_ON()
139   DCHECK(initialized_);
140 #endif
141   return thread_id_;
142 }
143
144 void JavaHandlerThread::StopOnThread() {
145   DCHECK(task_runner()->BelongsToCurrentThread());
146   DCHECK(state_);
147   state_->pump->QuitWhenIdle(base::BindOnce(
148       &JavaHandlerThread::QuitThreadSafely, base::Unretained(this)));
149 }
150
151 void JavaHandlerThread::QuitThreadSafely() {
152   DCHECK(task_runner()->BelongsToCurrentThread());
153   JNIEnv* env = base::android::AttachCurrentThread();
154   Java_JavaHandlerThread_quitThreadSafely(env, java_thread_,
155                                           reinterpret_cast<intptr_t>(this));
156 }
157
158 JavaHandlerThread::State::State()
159     : sequence_manager(sequence_manager::CreateUnboundSequenceManager(
160           sequence_manager::SequenceManager::Settings::Builder()
161               .SetMessagePumpType(base::MessagePumpType::JAVA)
162               .Build())),
163       default_task_queue(
164           sequence_manager->CreateTaskQueue(sequence_manager::TaskQueue::Spec(
165               sequence_manager::QueueName::DEFAULT_TQ))) {
166   // TYPE_JAVA to get the Android java style message loop.
167   std::unique_ptr<MessagePump> message_pump =
168       MessagePump::Create(base::MessagePumpType::JAVA);
169   pump = static_cast<MessagePumpForUI*>(message_pump.get());
170
171   // We must set SetTaskRunner before binding because the Android UI pump
172   // creates a RunLoop which samples SingleThreadTaskRunner::GetCurrentDefault.
173   static_cast<sequence_manager::internal::SequenceManagerImpl*>(
174       sequence_manager.get())
175       ->SetTaskRunner(default_task_queue->task_runner());
176   sequence_manager->BindToMessagePump(std::move(message_pump));
177 }
178
179 JavaHandlerThread::State::~State() = default;
180
181 } // namespace android
182 } // namespace base