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_