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/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