| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * libjingle | 3 * libjingle |
| 4 * Copyright 2015 Google Inc. | 4 * Copyright 2015 Google Inc. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions are met: | 7 * modification, are permitted provided that the following conditions are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright notice, | 9 * 1. Redistributions of source code must retain the above copyright notice, |
| 10 * this list of conditions and the following disclaimer. | 10 * this list of conditions and the following disclaimer. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT; | 42 static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT; |
| 43 | 43 |
| 44 // Key for per-thread JNIEnv* data. Non-NULL in threads attached to |g_jvm| by | 44 // Key for per-thread JNIEnv* data. Non-NULL in threads attached to |g_jvm| by |
| 45 // AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that | 45 // AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that |
| 46 // were attached by the JVM because of a Java->native call. | 46 // were attached by the JVM because of a Java->native call. |
| 47 static pthread_key_t g_jni_ptr; | 47 static pthread_key_t g_jni_ptr; |
| 48 | 48 |
| 49 using icu::UnicodeString; | 49 using icu::UnicodeString; |
| 50 | 50 |
| 51 JavaVM *GetJVM() { | 51 JavaVM *GetJVM() { |
| 52 CHECK(g_jvm) << "JNI_OnLoad failed to run?"; | 52 RTC_CHECK(g_jvm) << "JNI_OnLoad failed to run?"; |
| 53 return g_jvm; | 53 return g_jvm; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Return a |JNIEnv*| usable on this thread or NULL if this thread is detached. | 56 // Return a |JNIEnv*| usable on this thread or NULL if this thread is detached. |
| 57 JNIEnv* GetEnv() { | 57 JNIEnv* GetEnv() { |
| 58 void* env = NULL; | 58 void* env = NULL; |
| 59 jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6); | 59 jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6); |
| 60 CHECK(((env != NULL) && (status == JNI_OK)) || | 60 RTC_CHECK(((env != NULL) && (status == JNI_OK)) || |
| 61 ((env == NULL) && (status == JNI_EDETACHED))) | 61 ((env == NULL) && (status == JNI_EDETACHED))) |
| 62 << "Unexpected GetEnv return: " << status << ":" << env; | 62 << "Unexpected GetEnv return: " << status << ":" << env; |
| 63 return reinterpret_cast<JNIEnv*>(env); | 63 return reinterpret_cast<JNIEnv*>(env); |
| 64 } | 64 } |
| 65 | 65 |
| 66 static void ThreadDestructor(void* prev_jni_ptr) { | 66 static void ThreadDestructor(void* prev_jni_ptr) { |
| 67 // This function only runs on threads where |g_jni_ptr| is non-NULL, meaning | 67 // This function only runs on threads where |g_jni_ptr| is non-NULL, meaning |
| 68 // we were responsible for originally attaching the thread, so are responsible | 68 // we were responsible for originally attaching the thread, so are responsible |
| 69 // for detaching it now. However, because some JVM implementations (notably | 69 // for detaching it now. However, because some JVM implementations (notably |
| 70 // Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism, | 70 // Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism, |
| 71 // the JVMs accounting info for this thread may already be wiped out by the | 71 // the JVMs accounting info for this thread may already be wiped out by the |
| 72 // time this is called. Thus it may appear we are already detached even though | 72 // time this is called. Thus it may appear we are already detached even though |
| 73 // it was our responsibility to detach! Oh well. | 73 // it was our responsibility to detach! Oh well. |
| 74 if (!GetEnv()) | 74 if (!GetEnv()) |
| 75 return; | 75 return; |
| 76 | 76 |
| 77 CHECK(GetEnv() == prev_jni_ptr) | 77 RTC_CHECK(GetEnv() == prev_jni_ptr) |
| 78 << "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv(); | 78 << "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv(); |
| 79 jint status = g_jvm->DetachCurrentThread(); | 79 jint status = g_jvm->DetachCurrentThread(); |
| 80 CHECK(status == JNI_OK) << "Failed to detach thread: " << status; | 80 RTC_CHECK(status == JNI_OK) << "Failed to detach thread: " << status; |
| 81 CHECK(!GetEnv()) << "Detaching was a successful no-op???"; | 81 RTC_CHECK(!GetEnv()) << "Detaching was a successful no-op???"; |
| 82 } | 82 } |
| 83 | 83 |
| 84 static void CreateJNIPtrKey() { | 84 static void CreateJNIPtrKey() { |
| 85 CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor)) | 85 RTC_CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor)) |
| 86 << "pthread_key_create"; | 86 << "pthread_key_create"; |
| 87 } | 87 } |
| 88 | 88 |
| 89 jint InitGlobalJniVariables(JavaVM *jvm) { | 89 jint InitGlobalJniVariables(JavaVM *jvm) { |
| 90 CHECK(!g_jvm) << "InitGlobalJniVariables!"; | 90 RTC_CHECK(!g_jvm) << "InitGlobalJniVariables!"; |
| 91 g_jvm = jvm; | 91 g_jvm = jvm; |
| 92 CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?"; | 92 RTC_CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?"; |
| 93 | 93 |
| 94 CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once"; | 94 RTC_CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once"; |
| 95 | 95 |
| 96 JNIEnv* jni = nullptr; | 96 JNIEnv* jni = nullptr; |
| 97 if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK) | 97 if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK) |
| 98 return -1; | 98 return -1; |
| 99 | 99 |
| 100 return JNI_VERSION_1_6; | 100 return JNI_VERSION_1_6; |
| 101 } | 101 } |
| 102 | 102 |
| 103 // Return thread ID as a string. | 103 // Return thread ID as a string. |
| 104 static std::string GetThreadId() { | 104 static std::string GetThreadId() { |
| 105 char buf[21]; // Big enough to hold a kuint64max plus terminating NULL. | 105 char buf[21]; // Big enough to hold a kuint64max plus terminating NULL. |
| 106 CHECK_LT(snprintf(buf, sizeof(buf), "%ld", | 106 RTC_CHECK_LT(snprintf(buf, sizeof(buf), "%ld", |
| 107 static_cast<long>(syscall(__NR_gettid))), | 107 static_cast<long>(syscall(__NR_gettid))), |
| 108 sizeof(buf)) | 108 sizeof(buf)) |
| 109 << "Thread id is bigger than uint64??"; | 109 << "Thread id is bigger than uint64??"; |
| 110 return std::string(buf); | 110 return std::string(buf); |
| 111 } | 111 } |
| 112 | 112 |
| 113 // Return the current thread's name. | 113 // Return the current thread's name. |
| 114 static std::string GetThreadName() { | 114 static std::string GetThreadName() { |
| 115 char name[17] = {0}; | 115 char name[17] = {0}; |
| 116 if (prctl(PR_GET_NAME, name) != 0) | 116 if (prctl(PR_GET_NAME, name) != 0) |
| 117 return std::string("<noname>"); | 117 return std::string("<noname>"); |
| 118 return std::string(name); | 118 return std::string(name); |
| 119 } | 119 } |
| 120 | 120 |
| 121 // Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary. | 121 // Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary. |
| 122 JNIEnv* AttachCurrentThreadIfNeeded() { | 122 JNIEnv* AttachCurrentThreadIfNeeded() { |
| 123 JNIEnv* jni = GetEnv(); | 123 JNIEnv* jni = GetEnv(); |
| 124 if (jni) | 124 if (jni) |
| 125 return jni; | 125 return jni; |
| 126 CHECK(!pthread_getspecific(g_jni_ptr)) | 126 RTC_CHECK(!pthread_getspecific(g_jni_ptr)) |
| 127 << "TLS has a JNIEnv* but not attached?"; | 127 << "TLS has a JNIEnv* but not attached?"; |
| 128 | 128 |
| 129 std::string name(GetThreadName() + " - " + GetThreadId()); | 129 std::string name(GetThreadName() + " - " + GetThreadId()); |
| 130 JavaVMAttachArgs args; | 130 JavaVMAttachArgs args; |
| 131 args.version = JNI_VERSION_1_6; | 131 args.version = JNI_VERSION_1_6; |
| 132 args.name = &name[0]; | 132 args.name = &name[0]; |
| 133 args.group = NULL; | 133 args.group = NULL; |
| 134 // Deal with difference in signatures between Oracle's jni.h and Android's. | 134 // Deal with difference in signatures between Oracle's jni.h and Android's. |
| 135 #ifdef _JAVASOFT_JNI_H_ // Oracle's jni.h violates the JNI spec! | 135 #ifdef _JAVASOFT_JNI_H_ // Oracle's jni.h violates the JNI spec! |
| 136 void* env = NULL; | 136 void* env = NULL; |
| 137 #else | 137 #else |
| 138 JNIEnv* env = NULL; | 138 JNIEnv* env = NULL; |
| 139 #endif | 139 #endif |
| 140 CHECK(!g_jvm->AttachCurrentThread(&env, &args)) << "Failed to attach thread"; | 140 RTC_CHECK(!g_jvm->AttachCurrentThread(&env, &args)) |
| 141 CHECK(env) << "AttachCurrentThread handed back NULL!"; | 141 << "Failed to attach thread"; |
| 142 RTC_CHECK(env) << "AttachCurrentThread handed back NULL!"; |
| 142 jni = reinterpret_cast<JNIEnv*>(env); | 143 jni = reinterpret_cast<JNIEnv*>(env); |
| 143 CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific"; | 144 RTC_CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific"; |
| 144 return jni; | 145 return jni; |
| 145 } | 146 } |
| 146 | 147 |
| 147 // Return a |jlong| that will correctly convert back to |ptr|. This is needed | 148 // Return a |jlong| that will correctly convert back to |ptr|. This is needed |
| 148 // because the alternative (of silently passing a 32-bit pointer to a vararg | 149 // because the alternative (of silently passing a 32-bit pointer to a vararg |
| 149 // function expecting a 64-bit param) picks up garbage in the high 32 bits. | 150 // function expecting a 64-bit param) picks up garbage in the high 32 bits. |
| 150 jlong jlongFromPointer(void* ptr) { | 151 jlong jlongFromPointer(void* ptr) { |
| 151 static_assert(sizeof(intptr_t) <= sizeof(jlong), | 152 static_assert(sizeof(intptr_t) <= sizeof(jlong), |
| 152 "Time to rethink the use of jlongs"); | 153 "Time to rethink the use of jlongs"); |
| 153 // Going through intptr_t to be obvious about the definedness of the | 154 // Going through intptr_t to be obvious about the definedness of the |
| 154 // conversion from pointer to integral type. intptr_t to jlong is a standard | 155 // conversion from pointer to integral type. intptr_t to jlong is a standard |
| 155 // widening by the static_assert above. | 156 // widening by the static_assert above. |
| 156 jlong ret = reinterpret_cast<intptr_t>(ptr); | 157 jlong ret = reinterpret_cast<intptr_t>(ptr); |
| 157 DCHECK(reinterpret_cast<void*>(ret) == ptr); | 158 RTC_DCHECK(reinterpret_cast<void*>(ret) == ptr); |
| 158 return ret; | 159 return ret; |
| 159 } | 160 } |
| 160 | 161 |
| 161 // JNIEnv-helper methods that CHECK success: no Java exception thrown and found | 162 // JNIEnv-helper methods that RTC_CHECK success: no Java exception thrown and |
| 162 // object/class/method/field is non-null. | 163 // found object/class/method/field is non-null. |
| 163 jmethodID GetMethodID( | 164 jmethodID GetMethodID( |
| 164 JNIEnv* jni, jclass c, const std::string& name, const char* signature) { | 165 JNIEnv* jni, jclass c, const std::string& name, const char* signature) { |
| 165 jmethodID m = jni->GetMethodID(c, name.c_str(), signature); | 166 jmethodID m = jni->GetMethodID(c, name.c_str(), signature); |
| 166 CHECK_EXCEPTION(jni) << "error during GetMethodID: " << name << ", " | 167 CHECK_EXCEPTION(jni) << "error during GetMethodID: " << name << ", " |
| 167 << signature; | 168 << signature; |
| 168 CHECK(m) << name << ", " << signature; | 169 RTC_CHECK(m) << name << ", " << signature; |
| 169 return m; | 170 return m; |
| 170 } | 171 } |
| 171 | 172 |
| 172 jmethodID GetStaticMethodID( | 173 jmethodID GetStaticMethodID( |
| 173 JNIEnv* jni, jclass c, const char* name, const char* signature) { | 174 JNIEnv* jni, jclass c, const char* name, const char* signature) { |
| 174 jmethodID m = jni->GetStaticMethodID(c, name, signature); | 175 jmethodID m = jni->GetStaticMethodID(c, name, signature); |
| 175 CHECK_EXCEPTION(jni) << "error during GetStaticMethodID: " << name << ", " | 176 CHECK_EXCEPTION(jni) << "error during GetStaticMethodID: " << name << ", " |
| 176 << signature; | 177 << signature; |
| 177 CHECK(m) << name << ", " << signature; | 178 RTC_CHECK(m) << name << ", " << signature; |
| 178 return m; | 179 return m; |
| 179 } | 180 } |
| 180 | 181 |
| 181 jfieldID GetFieldID( | 182 jfieldID GetFieldID( |
| 182 JNIEnv* jni, jclass c, const char* name, const char* signature) { | 183 JNIEnv* jni, jclass c, const char* name, const char* signature) { |
| 183 jfieldID f = jni->GetFieldID(c, name, signature); | 184 jfieldID f = jni->GetFieldID(c, name, signature); |
| 184 CHECK_EXCEPTION(jni) << "error during GetFieldID"; | 185 CHECK_EXCEPTION(jni) << "error during GetFieldID"; |
| 185 CHECK(f) << name << ", " << signature; | 186 RTC_CHECK(f) << name << ", " << signature; |
| 186 return f; | 187 return f; |
| 187 } | 188 } |
| 188 | 189 |
| 189 jclass GetObjectClass(JNIEnv* jni, jobject object) { | 190 jclass GetObjectClass(JNIEnv* jni, jobject object) { |
| 190 jclass c = jni->GetObjectClass(object); | 191 jclass c = jni->GetObjectClass(object); |
| 191 CHECK_EXCEPTION(jni) << "error during GetObjectClass"; | 192 CHECK_EXCEPTION(jni) << "error during GetObjectClass"; |
| 192 CHECK(c) << "GetObjectClass returned NULL"; | 193 RTC_CHECK(c) << "GetObjectClass returned NULL"; |
| 193 return c; | 194 return c; |
| 194 } | 195 } |
| 195 | 196 |
| 196 jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) { | 197 jobject GetObjectField(JNIEnv* jni, jobject object, jfieldID id) { |
| 197 jobject o = jni->GetObjectField(object, id); | 198 jobject o = jni->GetObjectField(object, id); |
| 198 CHECK_EXCEPTION(jni) << "error during GetObjectField"; | 199 CHECK_EXCEPTION(jni) << "error during GetObjectField"; |
| 199 CHECK(o) << "GetObjectField returned NULL"; | 200 RTC_CHECK(o) << "GetObjectField returned NULL"; |
| 200 return o; | 201 return o; |
| 201 } | 202 } |
| 202 | 203 |
| 203 jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) { | 204 jstring GetStringField(JNIEnv* jni, jobject object, jfieldID id) { |
| 204 return static_cast<jstring>(GetObjectField(jni, object, id)); | 205 return static_cast<jstring>(GetObjectField(jni, object, id)); |
| 205 } | 206 } |
| 206 | 207 |
| 207 jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) { | 208 jlong GetLongField(JNIEnv* jni, jobject object, jfieldID id) { |
| 208 jlong l = jni->GetLongField(object, id); | 209 jlong l = jni->GetLongField(object, id); |
| 209 CHECK_EXCEPTION(jni) << "error during GetLongField"; | 210 CHECK_EXCEPTION(jni) << "error during GetLongField"; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 jni->CallStaticObjectMethod(state_class, state_values_id)); | 259 jni->CallStaticObjectMethod(state_class, state_values_id)); |
| 259 CHECK_EXCEPTION(jni) << "error during CallStaticObjectMethod"; | 260 CHECK_EXCEPTION(jni) << "error during CallStaticObjectMethod"; |
| 260 jobject ret = jni->GetObjectArrayElement(state_values, index); | 261 jobject ret = jni->GetObjectArrayElement(state_values, index); |
| 261 CHECK_EXCEPTION(jni) << "error during GetObjectArrayElement"; | 262 CHECK_EXCEPTION(jni) << "error during GetObjectArrayElement"; |
| 262 return ret; | 263 return ret; |
| 263 } | 264 } |
| 264 | 265 |
| 265 jobject NewGlobalRef(JNIEnv* jni, jobject o) { | 266 jobject NewGlobalRef(JNIEnv* jni, jobject o) { |
| 266 jobject ret = jni->NewGlobalRef(o); | 267 jobject ret = jni->NewGlobalRef(o); |
| 267 CHECK_EXCEPTION(jni) << "error during NewGlobalRef"; | 268 CHECK_EXCEPTION(jni) << "error during NewGlobalRef"; |
| 268 CHECK(ret); | 269 RTC_CHECK(ret); |
| 269 return ret; | 270 return ret; |
| 270 } | 271 } |
| 271 | 272 |
| 272 void DeleteGlobalRef(JNIEnv* jni, jobject o) { | 273 void DeleteGlobalRef(JNIEnv* jni, jobject o) { |
| 273 jni->DeleteGlobalRef(o); | 274 jni->DeleteGlobalRef(o); |
| 274 CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef"; | 275 CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef"; |
| 275 } | 276 } |
| 276 | 277 |
| 277 // Scope Java local references to the lifetime of this object. Use in all C++ | 278 // Scope Java local references to the lifetime of this object. Use in all C++ |
| 278 // callbacks (i.e. entry points that don't originate in a Java callstack | 279 // callbacks (i.e. entry points that don't originate in a Java callstack |
| 279 // through a "native" method call). | 280 // through a "native" method call). |
| 280 ScopedLocalRefFrame::ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) { | 281 ScopedLocalRefFrame::ScopedLocalRefFrame(JNIEnv* jni) : jni_(jni) { |
| 281 CHECK(!jni_->PushLocalFrame(0)) << "Failed to PushLocalFrame"; | 282 RTC_CHECK(!jni_->PushLocalFrame(0)) << "Failed to PushLocalFrame"; |
| 282 } | 283 } |
| 283 ScopedLocalRefFrame::~ScopedLocalRefFrame() { | 284 ScopedLocalRefFrame::~ScopedLocalRefFrame() { |
| 284 jni_->PopLocalFrame(NULL); | 285 jni_->PopLocalFrame(NULL); |
| 285 } | 286 } |
| 286 | 287 |
| 287 } // namespace webrtc_jni | 288 } // namespace webrtc_jni |
| OLD | NEW |