runtime: Initialize native bridge in app-zygote

An app-zygote may be running PreLoad hooks, which may require native-bridged
execution if non-native jni code is involved (testAppZygoteSyscalls needs that).

Test: CtsExternalServiceTestCases
android.externalservice.cts.ExternalServiceTest
testBindExternalServiceWithZygote
Test: CtsSeccompHostTestCases
android.seccomp.cts.SeccompHostJUnit4DeviceTest
testAppZygoteSyscalls
both for Q.sdk_gphone_x86_arm.armeabi-v7a
Bug: 143143718
Bug: 146904103

Change-Id: I53f33183cc3d0bd992344441111a84f4c04533fa
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 8e832b8..482c4ec 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -413,13 +413,6 @@
     std::srand(static_cast<uint32_t>(NanoTime()));
   }
 
-  if (is_zygote) {
-    // If creating a child-zygote, do not call into the runtime's post-fork logic.
-    // Doing so would spin up threads for Binder and JDWP. Instead, the Java side
-    // of the child process will call a static main in a class specified by the parent.
-    return;
-  }
-
   if (instruction_set != nullptr && !is_system_server) {
     ScopedUtfChars isa_string(env, instruction_set);
     InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
@@ -427,11 +420,12 @@
     if (isa != InstructionSet::kNone && isa != kRuntimeISA) {
       action = Runtime::NativeBridgeAction::kInitialize;
     }
-    runtime->InitNonZygoteOrPostFork(env, is_system_server, action, isa_string.c_str());
+    runtime->InitNonZygoteOrPostFork(env, is_system_server, is_zygote, action, isa_string.c_str());
   } else {
     runtime->InitNonZygoteOrPostFork(
         env,
         is_system_server,
+        is_zygote,
         Runtime::NativeBridgeAction::kUnload,
         /*isa=*/ nullptr,
         profile_system_server);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 32de85a..0dc93c3 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -935,6 +935,7 @@
         : NativeBridgeAction::kUnload;
     InitNonZygoteOrPostFork(self->GetJniEnv(),
                             /* is_system_server= */ false,
+                            /* is_child_zygote= */ false,
                             action,
                             GetInstructionSetString(kRuntimeISA));
   }
@@ -999,11 +1000,13 @@
 void Runtime::InitNonZygoteOrPostFork(
     JNIEnv* env,
     bool is_system_server,
+    // This is true when we are initializing a child-zygote. It requires
+    // native bridge initialization to be able to run guest native code in
+    // doPreload().
+    bool is_child_zygote,
     NativeBridgeAction action,
     const char* isa,
     bool profile_system_server) {
-  DCHECK(!IsZygote());
-
   if (is_native_bridge_loaded_) {
     switch (action) {
       case NativeBridgeAction::kUnload:
@@ -1016,6 +1019,16 @@
     }
   }
 
+  if (is_child_zygote) {
+    // If creating a child-zygote we only initialize native bridge. The rest of
+    // runtime post-fork logic would spin up threads for Binder and JDWP.
+    // Instead, the Java side of the child process will call a static main in a
+    // class specified by the parent.
+    return;
+  }
+
+  DCHECK(!IsZygote());
+
   if (is_system_server && profile_system_server) {
     // Set the system server package name to "android".
     // This is used to tell the difference between samples provided by system server
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fd09dfb..61ca874 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -511,6 +511,7 @@
   void InitNonZygoteOrPostFork(
       JNIEnv* env,
       bool is_system_server,
+      bool is_child_zygote,
       NativeBridgeAction action,
       const char* isa,
       bool profile_system_server = false);