| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 }; | 34 }; |
| 35 | 35 |
| 36 // Android's FindClass() is trickier than usual because the app-specific | 36 // Android's FindClass() is trickier than usual because the app-specific |
| 37 // ClassLoader is not consulted when there is no app-specific frame on the | 37 // ClassLoader is not consulted when there is no app-specific frame on the |
| 38 // stack. Consequently, we only look up all classes once in native WebRTC. | 38 // stack. Consequently, we only look up all classes once in native WebRTC. |
| 39 // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass | 39 // http://developer.android.com/training/articles/perf-jni.html#faq_FindClass |
| 40 void LoadClasses(JNIEnv* jni) { | 40 void LoadClasses(JNIEnv* jni) { |
| 41 for (auto& c : loaded_classes) { | 41 for (auto& c : loaded_classes) { |
| 42 jclass localRef = FindClass(jni, c.name); | 42 jclass localRef = FindClass(jni, c.name); |
| 43 CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name; | 43 CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name; |
| 44 CHECK(localRef) << c.name; | 44 RTC_CHECK(localRef) << c.name; |
| 45 jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef)); | 45 jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef)); |
| 46 CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name; | 46 CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name; |
| 47 CHECK(globalRef) << c.name; | 47 RTC_CHECK(globalRef) << c.name; |
| 48 c.clazz = globalRef; | 48 c.clazz = globalRef; |
| 49 } | 49 } |
| 50 } | 50 } |
| 51 | 51 |
| 52 void FreeClassReferences(JNIEnv* jni) { | 52 void FreeClassReferences(JNIEnv* jni) { |
| 53 for (auto& c : loaded_classes) { | 53 for (auto& c : loaded_classes) { |
| 54 jni->DeleteGlobalRef(c.clazz); | 54 jni->DeleteGlobalRef(c.clazz); |
| 55 c.clazz = nullptr; | 55 c.clazz = nullptr; |
| 56 } | 56 } |
| 57 } | 57 } |
| 58 | 58 |
| 59 jclass LookUpClass(const char* name) { | 59 jclass LookUpClass(const char* name) { |
| 60 for (auto& c : loaded_classes) { | 60 for (auto& c : loaded_classes) { |
| 61 if (strcmp(c.name, name) == 0) | 61 if (strcmp(c.name, name) == 0) |
| 62 return c.clazz; | 62 return c.clazz; |
| 63 } | 63 } |
| 64 CHECK(false) << "Unable to find class in lookup table"; | 64 RTC_CHECK(false) << "Unable to find class in lookup table"; |
| 65 return 0; | 65 return 0; |
| 66 } | 66 } |
| 67 | 67 |
| 68 // AttachCurrentThreadIfNeeded implementation. | 68 // AttachCurrentThreadIfNeeded implementation. |
| 69 AttachCurrentThreadIfNeeded::AttachCurrentThreadIfNeeded() | 69 AttachCurrentThreadIfNeeded::AttachCurrentThreadIfNeeded() |
| 70 : attached_(false) { | 70 : attached_(false) { |
| 71 ALOGD("AttachCurrentThreadIfNeeded::ctor%s", GetThreadInfo().c_str()); | 71 ALOGD("AttachCurrentThreadIfNeeded::ctor%s", GetThreadInfo().c_str()); |
| 72 JavaVM* jvm = JVM::GetInstance()->jvm(); | 72 JavaVM* jvm = JVM::GetInstance()->jvm(); |
| 73 CHECK(jvm); | 73 RTC_CHECK(jvm); |
| 74 JNIEnv* jni = GetEnv(jvm); | 74 JNIEnv* jni = GetEnv(jvm); |
| 75 if (!jni) { | 75 if (!jni) { |
| 76 ALOGD("Attaching thread to JVM"); | 76 ALOGD("Attaching thread to JVM"); |
| 77 JNIEnv* env = nullptr; | 77 JNIEnv* env = nullptr; |
| 78 jint ret = jvm->AttachCurrentThread(&env, nullptr); | 78 jint ret = jvm->AttachCurrentThread(&env, nullptr); |
| 79 attached_ = (ret == JNI_OK); | 79 attached_ = (ret == JNI_OK); |
| 80 } | 80 } |
| 81 } | 81 } |
| 82 | 82 |
| 83 AttachCurrentThreadIfNeeded::~AttachCurrentThreadIfNeeded() { | 83 AttachCurrentThreadIfNeeded::~AttachCurrentThreadIfNeeded() { |
| 84 ALOGD("AttachCurrentThreadIfNeeded::dtor%s", GetThreadInfo().c_str()); | 84 ALOGD("AttachCurrentThreadIfNeeded::dtor%s", GetThreadInfo().c_str()); |
| 85 DCHECK(thread_checker_.CalledOnValidThread()); | 85 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 86 if (attached_) { | 86 if (attached_) { |
| 87 ALOGD("Detaching thread from JVM"); | 87 ALOGD("Detaching thread from JVM"); |
| 88 jint res = JVM::GetInstance()->jvm()->DetachCurrentThread(); | 88 jint res = JVM::GetInstance()->jvm()->DetachCurrentThread(); |
| 89 CHECK(res == JNI_OK) << "DetachCurrentThread failed: " << res; | 89 RTC_CHECK(res == JNI_OK) << "DetachCurrentThread failed: " << res; |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 // GlobalRef implementation. | 93 // GlobalRef implementation. |
| 94 GlobalRef::GlobalRef(JNIEnv* jni, jobject object) | 94 GlobalRef::GlobalRef(JNIEnv* jni, jobject object) |
| 95 : jni_(jni), j_object_(NewGlobalRef(jni, object)) { | 95 : jni_(jni), j_object_(NewGlobalRef(jni, object)) { |
| 96 ALOGD("GlobalRef::ctor%s", GetThreadInfo().c_str()); | 96 ALOGD("GlobalRef::ctor%s", GetThreadInfo().c_str()); |
| 97 } | 97 } |
| 98 | 98 |
| 99 GlobalRef::~GlobalRef() { | 99 GlobalRef::~GlobalRef() { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 return res; | 171 return res; |
| 172 } | 172 } |
| 173 | 173 |
| 174 // JNIEnvironment implementation. | 174 // JNIEnvironment implementation. |
| 175 JNIEnvironment::JNIEnvironment(JNIEnv* jni) : jni_(jni) { | 175 JNIEnvironment::JNIEnvironment(JNIEnv* jni) : jni_(jni) { |
| 176 ALOGD("JNIEnvironment::ctor%s", GetThreadInfo().c_str()); | 176 ALOGD("JNIEnvironment::ctor%s", GetThreadInfo().c_str()); |
| 177 } | 177 } |
| 178 | 178 |
| 179 JNIEnvironment::~JNIEnvironment() { | 179 JNIEnvironment::~JNIEnvironment() { |
| 180 ALOGD("JNIEnvironment::dtor%s", GetThreadInfo().c_str()); | 180 ALOGD("JNIEnvironment::dtor%s", GetThreadInfo().c_str()); |
| 181 DCHECK(thread_checker_.CalledOnValidThread()); | 181 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 182 } | 182 } |
| 183 | 183 |
| 184 rtc::scoped_ptr<NativeRegistration> JNIEnvironment::RegisterNatives( | 184 rtc::scoped_ptr<NativeRegistration> JNIEnvironment::RegisterNatives( |
| 185 const char* name, const JNINativeMethod *methods, int num_methods) { | 185 const char* name, const JNINativeMethod *methods, int num_methods) { |
| 186 ALOGD("JNIEnvironment::RegisterNatives(%s)", name); | 186 ALOGD("JNIEnvironment::RegisterNatives(%s)", name); |
| 187 DCHECK(thread_checker_.CalledOnValidThread()); | 187 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 188 jclass clazz = LookUpClass(name); | 188 jclass clazz = LookUpClass(name); |
| 189 jni_->RegisterNatives(clazz, methods, num_methods); | 189 jni_->RegisterNatives(clazz, methods, num_methods); |
| 190 CHECK_EXCEPTION(jni_) << "Error during RegisterNatives"; | 190 CHECK_EXCEPTION(jni_) << "Error during RegisterNatives"; |
| 191 return rtc::scoped_ptr<NativeRegistration>( | 191 return rtc::scoped_ptr<NativeRegistration>( |
| 192 new NativeRegistration(jni_, clazz)); | 192 new NativeRegistration(jni_, clazz)); |
| 193 } | 193 } |
| 194 | 194 |
| 195 std::string JNIEnvironment::JavaToStdString(const jstring& j_string) { | 195 std::string JNIEnvironment::JavaToStdString(const jstring& j_string) { |
| 196 DCHECK(thread_checker_.CalledOnValidThread()); | 196 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 197 const char* jchars = jni_->GetStringUTFChars(j_string, nullptr); | 197 const char* jchars = jni_->GetStringUTFChars(j_string, nullptr); |
| 198 CHECK_EXCEPTION(jni_); | 198 CHECK_EXCEPTION(jni_); |
| 199 const int size = jni_->GetStringUTFLength(j_string); | 199 const int size = jni_->GetStringUTFLength(j_string); |
| 200 CHECK_EXCEPTION(jni_); | 200 CHECK_EXCEPTION(jni_); |
| 201 std::string ret(jchars, size); | 201 std::string ret(jchars, size); |
| 202 jni_->ReleaseStringUTFChars(j_string, jchars); | 202 jni_->ReleaseStringUTFChars(j_string, jchars); |
| 203 CHECK_EXCEPTION(jni_); | 203 CHECK_EXCEPTION(jni_); |
| 204 return ret; | 204 return ret; |
| 205 } | 205 } |
| 206 | 206 |
| 207 // static | 207 // static |
| 208 void JVM::Initialize(JavaVM* jvm, jobject context) { | 208 void JVM::Initialize(JavaVM* jvm, jobject context) { |
| 209 ALOGD("JVM::Initialize%s", GetThreadInfo().c_str()); | 209 ALOGD("JVM::Initialize%s", GetThreadInfo().c_str()); |
| 210 CHECK(!g_jvm); | 210 RTC_CHECK(!g_jvm); |
| 211 g_jvm = new JVM(jvm, context); | 211 g_jvm = new JVM(jvm, context); |
| 212 } | 212 } |
| 213 | 213 |
| 214 // static | 214 // static |
| 215 void JVM::Uninitialize() { | 215 void JVM::Uninitialize() { |
| 216 ALOGD("JVM::Uninitialize%s", GetThreadInfo().c_str()); | 216 ALOGD("JVM::Uninitialize%s", GetThreadInfo().c_str()); |
| 217 DCHECK(g_jvm); | 217 RTC_DCHECK(g_jvm); |
| 218 delete g_jvm; | 218 delete g_jvm; |
| 219 g_jvm = nullptr; | 219 g_jvm = nullptr; |
| 220 } | 220 } |
| 221 | 221 |
| 222 // static | 222 // static |
| 223 JVM* JVM::GetInstance() { | 223 JVM* JVM::GetInstance() { |
| 224 DCHECK(g_jvm); | 224 RTC_DCHECK(g_jvm); |
| 225 return g_jvm; | 225 return g_jvm; |
| 226 } | 226 } |
| 227 | 227 |
| 228 JVM::JVM(JavaVM* jvm, jobject context) | 228 JVM::JVM(JavaVM* jvm, jobject context) |
| 229 : jvm_(jvm) { | 229 : jvm_(jvm) { |
| 230 ALOGD("JVM::JVM%s", GetThreadInfo().c_str()); | 230 ALOGD("JVM::JVM%s", GetThreadInfo().c_str()); |
| 231 CHECK(jni()) << "AttachCurrentThread() must be called on this thread."; | 231 RTC_CHECK(jni()) << "AttachCurrentThread() must be called on this thread."; |
| 232 context_ = NewGlobalRef(jni(), context); | 232 context_ = NewGlobalRef(jni(), context); |
| 233 LoadClasses(jni()); | 233 LoadClasses(jni()); |
| 234 } | 234 } |
| 235 | 235 |
| 236 JVM::~JVM() { | 236 JVM::~JVM() { |
| 237 ALOGD("JVM::~JVM%s", GetThreadInfo().c_str()); | 237 ALOGD("JVM::~JVM%s", GetThreadInfo().c_str()); |
| 238 DCHECK(thread_checker_.CalledOnValidThread()); | 238 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 239 FreeClassReferences(jni()); | 239 FreeClassReferences(jni()); |
| 240 DeleteGlobalRef(jni(), context_); | 240 DeleteGlobalRef(jni(), context_); |
| 241 } | 241 } |
| 242 | 242 |
| 243 rtc::scoped_ptr<JNIEnvironment> JVM::environment() { | 243 rtc::scoped_ptr<JNIEnvironment> JVM::environment() { |
| 244 ALOGD("JVM::environment%s", GetThreadInfo().c_str()); | 244 ALOGD("JVM::environment%s", GetThreadInfo().c_str()); |
| 245 // The JNIEnv is used for thread-local storage. For this reason, we cannot | 245 // The JNIEnv is used for thread-local storage. For this reason, we cannot |
| 246 // share a JNIEnv between threads. If a piece of code has no other way to get | 246 // share a JNIEnv between threads. If a piece of code has no other way to get |
| 247 // its JNIEnv, we should share the JavaVM, and use GetEnv to discover the | 247 // its JNIEnv, we should share the JavaVM, and use GetEnv to discover the |
| 248 // thread's JNIEnv. (Assuming it has one, if not, use AttachCurrentThread). | 248 // thread's JNIEnv. (Assuming it has one, if not, use AttachCurrentThread). |
| 249 // See // http://developer.android.com/training/articles/perf-jni.html. | 249 // See // http://developer.android.com/training/articles/perf-jni.html. |
| 250 JNIEnv* jni = GetEnv(jvm_); | 250 JNIEnv* jni = GetEnv(jvm_); |
| 251 if (!jni) { | 251 if (!jni) { |
| 252 ALOGE("AttachCurrentThread() has not been called on this thread."); | 252 ALOGE("AttachCurrentThread() has not been called on this thread."); |
| 253 return rtc::scoped_ptr<JNIEnvironment>(); | 253 return rtc::scoped_ptr<JNIEnvironment>(); |
| 254 } | 254 } |
| 255 return rtc::scoped_ptr<JNIEnvironment>(new JNIEnvironment(jni)); | 255 return rtc::scoped_ptr<JNIEnvironment>(new JNIEnvironment(jni)); |
| 256 } | 256 } |
| 257 | 257 |
| 258 JavaClass JVM::GetClass(const char* name) { | 258 JavaClass JVM::GetClass(const char* name) { |
| 259 ALOGD("JVM::GetClass(%s)%s", name, GetThreadInfo().c_str()); | 259 ALOGD("JVM::GetClass(%s)%s", name, GetThreadInfo().c_str()); |
| 260 DCHECK(thread_checker_.CalledOnValidThread()); | 260 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 261 return JavaClass(jni(), LookUpClass(name)); | 261 return JavaClass(jni(), LookUpClass(name)); |
| 262 } | 262 } |
| 263 | 263 |
| 264 } // namespace webrtc | 264 } // namespace webrtc |
| OLD | NEW |