summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/sdk/android/native_api/jni
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/libwebrtc/sdk/android/native_api/jni
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/sdk/android/native_api/jni')
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/class_loader.cc80
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/class_loader.h40
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/java_types.cc355
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/java_types.h366
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/jni_int_wrapper.h59
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/jvm.cc21
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/jvm.h21
-rw-r--r--third_party/libwebrtc/sdk/android/native_api/jni/scoped_java_ref.h226
8 files changed, 1168 insertions, 0 deletions
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.cc b/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.cc
new file mode 100644
index 0000000000..1789d78c85
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.cc
@@ -0,0 +1,80 @@
+/*
+ * 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/native_api/jni/class_loader.h"
+
+#include <algorithm>
+#include <string>
+
+#include "rtc_base/checks.h"
+#include "sdk/android/generated_native_api_jni/WebRtcClassLoader_jni.h"
+#include "sdk/android/native_api/jni/java_types.h"
+#include "sdk/android/native_api/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 {
+
+class ClassLoader {
+ public:
+ explicit ClassLoader(JNIEnv* env)
+ : class_loader_(jni::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 webrtc
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.h b/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.h
new file mode 100644
index 0000000000..2d102fe4a2
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/class_loader.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+// 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
+
+#ifndef SDK_ANDROID_NATIVE_API_JNI_CLASS_LOADER_H_
+#define SDK_ANDROID_NATIVE_API_JNI_CLASS_LOADER_H_
+
+#include <jni.h>
+
+#include "sdk/android/native_api/jni/scoped_java_ref.h"
+
+namespace webrtc {
+
+// This method should be called from JNI_OnLoad and before any calls to
+// FindClass. This is normally called by InitAndroid.
+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);
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_CLASS_LOADER_H_
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/java_types.cc b/third_party/libwebrtc/sdk/android/native_api/jni/java_types.cc
new file mode 100644
index 0000000000..af02c10f4c
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/java_types.cc
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2015 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/native_api/jni/java_types.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "sdk/android/generated_external_classes_jni/ArrayList_jni.h"
+#include "sdk/android/generated_external_classes_jni/Boolean_jni.h"
+#include "sdk/android/generated_external_classes_jni/Double_jni.h"
+#include "sdk/android/generated_external_classes_jni/Enum_jni.h"
+#include "sdk/android/generated_external_classes_jni/Integer_jni.h"
+#include "sdk/android/generated_external_classes_jni/Iterable_jni.h"
+#include "sdk/android/generated_external_classes_jni/Iterator_jni.h"
+#include "sdk/android/generated_external_classes_jni/LinkedHashMap_jni.h"
+#include "sdk/android/generated_external_classes_jni/Long_jni.h"
+#include "sdk/android/generated_external_classes_jni/Map_jni.h"
+#include "sdk/android/generated_native_api_jni/JniHelper_jni.h"
+
+namespace webrtc {
+
+Iterable::Iterable(JNIEnv* jni, const JavaRef<jobject>& iterable)
+ : jni_(jni), iterable_(jni, iterable) {}
+
+Iterable::Iterable(Iterable&& other) = default;
+
+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_)) {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+}
+
+Iterable::Iterator::~Iterator() = default;
+
+// Advances the iterator one step.
+Iterable::Iterator& Iterable::Iterator::operator++() {
+ RTC_DCHECK_RUN_ON(&thread_checker_);
+ 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_DCHECK_RUN_ON(&thread_checker_);
+ return jni_ == nullptr || IsNull(jni_, iterator_);
+}
+
+bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj) {
+ return jni->IsSameObject(obj.obj(), nullptr);
+}
+
+std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum) {
+ return JavaToStdString(jni, JNI_Enum::Java_Enum_name(jni, j_enum));
+}
+
+Iterable GetJavaMapEntrySet(JNIEnv* jni, const JavaRef<jobject>& j_map) {
+ return Iterable(jni, JNI_Map::Java_Map_entrySet(jni, j_map));
+}
+
+ScopedJavaLocalRef<jobject> GetJavaMapEntryKey(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_entry) {
+ return jni::Java_JniHelper_getKey(jni, j_entry);
+}
+
+ScopedJavaLocalRef<jobject> GetJavaMapEntryValue(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_entry) {
+ return jni::Java_JniHelper_getValue(jni, j_entry);
+}
+
+int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long) {
+ return JNI_Long::Java_Long_longValue(env, j_long);
+}
+
+absl::optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
+ const JavaRef<jobject>& boolean) {
+ if (IsNull(jni, boolean))
+ return absl::nullopt;
+ return JNI_Boolean::Java_Boolean_booleanValue(jni, boolean);
+}
+
+absl::optional<double> JavaToNativeOptionalDouble(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_double) {
+ if (IsNull(jni, j_double))
+ return absl::nullopt;
+ return JNI_Double::Java_Double_doubleValue(jni, j_double);
+}
+
+absl::optional<int32_t> JavaToNativeOptionalInt(
+ JNIEnv* jni,
+ const JavaRef<jobject>& integer) {
+ if (IsNull(jni, integer))
+ return absl::nullopt;
+ return JNI_Integer::Java_Integer_intValue(jni, integer);
+}
+
+// Given a jstring, reinterprets it to a new native string.
+std::string JavaToNativeString(JNIEnv* jni, const JavaRef<jstring>& j_string) {
+ const ScopedJavaLocalRef<jbyteArray> j_byte_array =
+ jni::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;
+}
+
+std::map<std::string, std::string> JavaToNativeStringMap(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_map) {
+ return JavaToNativeMap<std::string, std::string>(
+ jni, j_map,
+ [](JNIEnv* env, JavaRef<jobject> const& key,
+ JavaRef<jobject> const& value) {
+ return std::make_pair(
+ JavaToNativeString(env, static_java_ref_cast<jstring>(env, key)),
+ JavaToNativeString(env, static_java_ref_cast<jstring>(env, value)));
+ });
+}
+
+ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b) {
+ return JNI_Boolean::Java_Boolean_ConstructorJLB_Z(env, b);
+}
+
+ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d) {
+ return JNI_Double::Java_Double_ConstructorJLD_D(env, d);
+}
+
+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<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> NativeToJavaDouble(
+ JNIEnv* jni,
+ const absl::optional<double>& optional_double) {
+ return optional_double ? NativeToJavaDouble(jni, *optional_double) : nullptr;
+}
+
+ScopedJavaLocalRef<jobject> NativeToJavaInteger(
+ JNIEnv* jni,
+ const absl::optional<int32_t>& optional_int) {
+ return optional_int ? NativeToJavaInteger(jni, *optional_int) : nullptr;
+}
+
+ScopedJavaLocalRef<jstring> NativeToJavaString(
+ JNIEnv* jni,
+ const absl::optional<std::string>& str) {
+ return str ? NativeToJavaString(jni, *str) : nullptr;
+}
+
+ScopedJavaLocalRef<jbyteArray> NativeToJavaByteArray(
+ JNIEnv* env,
+ rtc::ArrayView<int8_t> container) {
+ ScopedJavaLocalRef<jbyteArray> jarray(env,
+ env->NewByteArray(container.size()));
+ int8_t* array_ptr =
+ env->GetByteArrayElements(jarray.obj(), /*isCopy=*/nullptr);
+ memcpy(array_ptr, container.data(), container.size() * sizeof(int8_t));
+ env->ReleaseByteArrayElements(jarray.obj(), array_ptr, /*mode=*/0);
+ return jarray;
+}
+
+ScopedJavaLocalRef<jintArray> NativeToJavaIntArray(
+ JNIEnv* env,
+ rtc::ArrayView<int32_t> container) {
+ ScopedJavaLocalRef<jintArray> jarray(env, env->NewIntArray(container.size()));
+ int32_t* array_ptr =
+ env->GetIntArrayElements(jarray.obj(), /*isCopy=*/nullptr);
+ memcpy(array_ptr, container.data(), container.size() * sizeof(int32_t));
+ env->ReleaseIntArrayElements(jarray.obj(), array_ptr, /*mode=*/0);
+ return jarray;
+}
+
+std::vector<int8_t> JavaToNativeByteArray(JNIEnv* env,
+ const JavaRef<jbyteArray>& jarray) {
+ int8_t* array_ptr =
+ env->GetByteArrayElements(jarray.obj(), /*isCopy=*/nullptr);
+ size_t array_length = env->GetArrayLength(jarray.obj());
+ std::vector<int8_t> container(array_ptr, array_ptr + array_length);
+ env->ReleaseByteArrayElements(jarray.obj(), array_ptr, /*mode=*/JNI_ABORT);
+ return container;
+}
+
+std::vector<int32_t> JavaToNativeIntArray(JNIEnv* env,
+ const JavaRef<jintArray>& jarray) {
+ int32_t* array_ptr =
+ env->GetIntArrayElements(jarray.obj(), /*isCopy=*/nullptr);
+ size_t array_length = env->GetArrayLength(jarray.obj());
+ std::vector<int32_t> container(array_ptr, array_ptr + array_length);
+ env->ReleaseIntArrayElements(jarray.obj(), array_ptr, /*mode=*/JNI_ABORT);
+ return container;
+}
+
+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) {
+ ScopedJavaLocalRef<jobject> (*convert_function)(JNIEnv*, double) =
+ &NativeToJavaDouble;
+ return NativeToJavaObjectArray(env, container, java_lang_Double_clazz(env),
+ convert_function);
+}
+
+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> 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_function)(JNIEnv*, const std::string&) =
+ &NativeToJavaString;
+ return NativeToJavaObjectArray(
+ env, container,
+ static_cast<jclass>(jni::Java_JniHelper_getStringClass(env).obj()),
+ convert_function);
+}
+
+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);
+}
+
+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);
+}
+
+jlong NativeToJavaPointer(void* ptr) {
+ static_assert(sizeof(intptr_t) <= sizeof(jlong),
+ "Time to rethink the use of jlongs");
+ // Going through intptr_t to be obvious about the definedness of the
+ // conversion from pointer to integral type. intptr_t to jlong is a standard
+ // widening by the static_assert above.
+ jlong ret = reinterpret_cast<intptr_t>(ptr);
+ RTC_DCHECK(reinterpret_cast<void*>(ret) == ptr);
+ return ret;
+}
+
+// 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;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/java_types.h b/third_party/libwebrtc/sdk/android/native_api/jni/java_types.h
new file mode 100644
index 0000000000..1008737d90
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/java_types.h
@@ -0,0 +1,366 @@
+/*
+ * Copyright 2015 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.
+ */
+
+// 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
+
+#ifndef SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
+#define SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
+
+#include <jni.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/sequence_checker.h"
+#include "rtc_base/checks.h"
+#include "sdk/android/native_api/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 {
+
+// ---------------
+// -- Utilities --
+// ---------------
+
+// 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(Iterable&& other);
+
+ ~Iterable();
+
+ Iterable(const Iterable&) = delete;
+ Iterable& operator=(const Iterable&) = delete;
+
+ 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();
+
+ Iterator(const Iterator&) = delete;
+ Iterator& operator=(const Iterator&) = delete;
+
+ // 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_;
+ SequenceChecker thread_checker_;
+ };
+
+ Iterable::Iterator begin() { return Iterable::Iterator(jni_, iterable_); }
+ Iterable::Iterator end() { return Iterable::Iterator(); }
+
+ private:
+ JNIEnv* jni_;
+ ScopedJavaLocalRef<jobject> iterable_;
+};
+
+// Returns true if `obj` == null in Java.
+bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj);
+
+// Returns the name of a Java enum.
+std::string GetJavaEnumName(JNIEnv* jni, const JavaRef<jobject>& j_enum);
+
+Iterable GetJavaMapEntrySet(JNIEnv* jni, const JavaRef<jobject>& j_map);
+ScopedJavaLocalRef<jobject> GetJavaMapEntryKey(JNIEnv* jni,
+ const JavaRef<jobject>& j_entry);
+ScopedJavaLocalRef<jobject> GetJavaMapEntryValue(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_entry);
+
+// --------------------------------------------------------
+// -- Methods for converting Java types to native types. --
+// --------------------------------------------------------
+
+int64_t JavaToNativeLong(JNIEnv* env, const JavaRef<jobject>& j_long);
+
+absl::optional<bool> JavaToNativeOptionalBool(JNIEnv* jni,
+ const JavaRef<jobject>& boolean);
+absl::optional<double> JavaToNativeOptionalDouble(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_double);
+absl::optional<int32_t> JavaToNativeOptionalInt(
+ JNIEnv* jni,
+ const JavaRef<jobject>& integer);
+
+// Given a (UTF-16) jstring return a new UTF-8 native string.
+std::string JavaToNativeString(JNIEnv* jni, const JavaRef<jstring>& j_string);
+
+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;
+}
+
+template <typename T, typename Java_T = jobject, typename Convert>
+std::vector<T> JavaListToNativeVector(JNIEnv* env,
+ const JavaRef<jobject>& j_list,
+ Convert convert) {
+ std::vector<T> native_list;
+ if (!j_list.is_null()) {
+ for (ScopedJavaLocalRef<jobject>& j_item : Iterable(env, j_list)) {
+ native_list.emplace_back(
+ convert(env, static_java_ref_cast<Java_T>(env, j_item)));
+ }
+ CHECK_EXCEPTION(env) << "Error during JavaListToNativeVector";
+ }
+ return native_list;
+}
+
+template <typename Key, typename T, typename Convert>
+std::map<Key, T> JavaToNativeMap(JNIEnv* env,
+ const JavaRef<jobject>& j_map,
+ Convert convert) {
+ std::map<Key, T> container;
+ for (auto const& j_entry : GetJavaMapEntrySet(env, j_map)) {
+ container.emplace(convert(env, GetJavaMapEntryKey(env, j_entry),
+ GetJavaMapEntryValue(env, j_entry)));
+ }
+ return container;
+}
+
+// Converts Map<String, String> to std::map<std::string, std::string>.
+std::map<std::string, std::string> JavaToNativeStringMap(
+ JNIEnv* env,
+ const JavaRef<jobject>& j_map);
+
+// --------------------------------------------------------
+// -- Methods for converting native types to Java types. --
+// --------------------------------------------------------
+
+ScopedJavaLocalRef<jobject> NativeToJavaBoolean(JNIEnv* env, bool b);
+ScopedJavaLocalRef<jobject> NativeToJavaDouble(JNIEnv* env, double d);
+ScopedJavaLocalRef<jobject> NativeToJavaInteger(JNIEnv* jni, int32_t i);
+ScopedJavaLocalRef<jobject> NativeToJavaLong(JNIEnv* env, int64_t u);
+ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni, const char* str);
+ScopedJavaLocalRef<jstring> NativeToJavaString(JNIEnv* jni,
+ const std::string& str);
+
+ScopedJavaLocalRef<jobject> NativeToJavaDouble(
+ JNIEnv* jni,
+ const absl::optional<double>& optional_double);
+ScopedJavaLocalRef<jobject> NativeToJavaInteger(
+ JNIEnv* jni,
+ const absl::optional<int32_t>& optional_int);
+ScopedJavaLocalRef<jstring> NativeToJavaString(
+ JNIEnv* jni,
+ const absl::optional<std::string>& str);
+
+// 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<jbyteArray> NativeToJavaByteArray(
+ JNIEnv* env,
+ rtc::ArrayView<int8_t> container);
+ScopedJavaLocalRef<jintArray> NativeToJavaIntArray(
+ JNIEnv* env,
+ rtc::ArrayView<int32_t> container);
+
+std::vector<int8_t> JavaToNativeByteArray(JNIEnv* env,
+ const JavaRef<jbyteArray>& jarray);
+std::vector<int32_t> JavaToNativeIntArray(JNIEnv* env,
+ const JavaRef<jintArray>& jarray);
+
+ScopedJavaLocalRef<jobjectArray> NativeToJavaBooleanArray(
+ JNIEnv* env,
+ const std::vector<bool>& container);
+ScopedJavaLocalRef<jobjectArray> NativeToJavaDoubleArray(
+ JNIEnv* env,
+ const std::vector<double>& container);
+ScopedJavaLocalRef<jobjectArray> NativeToJavaIntegerArray(
+ JNIEnv* env,
+ const std::vector<int32_t>& container);
+ScopedJavaLocalRef<jobjectArray> NativeToJavaLongArray(
+ JNIEnv* env,
+ const std::vector<int64_t>& container);
+ScopedJavaLocalRef<jobjectArray> NativeToJavaStringArray(
+ JNIEnv* env,
+ const std::vector<std::string>& 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) {
+ const auto key_value_pair = convert(env, e);
+ builder.put(key_value_pair.first, key_value_pair.second);
+ }
+ return builder.GetJavaMap();
+}
+
+template <typename C>
+ScopedJavaLocalRef<jobject> NativeToJavaStringMap(JNIEnv* env,
+ const C& container) {
+ JavaMapBuilder builder(env);
+ for (const auto& e : container) {
+ const auto key_value_pair = std::make_pair(
+ NativeToJavaString(env, e.first), NativeToJavaString(env, e.second));
+ builder.put(key_value_pair.first, key_value_pair.second);
+ }
+ return builder.GetJavaMap();
+}
+
+// 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 NativeToJavaPointer(void* ptr);
+
+// ------------------------
+// -- Deprecated methods --
+// ------------------------
+
+// Deprecated. Use JavaToNativeString.
+inline std::string JavaToStdString(JNIEnv* jni,
+ const JavaRef<jstring>& j_string) {
+ return JavaToNativeString(jni, j_string);
+}
+
+// Deprecated. Use scoped jobjects instead.
+inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
+ return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
+}
+
+// Deprecated. Use JavaListToNativeVector<std::string, jstring> instead.
+// 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);
+
+// Deprecated. Use JavaToNativeStringMap instead.
+// Parses Map<String, String> to std::map<std::string, std::string>.
+inline std::map<std::string, std::string> JavaToStdMapStrings(
+ JNIEnv* jni,
+ const JavaRef<jobject>& j_map) {
+ return JavaToNativeStringMap(jni, 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));
+}
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/jni_int_wrapper.h b/third_party/libwebrtc/sdk/android/native_api/jni/jni_int_wrapper.h
new file mode 100644
index 0000000000..23da7f2ce4
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/jni_int_wrapper.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+// Originally this class is from Chromium.
+// https://cs.chromium.org/chromium/src/base/android/jni_int_wrapper.h.
+
+#ifndef SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
+#define SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
+
+// Wrapper used to receive int when calling Java from native. The wrapper
+// disallows automatic conversion of anything besides int32_t to a jint.
+// Checking is only done in debugging builds.
+
+#ifdef NDEBUG
+
+typedef jint JniIntWrapper;
+
+// This inline is sufficiently trivial that it does not change the
+// final code generated by g++.
+inline jint as_jint(JniIntWrapper wrapper) {
+ return wrapper;
+}
+
+#else
+
+class JniIntWrapper {
+ public:
+ JniIntWrapper() : i_(0) {}
+ JniIntWrapper(int32_t i) : i_(i) {} // NOLINT(runtime/explicit)
+ explicit JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {}
+
+ jint as_jint() const { return i_; }
+
+ // If you get an "invokes a deleted function" error at the lines below it is
+ // because you used an implicit conversion to convert e.g. a long to an
+ // int32_t when calling Java. We disallow this. If you want a lossy
+ // conversion, please use an explicit conversion in your C++ code.
+ JniIntWrapper(uint32_t) = delete; // NOLINT(runtime/explicit)
+ JniIntWrapper(uint64_t) = delete; // NOLINT(runtime/explicit)
+ JniIntWrapper(int64_t) = delete; // NOLINT(runtime/explicit)
+
+ private:
+ const jint i_;
+};
+
+inline jint as_jint(const JniIntWrapper& wrapper) {
+ return wrapper.as_jint();
+}
+
+#endif // NDEBUG
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/jvm.cc b/third_party/libwebrtc/sdk/android/native_api/jni/jvm.cc
new file mode 100644
index 0000000000..3356cbeb6f
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/jvm.cc
@@ -0,0 +1,21 @@
+/*
+ * 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/native_api/jni/jvm.h"
+
+#include "sdk/android/src/jni/jvm.h"
+
+namespace webrtc {
+
+JNIEnv* AttachCurrentThreadIfNeeded() {
+ return jni::AttachCurrentThreadIfNeeded();
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/jvm.h b/third_party/libwebrtc/sdk/android/native_api/jni/jvm.h
new file mode 100644
index 0000000000..00bce6734d
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/jvm.h
@@ -0,0 +1,21 @@
+/*
+ * 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_NATIVE_API_JNI_JVM_H_
+#define SDK_ANDROID_NATIVE_API_JNI_JVM_H_
+
+#include <jni.h>
+
+namespace webrtc {
+// Returns a JNI environment usable on this thread.
+JNIEnv* AttachCurrentThreadIfNeeded();
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_JVM_H_
diff --git a/third_party/libwebrtc/sdk/android/native_api/jni/scoped_java_ref.h b/third_party/libwebrtc/sdk/android/native_api/jni/scoped_java_ref.h
new file mode 100644
index 0000000000..a2be447de2
--- /dev/null
+++ b/third_party/libwebrtc/sdk/android/native_api/jni/scoped_java_ref.h
@@ -0,0 +1,226 @@
+/*
+ * 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_NATIVE_API_JNI_SCOPED_JAVA_REF_H_
+#define SDK_ANDROID_NATIVE_API_JNI_SCOPED_JAVA_REF_H_
+
+#include <jni.h>
+
+#include <utility>
+
+#include "sdk/android/native_api/jni/jvm.h"
+
+namespace webrtc {
+
+// 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:
+ JavaRef(const JavaRef&) = delete;
+ JavaRef& operator=(const JavaRef&) = delete;
+
+ 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:
+ constexpr JavaRef() : obj_(nullptr) {}
+ explicit JavaRef(jobject obj) : obj_(obj) {}
+ jobject obj_;
+};
+
+template <typename T>
+class JavaRef : public JavaRef<jobject> {
+ public:
+ JavaRef(const JavaRef&) = delete;
+ JavaRef& operator=(const JavaRef&) = delete;
+
+ T obj() const { return static_cast<T>(obj_); }
+
+ protected:
+ JavaRef() : JavaRef<jobject>(nullptr) {}
+ explicit JavaRef(T obj) : JavaRef<jobject>(obj) {}
+};
+
+// 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) {}
+
+ JavaParamRef(const JavaParamRef&) = delete;
+ JavaParamRef& operator=(const JavaParamRef&) = delete;
+};
+
+// 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() = default;
+ explicit constexpr ScopedJavaGlobalRef(std::nullptr_t) {}
+ 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_);
+ }
+
+ ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete;
+ ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef&) = delete;
+
+ void operator=(const JavaRef<T>& other) {
+ JNIEnv* env = AttachCurrentThreadIfNeeded();
+ if (obj_ != nullptr) {
+ env->DeleteGlobalRef(obj_);
+ }
+ obj_ = other.is_null() ? nullptr : env->NewGlobalRef(other.obj());
+ }
+
+ void operator=(std::nullptr_t) {
+ if (obj_ != nullptr) {
+ AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
+ }
+ obj_ = nullptr;
+ }
+
+ // 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;
+ }
+};
+
+template <typename T>
+inline ScopedJavaLocalRef<T> static_java_ref_cast(JNIEnv* env,
+ JavaRef<jobject> const& ref) {
+ ScopedJavaLocalRef<jobject> owned_ref(env, ref);
+ return ScopedJavaLocalRef<T>(env, static_cast<T>(owned_ref.Release()));
+}
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_SCOPED_JAVA_REF_H_