Add back the work-arounds for broken apps that assume JNI uses direct references.

Note that we'll need to add support for this to jni_compiler too.

Change-Id: I7e31ab4314ba913cde4629544addd0aad9a89b3b
diff --git a/src/scoped_jni_thread_state.h b/src/scoped_jni_thread_state.h
new file mode 100644
index 0000000..dd39cc3
--- /dev/null
+++ b/src/scoped_jni_thread_state.h
@@ -0,0 +1,55 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: enh@google.com (Elliott Hughes)
+
+#include "jni_internal.h"
+
+namespace art {
+
+// Entry/exit processing for all JNI calls.
+//
+// This performs the necessary thread state switching, lets us amortize the
+// cost of working out the current thread, and lets us check (and repair) apps
+// that are using a JNIEnv on the wrong thread.
+class ScopedJniThreadState {
+ public:
+  explicit ScopedJniThreadState(JNIEnv* env)
+      : env_(reinterpret_cast<JNIEnvExt*>(env)) {
+    self_ = ThreadForEnv(env);
+    self_->SetState(Thread::kRunnable);
+  }
+
+  ~ScopedJniThreadState() {
+    self_->SetState(Thread::kNative);
+  }
+
+  JNIEnvExt* Env() {
+    return env_;
+  }
+
+  Thread* Self() {
+    return self_;
+  }
+
+  JavaVMExt* Vm() {
+    return env_->vm;
+  }
+
+ private:
+  static Thread* ThreadForEnv(JNIEnv* env) {
+    JNIEnvExt* full_env(reinterpret_cast<JNIEnvExt*>(env));
+    Thread* env_self = full_env->self;
+    Thread* self = full_env->work_around_app_jni_bugs ? Thread::Current() : env_self;
+    if (self != env_self) {
+      LOG(ERROR) << "JNI ERROR: JNIEnv for " << *env_self
+                 << " used on " << *self;
+      // TODO: dump stack
+    }
+    return self;
+  }
+
+  JNIEnvExt* env_;
+  Thread* self_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedJniThreadState);
+};
+
+}  // namespace art