ART: Change ART for new native bridge sequence

Initialize or unload after a fork.

(cherry picked from commit 6be67eeedbe60afce42300ae3e7f0e7180a96efa)

Change-Id: I5a20de1cb68dd1802937b369b14c50c9c1031c67
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 820bd04..c3b84e3 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -17,8 +17,10 @@
 #include <stdlib.h>
 
 #include "debugger.h"
+#include "instruction_set.h"
 #include "jni_internal.h"
 #include "JNIHelp.h"
+#include "ScopedUtfChars.h"
 #include "thread-inl.h"
 
 #if defined(HAVE_PRCTL)
@@ -101,17 +103,27 @@
   return reinterpret_cast<jlong>(self);
 }
 
-static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags) {
+static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags,
+                                            jstring instruction_set) {
   Thread* thread = reinterpret_cast<Thread*>(token);
   // Our system thread ID, etc, has changed so reset Thread state.
   thread->InitAfterFork();
   EnableDebugFeatures(debug_flags);
-  Runtime::Current()->DidForkFromZygote();
+
+  Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload;
+  if (instruction_set != nullptr) {
+    ScopedUtfChars isa_string(env, instruction_set);
+    InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
+    if (isa != kNone && isa != kRuntimeISA) {
+      action = Runtime::NativeBridgeAction::kInitialize;
+    }
+  }
+  Runtime::Current()->DidForkFromZygote(action);
 }
 
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
-  NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JI)V"),
+  NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JILjava/lang/String;)V"),
 };
 
 void register_dalvik_system_ZygoteHooks(JNIEnv* env) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index c2912be..4f28dda 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -430,7 +430,7 @@
       return false;
     }
   } else {
-    DidForkFromZygote();
+    DidForkFromZygote(NativeBridgeAction::kInitialize);
   }
 
   StartDaemonThreads();
@@ -508,9 +508,19 @@
 #endif
 }
 
-void Runtime::DidForkFromZygote() {
+void Runtime::DidForkFromZygote(NativeBridgeAction action) {
   is_zygote_ = false;
 
+  switch (action) {
+    case NativeBridgeAction::kUnload:
+      android::UnloadNativeBridge();
+      break;
+
+    case NativeBridgeAction::kInitialize:
+      android::InitializeNativeBridge();
+      break;
+  }
+
   // Create the thread pool.
   heap_->CreateThreadPool();
 
@@ -831,8 +841,34 @@
   self->ClearException();
 
   // Look for a native bridge.
+  //
+  // The intended flow here is, in the case of a running system:
+  //
+  // Runtime::Init() (zygote):
+  //   LoadNativeBridge -> dlopen from cmd line parameter.
+  //  |
+  //  V
+  // Runtime::Start() (zygote):
+  //   No-op wrt native bridge.
+  //  |
+  //  | start app
+  //  V
+  // DidForkFromZygote(action)
+  //   action = kUnload -> dlclose native bridge.
+  //   action = kInitialize -> initialize library
+  //
+  //
+  // The intended flow here is, in the case of a simple dalvikvm call:
+  //
+  // Runtime::Init():
+  //   LoadNativeBridge -> dlopen from cmd line parameter.
+  //  |
+  //  V
+  // Runtime::Start():
+  //   DidForkFromZygote(kInitialize) -> try to initialize any native bridge given.
+  //   No-op wrt native bridge.
   native_bridge_library_filename_ = options->native_bridge_library_filename_;
-  android::SetupNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_);
+  android::LoadNativeBridge(native_bridge_library_filename_.c_str(), &native_bridge_art_callbacks_);
   VLOG(startup) << "Runtime::Setup native bridge library: "
                 << (native_bridge_library_filename_.empty() ?
                     "(empty)" : native_bridge_library_filename_);
diff --git a/runtime/runtime.h b/runtime/runtime.h
index db7b476..a868e2c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -387,9 +387,13 @@
 
   void SetStatsEnabled(bool new_state);
 
+  enum class NativeBridgeAction {  // private
+    kUnload,
+    kInitialize
+  };
   void PreZygoteFork();
   bool InitZygote();
-  void DidForkFromZygote();
+  void DidForkFromZygote(NativeBridgeAction action);
 
   const instrumentation::Instrumentation* GetInstrumentation() const {
     return &instrumentation_;
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
index 5b41606..808d968 100644
--- a/test/115-native-bridge/expected.txt
+++ b/test/115-native-bridge/expected.txt
@@ -1,5 +1,5 @@
-Ready for native bridge tests.
 Native bridge initialized.
+Ready for native bridge tests.
 Checking for support.
 Getting trampoline for JNI_OnLoad with shorty (null).
 Test ART callbacks: all JNI function number is 9.