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 |