Create an experimental Android NDK.
Following files were split: sdk/android/native_api/jni_helpers.h -> sdk/android/native_api/jni/java_types.h sdk/android/native_api/jni_helpers.cc -> sdk/android/native_api/jni/java_types.cc Skipping presubmit to avoid changing moved code. Bug: webrtc:8769 Change-Id: I0ef0f6b297b5002322915660d26cca33e91ff05b No-Presubmit: true Reviewed-on: https://webrtc-review.googlesource.com/40800 Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Reviewed-by: Anders Carlsson <andersc@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21799}
This commit is contained in:
committed by
Commit Bot
parent
4f6e4f0884
commit
82f96e6a56
@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "sdk/android/generated_base_jni/jni/Histogram_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "sdk/android/generated_video_jni/jni/MediaCodecVideoDecoder_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/androidmediacodeccommon.h"
|
||||
#include "sdk/android/src/jni/surfacetexturehelper.h"
|
||||
#include "sdk/android/src/jni/videoframe.h"
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "rtc_base/weak_ptr.h"
|
||||
#include "sdk/android/generated_video_jni/jni/MediaCodecVideoEncoder_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/androidmediacodeccommon.h"
|
||||
#include "sdk/android/src/jni/androidmediadecoder_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "sdk/android/generated_metrics_jni/jni/Metrics_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
#include "system_wrappers/include/metrics_default.h"
|
||||
|
||||
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/generated_base_jni/jni/WebRtcClassLoader_jni.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
// Abort the process if |jni| has a Java exception pending. This macros uses the
|
||||
// comma operator to execute ExceptionDescribe and ExceptionClear ignoring their
|
||||
// return values and sending "" to the error stream.
|
||||
#define CHECK_EXCEPTION(jni) \
|
||||
RTC_CHECK(!jni->ExceptionCheck()) \
|
||||
<< (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
class ClassLoader {
|
||||
public:
|
||||
explicit ClassLoader(JNIEnv* env)
|
||||
: class_loader_(Java_WebRtcClassLoader_getClassLoader(env)) {
|
||||
class_loader_class_ = reinterpret_cast<jclass>(
|
||||
env->NewGlobalRef(env->FindClass("java/lang/ClassLoader")));
|
||||
CHECK_EXCEPTION(env);
|
||||
load_class_method_ =
|
||||
env->GetMethodID(class_loader_class_, "loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
CHECK_EXCEPTION(env);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jclass> FindClass(JNIEnv* env, const char* c_name) {
|
||||
// ClassLoader.loadClass expects a classname with components separated by
|
||||
// dots instead of the slashes that JNIEnv::FindClass expects.
|
||||
std::string name(c_name);
|
||||
std::replace(name.begin(), name.end(), '/', '.');
|
||||
ScopedJavaLocalRef<jstring> j_name = NativeToJavaString(env, name);
|
||||
const jclass clazz = static_cast<jclass>(env->CallObjectMethod(
|
||||
class_loader_.obj(), load_class_method_, j_name.obj()));
|
||||
CHECK_EXCEPTION(env);
|
||||
return ScopedJavaLocalRef<jclass>(env, clazz);
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedJavaGlobalRef<jobject> class_loader_;
|
||||
jclass class_loader_class_;
|
||||
jmethodID load_class_method_;
|
||||
};
|
||||
|
||||
static ClassLoader* g_class_loader = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
void InitClassLoader(JNIEnv* env) {
|
||||
RTC_CHECK(g_class_loader == nullptr);
|
||||
g_class_loader = new ClassLoader(env);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* name) {
|
||||
// The class loader will be null in the JNI code called from the ClassLoader
|
||||
// ctor when we are bootstrapping ourself.
|
||||
return (g_class_loader == nullptr)
|
||||
? ScopedJavaLocalRef<jclass>(env, env->FindClass(name))
|
||||
: g_class_loader->FindClass(env, name);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
@ -8,34 +8,16 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Android's FindClass() is tricky because the app-specific ClassLoader is not
|
||||
// consulted when there is no app-specific frame on the stack (i.e. when called
|
||||
// from a thread created from native C++ code). These helper functions provide a
|
||||
// workaround for this.
|
||||
// http://developer.android.com/training/articles/perf-jni.html#faq_FindClass
|
||||
// Deprecated: use sdk/android/native_api/jni/class_loader.h instead.
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_CLASS_LOADER_H_
|
||||
#define SDK_ANDROID_SRC_JNI_CLASS_LOADER_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
// This method should be called from JNI_OnLoad and before any calls to
|
||||
// FindClass.
|
||||
void InitClassLoader(JNIEnv* env);
|
||||
|
||||
// This function is identical to JNIEnv::FindClass except that it works from any
|
||||
// thread. This function loads and returns a local reference to the class with
|
||||
// the given name. The name argument is a fully-qualified class name. For
|
||||
// example, the fully-qualified class name for the java.lang.String class is:
|
||||
// "java/lang/String". This function will be used from the JNI generated code
|
||||
// and should rarely be used manually.
|
||||
ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* name);
|
||||
|
||||
using ::webrtc::InitClassLoader;
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
// TODO(magjed): Update external clients to call webrtc::jni::InitClassLoader
|
||||
// immediately instead.
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -21,7 +21,7 @@ namespace jni {
|
||||
|
||||
// Deprecated. Call webrtc::jni::InitClassLoader() immediately instead..
|
||||
inline void LoadGlobalClassReferenceHolder() {
|
||||
webrtc::jni::InitClassLoader(GetEnv());
|
||||
webrtc::InitClassLoader(GetEnv());
|
||||
}
|
||||
|
||||
// Deprecated. Do not call at all.
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include "common_video/include/video_frame.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "sdk/android/generated_video_jni/jni/EncodedImage_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "media/base/h264_profile_level_id.h"
|
||||
#include "sdk/android/generated_video_jni/jni/HardwareVideoEncoderFactory_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include "sdk/android/src/jni/jni_generator_helper.h"
|
||||
|
||||
#include "rtc_base/atomicops.h"
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
|
||||
namespace base {
|
||||
namespace android {
|
||||
@ -28,8 +28,7 @@ jclass LazyGetClass(JNIEnv* env,
|
||||
rtc::AtomicOps::AcquireLoadPtr(atomic_class_id);
|
||||
if (value)
|
||||
return reinterpret_cast<jclass>(value);
|
||||
webrtc::jni::ScopedJavaGlobalRef<jclass> clazz(
|
||||
webrtc::jni::GetClass(env, class_name));
|
||||
webrtc::ScopedJavaGlobalRef<jclass> clazz(webrtc::GetClass(env, class_name));
|
||||
RTC_CHECK(!clazz.is_null()) << class_name;
|
||||
base::subtle::AtomicWord null_aw = nullptr;
|
||||
base::subtle::AtomicWord cas_result = rtc::AtomicOps::CompareAndSwapPtr(
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
// TODO(crbug.com/801260): Remove this macro definition as soon as
|
||||
// crrev.com/531028 will be reverted.
|
||||
@ -61,9 +61,9 @@ typedef void* AtomicWord;
|
||||
|
||||
namespace android {
|
||||
|
||||
using webrtc::jni::JavaRef;
|
||||
using webrtc::jni::ScopedJavaLocalRef;
|
||||
using webrtc::jni::JavaParamRef;
|
||||
using webrtc::JavaRef;
|
||||
using webrtc::ScopedJavaLocalRef;
|
||||
using webrtc::JavaParamRef;
|
||||
|
||||
// This function will initialize |atomic_class_id| to contain a global ref to
|
||||
// the given class, and will return that ref on subsequent calls. The caller is
|
||||
|
||||
@ -9,133 +9,13 @@
|
||||
*/
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#include "sdk/android/generated_base_jni/jni/JniHelper_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/ArrayList_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Boolean_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Double_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Enum_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Integer_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Iterable_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Iterator_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/LinkedHashMap_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Long_jni.h"
|
||||
#include "sdk/android/generated_external_classes_jni/jni/Map_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
static JavaVM* g_jvm = nullptr;
|
||||
|
||||
static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
// Key for per-thread JNIEnv* data. Non-NULL in threads attached to |g_jvm| by
|
||||
// AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that
|
||||
// were attached by the JVM because of a Java->native call.
|
||||
static pthread_key_t g_jni_ptr;
|
||||
|
||||
JavaVM *GetJVM() {
|
||||
RTC_CHECK(g_jvm) << "JNI_OnLoad failed to run?";
|
||||
return g_jvm;
|
||||
}
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
|
||||
JNIEnv* GetEnv() {
|
||||
void* env = nullptr;
|
||||
jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6);
|
||||
RTC_CHECK(((env != nullptr) && (status == JNI_OK)) ||
|
||||
((env == nullptr) && (status == JNI_EDETACHED)))
|
||||
<< "Unexpected GetEnv return: " << status << ":" << env;
|
||||
return reinterpret_cast<JNIEnv*>(env);
|
||||
}
|
||||
|
||||
static void ThreadDestructor(void* prev_jni_ptr) {
|
||||
// This function only runs on threads where |g_jni_ptr| is non-NULL, meaning
|
||||
// we were responsible for originally attaching the thread, so are responsible
|
||||
// for detaching it now. However, because some JVM implementations (notably
|
||||
// Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism,
|
||||
// the JVMs accounting info for this thread may already be wiped out by the
|
||||
// time this is called. Thus it may appear we are already detached even though
|
||||
// it was our responsibility to detach! Oh well.
|
||||
if (!GetEnv())
|
||||
return;
|
||||
|
||||
RTC_CHECK(GetEnv() == prev_jni_ptr)
|
||||
<< "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv();
|
||||
jint status = g_jvm->DetachCurrentThread();
|
||||
RTC_CHECK(status == JNI_OK) << "Failed to detach thread: " << status;
|
||||
RTC_CHECK(!GetEnv()) << "Detaching was a successful no-op???";
|
||||
}
|
||||
|
||||
static void CreateJNIPtrKey() {
|
||||
RTC_CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor))
|
||||
<< "pthread_key_create";
|
||||
}
|
||||
|
||||
jint InitGlobalJniVariables(JavaVM *jvm) {
|
||||
RTC_CHECK(!g_jvm) << "InitGlobalJniVariables!";
|
||||
g_jvm = jvm;
|
||||
RTC_CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?";
|
||||
|
||||
RTC_CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
|
||||
|
||||
JNIEnv* jni = nullptr;
|
||||
if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK)
|
||||
return -1;
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
// Return thread ID as a string.
|
||||
static std::string GetThreadId() {
|
||||
char buf[21]; // Big enough to hold a kuint64max plus terminating NULL.
|
||||
RTC_CHECK_LT(snprintf(buf, sizeof(buf), "%ld",
|
||||
static_cast<long>(syscall(__NR_gettid))),
|
||||
sizeof(buf))
|
||||
<< "Thread id is bigger than uint64??";
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// Return the current thread's name.
|
||||
static std::string GetThreadName() {
|
||||
char name[17] = {0};
|
||||
if (prctl(PR_GET_NAME, name) != 0)
|
||||
return std::string("<noname>");
|
||||
return std::string(name);
|
||||
}
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary.
|
||||
JNIEnv* AttachCurrentThreadIfNeeded() {
|
||||
JNIEnv* jni = GetEnv();
|
||||
if (jni)
|
||||
return jni;
|
||||
RTC_CHECK(!pthread_getspecific(g_jni_ptr))
|
||||
<< "TLS has a JNIEnv* but not attached?";
|
||||
|
||||
std::string name(GetThreadName() + " - " + GetThreadId());
|
||||
JavaVMAttachArgs args;
|
||||
args.version = JNI_VERSION_1_6;
|
||||
args.name = &name[0];
|
||||
args.group = nullptr;
|
||||
// Deal with difference in signatures between Oracle's jni.h and Android's.
|
||||
#ifdef _JAVASOFT_JNI_H_ // Oracle's jni.h violates the JNI spec!
|
||||
void* env = nullptr;
|
||||
#else
|
||||
JNIEnv* env = nullptr;
|
||||
#endif
|
||||
RTC_CHECK(!g_jvm->AttachCurrentThread(&env, &args))
|
||||
<< "Failed to attach thread";
|
||||
RTC_CHECK(env) << "AttachCurrentThread handed back NULL!";
|
||||
jni = reinterpret_cast<JNIEnv*>(env);
|
||||
RTC_CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific";
|
||||
return jni;
|
||||
}
|
||||
|
||||
// Return a |jlong| that will correctly convert back to |ptr|. This is needed
|
||||
// because the alternative (of silently passing a 32-bit pointer to a vararg
|
||||
// function expecting a 64-bit param) picks up garbage in the high 32 bits.
|
||||
@ -150,10 +30,6 @@ jlong jlongFromPointer(void* ptr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj) {
|
||||
return jni->IsSameObject(obj.obj(), nullptr);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
|
||||
void* address,
|
||||
jlong capacity) {
|
||||
@ -163,103 +39,6 @@ ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Given a jstring, reinterprets it to a new native string.
|
||||
std::string JavaToStdString(JNIEnv* jni, const JavaRef<jstring>& j_string) {
|
||||
const ScopedJavaLocalRef<jbyteArray> j_byte_array =
|
||||
Java_JniHelper_getStringBytes(jni, j_string);
|
||||
|
||||
const size_t len = jni->GetArrayLength(j_byte_array.obj());
|
||||
CHECK_EXCEPTION(jni) << "error during GetArrayLength";
|
||||
std::string str(len, '\0');
|
||||
jni->GetByteArrayRegion(j_byte_array.obj(), 0, len,
|
||||
reinterpret_cast<jbyte*>(&str[0]));
|
||||
CHECK_EXCEPTION(jni) << "error during GetByteArrayRegion";
|
||||
return str;
|
||||
}
|
||||
|
||||
// Given a list of jstrings, reinterprets it to a new vector of native strings.
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
|
||||
const JavaRef<jobject>& list) {
|
||||
std::vector<std::string> converted_list;
|
||||
if (!list.is_null()) {
|
||||
for (const JavaRef<jobject>& str : Iterable(jni, list)) {
|
||||
converted_list.push_back(JavaToStdString(
|
||||
jni, JavaParamRef<jstring>(static_cast<jstring>(str.obj()))));
|
||||
}
|
||||
}
|
||||
return converted_list;
|
||||
}
|
||||
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& integer) {
|
||||
if (IsNull(jni, integer))
|
||||
return rtc::nullopt;
|
||||
return JNI_Integer::Java_Integer_intValue(jni, integer);
|
||||
}
|
||||
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
|
||||
const JavaRef<jobject>& boolean) {
|
||||
if (IsNull(jni, boolean))
|
||||
return rtc::nullopt;
|
||||
return JNI_Boolean::Java_Boolean_booleanValue(jni, boolean);
|
||||
}
|
||||
|
||||
int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long) {
|
||||
return JNI_Long::Java_Long_longValue(env, j_long);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b) {
|
||||
return JNI_Boolean::Java_Boolean_ConstructorJLB_Z(env, b);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i) {
|
||||
return JNI_Integer::Java_Integer_ConstructorJLI_I(jni, i);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u) {
|
||||
return JNI_Long::Java_Long_ConstructorJLLO_J(env, u);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d) {
|
||||
return JNI_Double::Java_Double_ConstructorJLD_D(env, d);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* env, const char* str) {
|
||||
jstring j_str = env->NewStringUTF(str);
|
||||
CHECK_EXCEPTION(env) << "error during NewStringUTF";
|
||||
return ScopedJavaLocalRef<jstring>(env, j_str);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
|
||||
const std::string& str) {
|
||||
return NativeToJavaString(jni, str.c_str());
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(
|
||||
JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int) {
|
||||
return optional_int ? NativeToJavaInteger(jni, *optional_int) : nullptr;
|
||||
}
|
||||
|
||||
std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum) {
|
||||
return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum));
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_map) {
|
||||
const JavaRef<jobject>& j_entry_set = JNI_Map::Java_Map_entrySet(jni, j_map);
|
||||
std::map<std::string, std::string> result;
|
||||
for (const JavaRef<jobject>& j_entry : Iterable(jni, j_entry_set)) {
|
||||
result.insert(std::make_pair(
|
||||
JavaToStdString(jni, Java_JniHelper_getKey(jni, j_entry)),
|
||||
JavaToStdString(jni, Java_JniHelper_getValue(jni, j_entry))));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
jobject NewGlobalRef(JNIEnv* jni, jobject o) {
|
||||
jobject ret = jni->NewGlobalRef(o);
|
||||
CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
|
||||
@ -282,133 +61,5 @@ ScopedLocalRefFrame::~ScopedLocalRefFrame() {
|
||||
jni_->PopLocalFrame(nullptr);
|
||||
}
|
||||
|
||||
Iterable::Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable)
|
||||
: jni_(jni), iterable_(jni, iterable) {}
|
||||
|
||||
Iterable::~Iterable() = default;
|
||||
|
||||
// Creates an iterator representing the end of any collection.
|
||||
Iterable::Iterator::Iterator() = default;
|
||||
|
||||
// Creates an iterator pointing to the beginning of the specified collection.
|
||||
Iterable::Iterator::Iterator(JNIEnv* jni, const JavaRef<jobject>& iterable)
|
||||
: jni_(jni) {
|
||||
iterator_ = JNI_Iterable::Java_Iterable_iterator(jni, iterable);
|
||||
RTC_CHECK(!iterator_.is_null());
|
||||
// Start at the first element in the collection.
|
||||
++(*this);
|
||||
}
|
||||
|
||||
// Move constructor - necessary to be able to return iterator types from
|
||||
// functions.
|
||||
Iterable::Iterator::Iterator(Iterator&& other)
|
||||
: jni_(std::move(other.jni_)),
|
||||
iterator_(std::move(other.iterator_)),
|
||||
value_(std::move(other.value_)),
|
||||
thread_checker_(std::move(other.thread_checker_)){};
|
||||
|
||||
Iterable::Iterator::~Iterator() = default;
|
||||
|
||||
// Advances the iterator one step.
|
||||
Iterable::Iterator& Iterable::Iterator::operator++() {
|
||||
RTC_CHECK(thread_checker_.CalledOnValidThread());
|
||||
if (AtEnd()) {
|
||||
// Can't move past the end.
|
||||
return *this;
|
||||
}
|
||||
bool has_next = JNI_Iterator::Java_Iterator_hasNext(jni_, iterator_);
|
||||
if (!has_next) {
|
||||
iterator_ = nullptr;
|
||||
value_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_ = JNI_Iterator::Java_Iterator_next(jni_, iterator_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Iterable::Iterator::Remove() {
|
||||
JNI_Iterator::Java_Iterator_remove(jni_, iterator_);
|
||||
}
|
||||
|
||||
// Provides a way to compare the iterator with itself and with the end iterator.
|
||||
// Note: all other comparison results are undefined, just like for C++ input
|
||||
// iterators.
|
||||
bool Iterable::Iterator::operator==(const Iterable::Iterator& other) {
|
||||
// Two different active iterators should never be compared.
|
||||
RTC_DCHECK(this == &other || AtEnd() || other.AtEnd());
|
||||
return AtEnd() == other.AtEnd();
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobject>& Iterable::Iterator::operator*() {
|
||||
RTC_CHECK(!AtEnd());
|
||||
return value_;
|
||||
}
|
||||
|
||||
bool Iterable::Iterator::AtEnd() const {
|
||||
RTC_CHECK(thread_checker_.CalledOnValidThread());
|
||||
return jni_ == nullptr || IsNull(jni_, iterator_);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int32_t>& container) {
|
||||
ScopedJavaLocalRef<jobject> (*convert_function)(JNIEnv*, int32_t) =
|
||||
&NativeToJavaInteger;
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Integer_clazz(env),
|
||||
convert_function);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<bool>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Boolean_clazz(env),
|
||||
&NativeToJavaBoolean);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<double>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Double_clazz(env),
|
||||
&NativeToJavaDouble);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int64_t>& container) {
|
||||
return NativeToJavaObjectArray(env, container, java_lang_Long_clazz(env),
|
||||
&NativeToJavaLong);
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<std::string>& container) {
|
||||
ScopedJavaLocalRef<jstring> (*convert)(JNIEnv*, const std::string&) =
|
||||
&NativeToJavaString;
|
||||
return NativeToJavaObjectArray(
|
||||
env, container,
|
||||
static_cast<jclass>(Java_JniHelper_getStringClass(env).obj()), convert);
|
||||
}
|
||||
|
||||
JavaMapBuilder::JavaMapBuilder(JNIEnv* env)
|
||||
: env_(env),
|
||||
j_map_(JNI_LinkedHashMap::Java_LinkedHashMap_ConstructorJULIHM(env)) {}
|
||||
|
||||
JavaMapBuilder::~JavaMapBuilder() = default;
|
||||
|
||||
void JavaMapBuilder::put(const JavaRef<jobject>& key,
|
||||
const JavaRef<jobject>& value) {
|
||||
JNI_Map::Java_Map_put(env_, j_map_, key, value);
|
||||
}
|
||||
|
||||
JavaListBuilder::JavaListBuilder(JNIEnv* env)
|
||||
: env_(env), j_list_(JNI_ArrayList::Java_ArrayList_ConstructorJUALI(env)) {}
|
||||
|
||||
JavaListBuilder::~JavaListBuilder() = default;
|
||||
|
||||
void JavaListBuilder::add(const JavaRef<jobject>& element) {
|
||||
JNI_ArrayList::Java_ArrayList_addZ_JUE(env_, j_list_, element);
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
@ -15,24 +15,11 @@
|
||||
#define SDK_ANDROID_SRC_JNI_JNI_HELPERS_H_
|
||||
|
||||
#include <jni.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/optional.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/refcount.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
|
||||
// Abort the process if |jni| has a Java exception pending.
|
||||
// This macros uses the comma operator to execute ExceptionDescribe
|
||||
// and ExceptionClear ignoring their return values and sending ""
|
||||
// to the error stream.
|
||||
#define CHECK_EXCEPTION(jni) \
|
||||
RTC_CHECK(!jni->ExceptionCheck()) \
|
||||
<< (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/src/jni/jvm.h"
|
||||
|
||||
// Convenience macro defining JNI-accessible methods in the org.webrtc package.
|
||||
// Eliminates unnecessary boilerplate and line-wraps, reducing visual clutter.
|
||||
@ -42,70 +29,17 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jint InitGlobalJniVariables(JavaVM *jvm);
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
|
||||
JNIEnv* GetEnv();
|
||||
|
||||
JavaVM *GetJVM();
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary.
|
||||
JNIEnv* AttachCurrentThreadIfNeeded();
|
||||
// TODO(sakal): Remove once clients have migrated.
|
||||
using ::webrtc::JavaToStdMapStrings;
|
||||
|
||||
// Return a |jlong| that will correctly convert back to |ptr|. This is needed
|
||||
// because the alternative (of silently passing a 32-bit pointer to a vararg
|
||||
// function expecting a 64-bit param) picks up garbage in the high 32 bits.
|
||||
jlong jlongFromPointer(void* ptr);
|
||||
|
||||
// Returns true if |obj| == null in Java.
|
||||
bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj);
|
||||
|
||||
ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
|
||||
void* address,
|
||||
jlong capacity);
|
||||
// Given a (UTF-16) jstring return a new UTF-8 native string.
|
||||
std::string JavaToStdString(JNIEnv* jni, const JavaRef<jstring>& j_string);
|
||||
|
||||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
|
||||
return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
|
||||
}
|
||||
|
||||
// Given a List of (UTF-16) jstrings
|
||||
// return a new vector of UTF-8 native strings.
|
||||
std::vector<std::string> JavaToStdVectorStrings(JNIEnv* jni,
|
||||
const JavaRef<jobject>& list);
|
||||
|
||||
rtc::Optional<int32_t> JavaToNativeOptionalInt(JNIEnv* jni,
|
||||
const JavaRef<jobject>& integer);
|
||||
rtc::Optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
|
||||
const JavaRef<jobject>& boolean);
|
||||
int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long);
|
||||
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d);
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni, const char* str);
|
||||
ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
|
||||
const std::string& str);
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaInteger(
|
||||
JNIEnv* jni,
|
||||
const rtc::Optional<int32_t>& optional_int);
|
||||
|
||||
// Parses Map<String, String> to std::map<std::string, std::string>.
|
||||
std::map<std::string, std::string> JavaToStdMapStrings(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_map);
|
||||
|
||||
// Deprecated. Use scoped jobjects instead.
|
||||
inline std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
|
||||
jobject j_map) {
|
||||
return JavaToStdMapStrings(jni, JavaParamRef<jobject>(j_map));
|
||||
}
|
||||
|
||||
// Returns the name of a Java enum.
|
||||
std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum);
|
||||
|
||||
jobject NewGlobalRef(JNIEnv* jni, jobject o);
|
||||
|
||||
@ -123,178 +57,13 @@ class ScopedLocalRefFrame {
|
||||
JNIEnv* jni_;
|
||||
};
|
||||
|
||||
// Provides a convenient way to iterate over a Java Iterable using the
|
||||
// C++ range-for loop.
|
||||
// E.g. for (jobject value : Iterable(jni, j_iterable)) { ... }
|
||||
// Note: Since Java iterators cannot be duplicated, the iterator class is not
|
||||
// copyable to prevent creating multiple C++ iterators that refer to the same
|
||||
// Java iterator.
|
||||
class Iterable {
|
||||
public:
|
||||
Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable);
|
||||
~Iterable();
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
// Creates an iterator representing the end of any collection.
|
||||
Iterator();
|
||||
// Creates an iterator pointing to the beginning of the specified
|
||||
// collection.
|
||||
Iterator(JNIEnv* jni, const JavaRef<jobject>& iterable);
|
||||
|
||||
// Move constructor - necessary to be able to return iterator types from
|
||||
// functions.
|
||||
Iterator(Iterator&& other);
|
||||
|
||||
~Iterator();
|
||||
|
||||
// Move assignment should not be used.
|
||||
Iterator& operator=(Iterator&&) = delete;
|
||||
|
||||
// Advances the iterator one step.
|
||||
Iterator& operator++();
|
||||
|
||||
// Removes the element the iterator is pointing to. Must still advance the
|
||||
// iterator afterwards.
|
||||
void Remove();
|
||||
|
||||
// Provides a way to compare the iterator with itself and with the end
|
||||
// iterator.
|
||||
// Note: all other comparison results are undefined, just like for C++ input
|
||||
// iterators.
|
||||
bool operator==(const Iterator& other);
|
||||
bool operator!=(const Iterator& other) { return !(*this == other); }
|
||||
ScopedJavaLocalRef<jobject>& operator*();
|
||||
|
||||
private:
|
||||
bool AtEnd() const;
|
||||
|
||||
JNIEnv* jni_ = nullptr;
|
||||
ScopedJavaLocalRef<jobject> iterator_;
|
||||
ScopedJavaLocalRef<jobject> value_;
|
||||
rtc::ThreadChecker thread_checker_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(Iterator);
|
||||
};
|
||||
|
||||
Iterable::Iterator begin() { return Iterable::Iterator(jni_, iterable_); }
|
||||
Iterable::Iterator end() { return Iterable::Iterator(); }
|
||||
|
||||
private:
|
||||
JNIEnv* jni_;
|
||||
ScopedJavaLocalRef<jobject> iterable_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(Iterable);
|
||||
};
|
||||
|
||||
// Helper function for converting std::vector<T> into a Java array.
|
||||
template <typename T, typename Convert>
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaObjectArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<T>& container,
|
||||
jclass clazz,
|
||||
Convert convert) {
|
||||
ScopedJavaLocalRef<jobjectArray> j_container(
|
||||
env, env->NewObjectArray(container.size(), clazz, nullptr));
|
||||
int i = 0;
|
||||
for (const T& element : container) {
|
||||
env->SetObjectArrayElement(j_container.obj(), i,
|
||||
convert(env, element).obj());
|
||||
++i;
|
||||
}
|
||||
return j_container;
|
||||
}
|
||||
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int32_t>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<bool>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<int64_t>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<double>& container);
|
||||
ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
|
||||
JNIEnv* env,
|
||||
const std::vector<std::string>& container);
|
||||
|
||||
template <typename T, typename Convert>
|
||||
std::vector<T> JavaToNativeVector(JNIEnv* env,
|
||||
const JavaRef<jobjectArray>& j_container,
|
||||
Convert convert) {
|
||||
std::vector<T> container;
|
||||
const size_t size = env->GetArrayLength(j_container.obj());
|
||||
container.reserve(size);
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
container.emplace_back(convert(
|
||||
env, ScopedJavaLocalRef<jobject>(
|
||||
env, env->GetObjectArrayElement(j_container.obj(), i))));
|
||||
}
|
||||
CHECK_EXCEPTION(env) << "Error during JavaToNativeVector";
|
||||
return container;
|
||||
}
|
||||
|
||||
// This is a helper class for NativeToJavaList(). Use that function instead of
|
||||
// using this class directly.
|
||||
class JavaListBuilder {
|
||||
public:
|
||||
explicit JavaListBuilder(JNIEnv* env);
|
||||
~JavaListBuilder();
|
||||
void add(const JavaRef<jobject>& element);
|
||||
ScopedJavaLocalRef<jobject> java_list() { return j_list_; }
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
ScopedJavaLocalRef<jobject> j_list_;
|
||||
};
|
||||
|
||||
template <typename C, typename Convert>
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaList(JNIEnv* env,
|
||||
const C& container,
|
||||
Convert convert) {
|
||||
JavaListBuilder builder(env);
|
||||
for (const auto& e : container)
|
||||
builder.add(convert(env, e));
|
||||
return builder.java_list();
|
||||
}
|
||||
|
||||
// This is a helper class for NativeToJavaMap(). Use that function instead of
|
||||
// using this class directly.
|
||||
class JavaMapBuilder {
|
||||
public:
|
||||
explicit JavaMapBuilder(JNIEnv* env);
|
||||
~JavaMapBuilder();
|
||||
void put(const JavaRef<jobject>& key, const JavaRef<jobject>& value);
|
||||
ScopedJavaLocalRef<jobject> GetJavaMap() { return j_map_; }
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
ScopedJavaLocalRef<jobject> j_map_;
|
||||
};
|
||||
|
||||
template <typename C, typename Convert>
|
||||
ScopedJavaLocalRef<jobject> NativeToJavaMap(JNIEnv* env,
|
||||
const C& container,
|
||||
Convert convert) {
|
||||
JavaMapBuilder builder(env);
|
||||
for (const auto& e : container) {
|
||||
ScopedLocalRefFrame local_ref_frame(env);
|
||||
const auto key_value_pair = convert(env, e);
|
||||
builder.put(key_value_pair.first, key_value_pair.second);
|
||||
}
|
||||
return builder.GetJavaMap();
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
// TODO(magjed): Remove once external clients are updated.
|
||||
namespace webrtc_jni {
|
||||
|
||||
using webrtc::jni::AttachCurrentThreadIfNeeded;
|
||||
using webrtc::AttachCurrentThreadIfNeeded;
|
||||
using webrtc::jni::InitGlobalJniVariables;
|
||||
|
||||
} // namespace webrtc_jni
|
||||
|
||||
133
sdk/android/src/jni/jvm.cc
Normal file
133
sdk/android/src/jni/jvm.cc
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "sdk/android/src/jni/jvm.h"
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
static JavaVM* g_jvm = nullptr;
|
||||
|
||||
static pthread_once_t g_jni_ptr_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
// Key for per-thread JNIEnv* data. Non-NULL in threads attached to |g_jvm| by
|
||||
// AttachCurrentThreadIfNeeded(), NULL in unattached threads and threads that
|
||||
// were attached by the JVM because of a Java->native call.
|
||||
static pthread_key_t g_jni_ptr;
|
||||
|
||||
JavaVM* GetJVM() {
|
||||
RTC_CHECK(g_jvm) << "JNI_OnLoad failed to run?";
|
||||
return g_jvm;
|
||||
}
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
|
||||
JNIEnv* GetEnv() {
|
||||
void* env = nullptr;
|
||||
jint status = g_jvm->GetEnv(&env, JNI_VERSION_1_6);
|
||||
RTC_CHECK(((env != nullptr) && (status == JNI_OK)) ||
|
||||
((env == nullptr) && (status == JNI_EDETACHED)))
|
||||
<< "Unexpected GetEnv return: " << status << ":" << env;
|
||||
return reinterpret_cast<JNIEnv*>(env);
|
||||
}
|
||||
|
||||
static void ThreadDestructor(void* prev_jni_ptr) {
|
||||
// This function only runs on threads where |g_jni_ptr| is non-NULL, meaning
|
||||
// we were responsible for originally attaching the thread, so are responsible
|
||||
// for detaching it now. However, because some JVM implementations (notably
|
||||
// Oracle's http://goo.gl/eHApYT) also use the pthread_key_create mechanism,
|
||||
// the JVMs accounting info for this thread may already be wiped out by the
|
||||
// time this is called. Thus it may appear we are already detached even though
|
||||
// it was our responsibility to detach! Oh well.
|
||||
if (!GetEnv())
|
||||
return;
|
||||
|
||||
RTC_CHECK(GetEnv() == prev_jni_ptr)
|
||||
<< "Detaching from another thread: " << prev_jni_ptr << ":" << GetEnv();
|
||||
jint status = g_jvm->DetachCurrentThread();
|
||||
RTC_CHECK(status == JNI_OK) << "Failed to detach thread: " << status;
|
||||
RTC_CHECK(!GetEnv()) << "Detaching was a successful no-op???";
|
||||
}
|
||||
|
||||
static void CreateJNIPtrKey() {
|
||||
RTC_CHECK(!pthread_key_create(&g_jni_ptr, &ThreadDestructor))
|
||||
<< "pthread_key_create";
|
||||
}
|
||||
|
||||
jint InitGlobalJniVariables(JavaVM* jvm) {
|
||||
RTC_CHECK(!g_jvm) << "InitGlobalJniVariables!";
|
||||
g_jvm = jvm;
|
||||
RTC_CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?";
|
||||
|
||||
RTC_CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
|
||||
|
||||
JNIEnv* jni = nullptr;
|
||||
if (jvm->GetEnv(reinterpret_cast<void**>(&jni), JNI_VERSION_1_6) != JNI_OK)
|
||||
return -1;
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
// Return thread ID as a string.
|
||||
static std::string GetThreadId() {
|
||||
char buf[21]; // Big enough to hold a kuint64max plus terminating NULL.
|
||||
RTC_CHECK_LT(snprintf(buf, sizeof(buf), "%ld",
|
||||
static_cast<long>(syscall(__NR_gettid))),
|
||||
sizeof(buf))
|
||||
<< "Thread id is bigger than uint64??";
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// Return the current thread's name.
|
||||
static std::string GetThreadName() {
|
||||
char name[17] = {0};
|
||||
if (prctl(PR_GET_NAME, name) != 0)
|
||||
return std::string("<noname>");
|
||||
return std::string(name);
|
||||
}
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary.
|
||||
JNIEnv* AttachCurrentThreadIfNeeded() {
|
||||
JNIEnv* jni = GetEnv();
|
||||
if (jni)
|
||||
return jni;
|
||||
RTC_CHECK(!pthread_getspecific(g_jni_ptr))
|
||||
<< "TLS has a JNIEnv* but not attached?";
|
||||
|
||||
std::string name(GetThreadName() + " - " + GetThreadId());
|
||||
JavaVMAttachArgs args;
|
||||
args.version = JNI_VERSION_1_6;
|
||||
args.name = &name[0];
|
||||
args.group = nullptr;
|
||||
// Deal with difference in signatures between Oracle's jni.h and Android's.
|
||||
#ifdef _JAVASOFT_JNI_H_ // Oracle's jni.h violates the JNI spec!
|
||||
void* env = nullptr;
|
||||
#else
|
||||
JNIEnv* env = nullptr;
|
||||
#endif
|
||||
RTC_CHECK(!g_jvm->AttachCurrentThread(&env, &args))
|
||||
<< "Failed to attach thread";
|
||||
RTC_CHECK(env) << "AttachCurrentThread handed back NULL!";
|
||||
jni = reinterpret_cast<JNIEnv*>(env);
|
||||
RTC_CHECK(!pthread_setspecific(g_jni_ptr, jni)) << "pthread_setspecific";
|
||||
return jni;
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
32
sdk/android/src/jni/jvm.h
Normal file
32
sdk/android/src/jni/jvm.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_JVM_H_
|
||||
#define SDK_ANDROID_SRC_JNI_JVM_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
jint InitGlobalJniVariables(JavaVM* jvm);
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread or NULL if this thread is detached.
|
||||
JNIEnv* GetEnv();
|
||||
|
||||
JavaVM* GetJVM();
|
||||
|
||||
// Return a |JNIEnv*| usable on this thread. Attaches to |g_jvm| if necessary.
|
||||
JNIEnv* AttachCurrentThreadIfNeeded();
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SDK_ANDROID_SRC_JNI_JVM_H_
|
||||
@ -21,6 +21,7 @@
|
||||
#include "rtc_base/ipaddress.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/NetworkMonitorAutoDetect_jni.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/NetworkMonitor_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "rtc_base/logsinks.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/CallSessionFileRotatingLogSink_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/DataChannel_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/datachannel.h"
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "api/dtmfsenderinterface.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/DtmfSender_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "pc/webrtcsdp.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/IceCandidate_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/pc/mediastreamtrack.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/MediaConstraints_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "api/mediaconstraintsinterface.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/MediaStream_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "api/mediastreaminterface.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/MediaStreamTrack_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/mediatypes.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/ptr_util.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/PeerConnection_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/datachannel.h"
|
||||
#include "sdk/android/src/jni/pc/icecandidate.h"
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "rtc_base/stringutils.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/PeerConnectionFactory_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/androidnetworkmonitor.h"
|
||||
#include "sdk/android/src/jni/pc/audio.h"
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RTCStatsCollectorCallback_jni.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RTCStatsReport_jni.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RTCStats_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "sdk/android/src/jni/pc/rtpparameters.h"
|
||||
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RtpParameters_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/mediastreamtrack.h"
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpparameters.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "sdk/android/src/jni/pc/rtpreceiver.h"
|
||||
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RtpReceiver_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/mediastreamtrack.h"
|
||||
#include "sdk/android/src/jni/pc/rtpparameters.h"
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpreceiverinterface.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "sdk/android/src/jni/pc/rtpsender.h"
|
||||
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/RtpSender_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/pc/rtpparameters.h"
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/rtpsenderinterface.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "api/mediaconstraintsinterface.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/SdpObserver_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/SessionDescription_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "api/jsep.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/StatsObserver_jni.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/StatsReport_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "api/turncustomizer.h"
|
||||
#include "sdk/android/generated_peerconnection_jni/jni/TurnCustomizer_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#define SDK_ANDROID_SRC_JNI_PC_TURNCUSTOMIZER_H_
|
||||
|
||||
#include "api/turncustomizer.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
#include "sdk/android/src/jni/androidmediadecoder_jni.h"
|
||||
#include "sdk/android/src/jni/androidmediaencoder_jni.h"
|
||||
#include "sdk/android/src/jni/androidvideotracksource.h"
|
||||
#include "sdk/android/src/jni/pc/ownedfactoryandthreads.h"
|
||||
#include "sdk/android/src/jni/surfacetexturehelper.h"
|
||||
#include "sdk/android/src/jni/videodecoderfactorywrapper.h"
|
||||
#include "sdk/android/src/jni/videoencoderfactorywrapper.h"
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
|
||||
#include "rtc_base/scoped_ref_ptr.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace cricket {
|
||||
class WebRtcVideoEncoderFactory;
|
||||
|
||||
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
// Originally these classes are from Chromium.
|
||||
// https://cs.chromium.org/chromium/src/base/android/scoped_java_ref.h.
|
||||
|
||||
#ifndef SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
#define SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
|
||||
#include <jni.h>
|
||||
#include <utility>
|
||||
|
||||
#include "rtc_base/constructormagic.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
JNIEnv* AttachCurrentThreadIfNeeded();
|
||||
|
||||
// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
|
||||
// for allowing functions to accept a reference without having to mandate
|
||||
// whether it is a local or global type.
|
||||
template <typename T>
|
||||
class JavaRef;
|
||||
|
||||
// Template specialization of JavaRef, which acts as the base class for all
|
||||
// other JavaRef<> template types. This allows you to e.g. pass JavaRef<jstring>
|
||||
// into a function taking const JavaRef<jobject>&.
|
||||
template <>
|
||||
class JavaRef<jobject> {
|
||||
public:
|
||||
jobject obj() const { return obj_; }
|
||||
bool is_null() const {
|
||||
// This is not valid for weak references. For weak references you need to
|
||||
// use env->IsSameObject(objc_, nullptr), but that should be avoided anyway
|
||||
// since it does not prevent the object from being freed immediately
|
||||
// thereafter. Consequently, programmers should not use this check on weak
|
||||
// references anyway and should first make a ScopedJavaLocalRef or
|
||||
// ScopedJavaGlobalRef before checking if it is null.
|
||||
return obj_ == nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
JavaRef() : obj_(nullptr) {}
|
||||
explicit JavaRef(jobject obj) : obj_(obj) {}
|
||||
jobject obj_;
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaRef);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class JavaRef : public JavaRef<jobject> {
|
||||
public:
|
||||
T obj() const { return static_cast<T>(obj_); }
|
||||
|
||||
protected:
|
||||
JavaRef() : JavaRef<jobject>(nullptr) {}
|
||||
explicit JavaRef(T obj) : JavaRef<jobject>(obj) {}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaRef);
|
||||
};
|
||||
|
||||
// Holds a local reference to a JNI method parameter.
|
||||
// Method parameters should not be deleted, and so this class exists purely to
|
||||
// wrap them as a JavaRef<T> in the JNI binding generator. Do not create
|
||||
// instances manually.
|
||||
template <typename T>
|
||||
class JavaParamRef : public JavaRef<T> {
|
||||
public:
|
||||
// Assumes that |obj| is a parameter passed to a JNI method from Java.
|
||||
// Does not assume ownership as parameters should not be deleted.
|
||||
explicit JavaParamRef(T obj) : JavaRef<T>(obj) {}
|
||||
JavaParamRef(JNIEnv*, T obj) : JavaRef<T>(obj) {}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(JavaParamRef);
|
||||
};
|
||||
|
||||
// Holds a local reference to a Java object. The local reference is scoped
|
||||
// to the lifetime of this object.
|
||||
// Instances of this class may hold onto any JNIEnv passed into it until
|
||||
// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
|
||||
// thread, objects of this class must be created, used, and destroyed, on a
|
||||
// single thread.
|
||||
// Therefore, this class should only be used as a stack-based object and from a
|
||||
// single thread. If you wish to have the reference outlive the current
|
||||
// callstack (e.g. as a class member) or you wish to pass it across threads,
|
||||
// use a ScopedJavaGlobalRef instead.
|
||||
template <typename T>
|
||||
class ScopedJavaLocalRef : public JavaRef<T> {
|
||||
public:
|
||||
ScopedJavaLocalRef() = default;
|
||||
ScopedJavaLocalRef(std::nullptr_t) {} // NOLINT(runtime/explicit)
|
||||
|
||||
ScopedJavaLocalRef(JNIEnv* env, const JavaRef<T>& other) : env_(env) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
// Allow constructing e.g. ScopedJavaLocalRef<jobject> from
|
||||
// ScopedJavaLocalRef<jstring>.
|
||||
template <typename G>
|
||||
ScopedJavaLocalRef(ScopedJavaLocalRef<G>&& other) : env_(other.env()) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
|
||||
// Assumes that |obj| is a reference to a Java object and takes
|
||||
// ownership of this reference. This should preferably not be used
|
||||
// outside of JNI helper functions.
|
||||
ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(obj), env_(env) {}
|
||||
|
||||
~ScopedJavaLocalRef() {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
}
|
||||
|
||||
void operator=(const ScopedJavaLocalRef& other) {
|
||||
Reset(other.obj(), OwnershipPolicy::RETAIN);
|
||||
}
|
||||
void operator=(ScopedJavaLocalRef&& other) {
|
||||
Reset(other.Release(), OwnershipPolicy::ADOPT);
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
JNIEnv* env() const { return env_; }
|
||||
|
||||
private:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
enum OwnershipPolicy {
|
||||
// The scoped object takes ownership of an object by taking over an existing
|
||||
// ownership claim.
|
||||
ADOPT,
|
||||
// The scoped object will retain the the object and any initial ownership is
|
||||
// not changed.
|
||||
RETAIN
|
||||
};
|
||||
|
||||
void Reset(T obj, OwnershipPolicy policy) {
|
||||
if (obj_ != nullptr)
|
||||
env_->DeleteLocalRef(obj_);
|
||||
obj_ = (obj != nullptr && policy == OwnershipPolicy::RETAIN)
|
||||
? env_->NewLocalRef(obj)
|
||||
: obj;
|
||||
}
|
||||
|
||||
JNIEnv* const env_ = AttachCurrentThreadIfNeeded();
|
||||
};
|
||||
|
||||
// Holds a global reference to a Java object. The global reference is scoped
|
||||
// to the lifetime of this object. This class does not hold onto any JNIEnv*
|
||||
// passed to it, hence it is safe to use across threads (within the constraints
|
||||
// imposed by the underlying Java object that it references).
|
||||
template <typename T>
|
||||
class ScopedJavaGlobalRef : public JavaRef<T> {
|
||||
public:
|
||||
using JavaRef<T>::obj_;
|
||||
|
||||
ScopedJavaGlobalRef(JNIEnv* env, const JavaRef<T>& other)
|
||||
: JavaRef<T>(static_cast<T>(env->NewGlobalRef(other.obj()))) {}
|
||||
explicit ScopedJavaGlobalRef(const ScopedJavaLocalRef<T>& other)
|
||||
: ScopedJavaGlobalRef(other.env(), other) {}
|
||||
ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other)
|
||||
: JavaRef<T>(other.Release()) {}
|
||||
|
||||
~ScopedJavaGlobalRef() {
|
||||
if (obj_ != nullptr)
|
||||
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
|
||||
}
|
||||
|
||||
// Releases the reference to the caller. The caller *must* delete the
|
||||
// reference when it is done with it. Note that calling a Java method
|
||||
// is *not* a transfer of ownership and Release() should not be used.
|
||||
T Release() {
|
||||
T obj = static_cast<T>(obj_);
|
||||
obj_ = nullptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(ScopedJavaGlobalRef);
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SDK_ANDROID_SRC_JNI_SCOPED_JAVA_REF_H_
|
||||
@ -13,6 +13,7 @@
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/SurfaceTextureHelper_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/videoframe.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "sdk/android/src/jni/videocodecinfo.h"
|
||||
|
||||
#include "sdk/android/generated_video_jni/jni/VideoCodecInfo_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoDecoderFactory_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/wrappednativecodec.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoDecoderWrapper_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoDecoder_jni.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/encodedimage.h"
|
||||
#include "sdk/android/src/jni/videocodecstatus.h"
|
||||
#include "sdk/android/src/jni/videoframe.h"
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "rtc_base/logging.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoEncoderFactory_jni.h"
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/videocodecinfo.h"
|
||||
#include "sdk/android/src/jni/wrappednativecodec.h"
|
||||
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
#include "rtc_base/timeutils.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoEncoderWrapper_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/VideoEncoder_jni.h"
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/java_types.h"
|
||||
#include "sdk/android/src/jni/encodedimage.h"
|
||||
#include "sdk/android/src/jni/videocodecstatus.h"
|
||||
|
||||
|
||||
@ -23,6 +23,9 @@
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
// TODO(sakal): Remove once clients have migrated.
|
||||
using ::webrtc::JavaParamRef;
|
||||
|
||||
class SurfaceTextureHelper;
|
||||
|
||||
// Open gl texture matrix, in column-major order. Operations are
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "api/video/video_frame_buffer.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include "sdk/android/generated_video_jni/jni/WrappedNativeVideoDecoder_jni.h"
|
||||
#include "sdk/android/generated_video_jni/jni/WrappedNativeVideoEncoder_jni.h"
|
||||
#include "sdk/android/src/jni/class_loader.h"
|
||||
#include "sdk/android/native_api/jni/class_loader.h"
|
||||
#include "sdk/android/src/jni/jni_helpers.h"
|
||||
#include "sdk/android/src/jni/videodecoderwrapper.h"
|
||||
#include "sdk/android/src/jni/videoencoderwrapper.h"
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
|
||||
#include "api/video_codecs/video_decoder.h"
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "sdk/android/src/jni/scoped_java_ref.h"
|
||||
#include "sdk/android/native_api/jni/scoped_java_ref.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace jni {
|
||||
|
||||
Reference in New Issue
Block a user