| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |  | 
| 3  * |  | 
| 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 |  | 
| 6  *  tree. An additional intellectual property rights grant can be found |  | 
| 7  *  in the file PATENTS.  All contributing project authors may |  | 
| 8  *  be found in the AUTHORS file in the root of the source tree. |  | 
| 9  */ |  | 
| 10 |  | 
| 11 #include "webrtc/modules/audio_device/android/helpers_android.h" |  | 
| 12 |  | 
| 13 #include <android/log.h> |  | 
| 14 #include <assert.h> |  | 
| 15 #include <pthread.h> |  | 
| 16 #include <stddef.h> |  | 
| 17 #include <unistd.h> |  | 
| 18 |  | 
| 19 #define TAG "HelpersAndroid" |  | 
| 20 #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) |  | 
| 21 |  | 
| 22 namespace webrtc { |  | 
| 23 |  | 
| 24 JNIEnv* GetEnv(JavaVM* jvm) { |  | 
| 25   void* env = NULL; |  | 
| 26   jint status = jvm->GetEnv(&env, JNI_VERSION_1_6); |  | 
| 27   RTC_CHECK(((env != NULL) && (status == JNI_OK)) || |  | 
| 28             ((env == NULL) && (status == JNI_EDETACHED))) |  | 
| 29       << "Unexpected GetEnv return: " << status << ":" << env; |  | 
| 30   return reinterpret_cast<JNIEnv*>(env); |  | 
| 31 } |  | 
| 32 |  | 
| 33 // Return a |jlong| that will correctly convert back to |ptr|.  This is needed |  | 
| 34 // because the alternative (of silently passing a 32-bit pointer to a vararg |  | 
| 35 // function expecting a 64-bit param) picks up garbage in the high 32 bits. |  | 
| 36 jlong PointerTojlong(void* ptr) { |  | 
| 37   static_assert(sizeof(intptr_t) <= sizeof(jlong), |  | 
| 38                 "Time to rethink the use of jlongs"); |  | 
| 39   // Going through intptr_t to be obvious about the definedness of the |  | 
| 40   // conversion from pointer to integral type.  intptr_t to jlong is a standard |  | 
| 41   // widening by the static_assert above. |  | 
| 42   jlong ret = reinterpret_cast<intptr_t>(ptr); |  | 
| 43   RTC_DCHECK(reinterpret_cast<void*>(ret) == ptr); |  | 
| 44   return ret; |  | 
| 45 } |  | 
| 46 |  | 
| 47 jmethodID GetMethodID( |  | 
| 48     JNIEnv* jni, jclass c, const char* name, const char* signature) { |  | 
| 49   jmethodID m = jni->GetMethodID(c, name, signature); |  | 
| 50   CHECK_EXCEPTION(jni) << "Error during GetMethodID: " << name << ", " |  | 
| 51                        << signature; |  | 
| 52   RTC_CHECK(m) << name << ", " << signature; |  | 
| 53   return m; |  | 
| 54 } |  | 
| 55 |  | 
| 56 jmethodID GetStaticMethodID( |  | 
| 57     JNIEnv* jni, jclass c, const char* name, const char* signature) { |  | 
| 58   jmethodID m = jni->GetStaticMethodID(c, name, signature); |  | 
| 59   CHECK_EXCEPTION(jni) << "Error during GetStaticMethodID: " << name << ", " |  | 
| 60                        << signature; |  | 
| 61   RTC_CHECK(m) << name << ", " << signature; |  | 
| 62   return m; |  | 
| 63 } |  | 
| 64 |  | 
| 65 jclass FindClass(JNIEnv* jni, const char* name) { |  | 
| 66   jclass c = jni->FindClass(name); |  | 
| 67   CHECK_EXCEPTION(jni) << "Error during FindClass: " << name; |  | 
| 68   RTC_CHECK(c) << name; |  | 
| 69   return c; |  | 
| 70 } |  | 
| 71 |  | 
| 72 jobject NewGlobalRef(JNIEnv* jni, jobject o) { |  | 
| 73   jobject ret = jni->NewGlobalRef(o); |  | 
| 74   CHECK_EXCEPTION(jni) << "Error during NewGlobalRef"; |  | 
| 75   RTC_CHECK(ret); |  | 
| 76   return ret; |  | 
| 77 } |  | 
| 78 |  | 
| 79 void DeleteGlobalRef(JNIEnv* jni, jobject o) { |  | 
| 80   jni->DeleteGlobalRef(o); |  | 
| 81   CHECK_EXCEPTION(jni) << "Error during DeleteGlobalRef"; |  | 
| 82 } |  | 
| 83 |  | 
| 84 std::string GetThreadId() { |  | 
| 85   char buf[21];  // Big enough to hold a kuint64max plus terminating NULL. |  | 
| 86   int thread_id = gettid(); |  | 
| 87   RTC_CHECK_LT(snprintf(buf, sizeof(buf), "%i", thread_id), |  | 
| 88                static_cast<int>(sizeof(buf))) |  | 
| 89       << "Thread id is bigger than uint64??"; |  | 
| 90   return std::string(buf); |  | 
| 91 } |  | 
| 92 |  | 
| 93 std::string GetThreadInfo() { |  | 
| 94   return "@[tid=" + GetThreadId() + "]"; |  | 
| 95 } |  | 
| 96 |  | 
| 97 AttachThreadScoped::AttachThreadScoped(JavaVM* jvm) |  | 
| 98     : attached_(false), jvm_(jvm), env_(NULL) { |  | 
| 99   env_ = GetEnv(jvm); |  | 
| 100   if (!env_) { |  | 
| 101     // Adding debug log here so we can track down potential leaks and figure |  | 
| 102     // out why we sometimes see "Native thread exiting without having called |  | 
| 103     // DetachCurrentThread" in logcat outputs. |  | 
| 104     ALOGD("Attaching thread to JVM%s", GetThreadInfo().c_str()); |  | 
| 105     jint res = jvm->AttachCurrentThread(&env_, NULL); |  | 
| 106     attached_ = (res == JNI_OK); |  | 
| 107     RTC_CHECK(attached_) << "AttachCurrentThread failed: " << res; |  | 
| 108   } |  | 
| 109 } |  | 
| 110 |  | 
| 111 AttachThreadScoped::~AttachThreadScoped() { |  | 
| 112   if (attached_) { |  | 
| 113     ALOGD("Detaching thread from JVM%s", GetThreadInfo().c_str()); |  | 
| 114     jint res = jvm_->DetachCurrentThread(); |  | 
| 115     RTC_CHECK(res == JNI_OK) << "DetachCurrentThread failed: " << res; |  | 
| 116     RTC_CHECK(!GetEnv(jvm_)); |  | 
| 117   } |  | 
| 118 } |  | 
| 119 |  | 
| 120 JNIEnv* AttachThreadScoped::env() { return env_; } |  | 
| 121 |  | 
| 122 }  // namespace webrtc |  | 
| OLD | NEW | 
|---|