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}
diff --git a/sdk/android/native_api/base/init.cc b/sdk/android/native_api/base/init.cc
new file mode 100644
index 0000000..176aa89
--- /dev/null
+++ b/sdk/android/native_api/base/init.cc
@@ -0,0 +1,24 @@
+/*
+ * 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/base/init.h"
+
+#include "rtc_base/checks.h"
+#include "sdk/android/native_api/jni/class_loader.h"
+#include "sdk/android/src/jni/jni_helpers.h"
+
+namespace webrtc {
+
+void InitAndroid(JavaVM* jvm) {
+ RTC_CHECK_GE(jni::InitGlobalJniVariables(jvm), 0);
+ InitClassLoader(jni::GetEnv());
+}
+
+} // namespace webrtc
diff --git a/sdk/android/native_api/base/init.h b/sdk/android/native_api/base/init.h
new file mode 100644
index 0000000..d6a0ec1
--- /dev/null
+++ b/sdk/android/native_api/base/init.h
@@ -0,0 +1,23 @@
+/*
+ * 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_BASE_INIT_H_
+#define SDK_ANDROID_NATIVE_API_BASE_INIT_H_
+
+#include <jni.h>
+
+namespace webrtc {
+
+// Initializes global state needed by WebRTC Android NDK.
+void InitAndroid(JavaVM* jvm);
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_BASE_INIT_H_
diff --git a/sdk/android/native_api/codecs/wrapper.cc b/sdk/android/native_api/codecs/wrapper.cc
new file mode 100644
index 0000000..d7ff44d
--- /dev/null
+++ b/sdk/android/native_api/codecs/wrapper.cc
@@ -0,0 +1,33 @@
+/*
+ * 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/codecs/wrapper.h"
+
+#include "rtc_base/ptr_util.h"
+#include "sdk/android/src/jni/videodecoderfactorywrapper.h"
+#include "sdk/android/src/jni/videoencoderfactorywrapper.h"
+
+namespace webrtc {
+
+std::unique_ptr<VideoDecoderFactory> JavaToNativeVideoDecoderFactory(
+ JNIEnv* jni,
+ jobject decoder_factory) {
+ return rtc::MakeUnique<jni::VideoDecoderFactoryWrapper>(
+ jni, JavaParamRef<jobject>(decoder_factory));
+}
+
+std::unique_ptr<VideoEncoderFactory> JavaToNativeVideoEncoderFactory(
+ JNIEnv* jni,
+ jobject en) {
+ return rtc::MakeUnique<jni::VideoEncoderFactoryWrapper>(
+ jni, JavaParamRef<jobject>(en));
+}
+
+} // namespace webrtc
diff --git a/sdk/android/native_api/codecs/wrapper.h b/sdk/android/native_api/codecs/wrapper.h
new file mode 100644
index 0000000..b13f270
--- /dev/null
+++ b/sdk/android/native_api/codecs/wrapper.h
@@ -0,0 +1,36 @@
+/*
+ * 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_CODECS_WRAPPER_H_
+#define SDK_ANDROID_NATIVE_API_CODECS_WRAPPER_H_
+
+#include <jni.h>
+#include <memory>
+
+#include "api/video_codecs/video_decoder_factory.h"
+#include "api/video_codecs/video_encoder_factory.h"
+
+namespace webrtc {
+
+// Creates an instance of webrtc::VideoDecoderFactory from Java
+// VideoDecoderFactory.
+std::unique_ptr<VideoDecoderFactory> JavaToNativeVideoDecoderFactory(
+ JNIEnv* jni,
+ jobject decoder_factory);
+
+// Creates an instance of webrtc::VideoEncoderFactory from Java
+// VideoEncoderFactory.
+std::unique_ptr<VideoEncoderFactory> JavaToNativeVideoEncoderFactory(
+ JNIEnv* jni,
+ jobject encoder_factory);
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_CODECS_WRAPPER_H_
diff --git a/sdk/android/native_api/jni/class_loader.cc b/sdk/android/native_api/jni/class_loader.cc
new file mode 100644
index 0000000..0b5a87f
--- /dev/null
+++ b/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/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_(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/sdk/android/native_api/jni/class_loader.h b/sdk/android/native_api/jni/class_loader.h
new file mode 100644
index 0000000..2d102fe
--- /dev/null
+++ b/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/sdk/android/native_api/jni/java_types.cc b/sdk/android/native_api/jni/java_types.cc
new file mode 100644
index 0000000..74d1ddb
--- /dev/null
+++ b/sdk/android/native_api/jni/java_types.cc
@@ -0,0 +1,259 @@
+/*
+ * 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 <string>
+#include <utility>
+
+#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/generated_native_api_jni/jni/JniHelper_jni.h"
+
+namespace webrtc {
+
+bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj) {
+ return jni->IsSameObject(obj.obj(), nullptr);
+}
+
+// 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;
+}
+
+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 webrtc
diff --git a/sdk/android/native_api/jni/java_types.h b/sdk/android/native_api/jni/java_types.h
new file mode 100644
index 0000000..bd9e700
--- /dev/null
+++ b/sdk/android/native_api/jni/java_types.h
@@ -0,0 +1,253 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#include "api/optional.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/thread_checker.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 {
+
+// Returns true if |obj| == null in Java.
+bool IsNull(JNIEnv* jni, const JavaRef<jobject>& obj);
+
+// 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);
+
+// 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) {
+ const auto key_value_pair = convert(env, e);
+ builder.put(key_value_pair.first, key_value_pair.second);
+ }
+ return builder.GetJavaMap();
+}
+
+} // namespace webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_JAVA_TYPES_H_
diff --git a/sdk/android/native_api/jni/jvm.cc b/sdk/android/native_api/jni/jvm.cc
new file mode 100644
index 0000000..3356cbe
--- /dev/null
+++ b/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/sdk/android/native_api/jni/jvm.h b/sdk/android/native_api/jni/jvm.h
new file mode 100644
index 0000000..00bce67
--- /dev/null
+++ b/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/sdk/android/native_api/jni/scoped_java_ref.h b/sdk/android/native_api/jni/scoped_java_ref.h
new file mode 100644
index 0000000..e3259f1
--- /dev/null
+++ b/sdk/android/native_api/jni/scoped_java_ref.h
@@ -0,0 +1,202 @@
+/*
+ * 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 "rtc_base/constructormagic.h"
+#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:
+ 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 webrtc
+
+#endif // SDK_ANDROID_NATIVE_API_JNI_SCOPED_JAVA_REF_H_