Refactor native Zygote code.

This patch refactors the native Zygote code in anticipation of future
changes.  Notibly, this allows forking without application specific
information, replaces a lambda that was defined twice with a function,
and cleans up some of the jstring extraction logic.

Bug: 68253328
Test: Built image, flashed phone, and booted
Change-Id: I694994b2062b2839bf0cdf7d4bef366d98fc6eed
Merged-In: I694994b2062b2839bf0cdf7d4bef366d98fc6eed
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 6f400c4..b96b8ec 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -20,7 +20,9 @@
 #include <sys/mount.h>
 #include <linux/fs.h>
 
+#include <functional>
 #include <list>
+#include <optional>
 #include <sstream>
 #include <string>
 
@@ -70,6 +72,8 @@
 
 namespace {
 
+using namespace std::placeholders;
+
 using android::String8;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
@@ -522,12 +526,12 @@
 static FileDescriptorTable* gOpenFdTable = NULL;
 
 static bool FillFileDescriptorVector(JNIEnv* env,
-                                     jintArray java_fds,
+                                     jintArray managed_fds,
                                      std::vector<int>* fds,
                                      std::string* error_msg) {
   CHECK(fds != nullptr);
-  if (java_fds != nullptr) {
-    ScopedIntArrayRO ar(env, java_fds);
+  if (managed_fds != nullptr) {
+    ScopedIntArrayRO ar(env, managed_fds);
     if (ar.get() == nullptr) {
       *error_msg = "Bad fd array";
       return false;
@@ -540,32 +544,138 @@
   return true;
 }
 
-// Utility routine to specialize a zygote child process.
-static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
-                             jint runtime_flags, jobjectArray javaRlimits,
-                             jlong permittedCapabilities, jlong effectiveCapabilities,
-                             jint mount_external, jstring java_se_info, jstring java_se_name,
-                             bool is_system_server, bool is_child_zygote, jstring instructionSet,
-                             jstring dataDir) {
-  std::string error_msg;
+[[noreturn]]
+static void ZygoteFailure(JNIEnv* env,
+                          const char* process_name,
+                          jstring managed_process_name,
+                          const std::string& msg) {
+  std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr;
+  if (managed_process_name != nullptr) {
+    scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name));
+    if (scoped_managed_process_name_ptr->c_str() != nullptr) {
+      process_name = scoped_managed_process_name_ptr->c_str();
+    }
+  }
 
-  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
-      __attribute__ ((noreturn)) {
-    const char* se_name_c_str = nullptr;
-    std::unique_ptr<ScopedUtfChars> se_name;
-    if (java_se_name != nullptr) {
-      se_name.reset(new ScopedUtfChars(env, java_se_name));
-      se_name_c_str = se_name->c_str();
+  const std::string& error_msg =
+      (process_name == nullptr) ? msg : StringPrintf("(%s) %s", process_name, msg.c_str());
+
+  env->FatalError(error_msg.c_str());
+  __builtin_unreachable();
+}
+
+static std::optional<std::string> ExtractJString(JNIEnv* env,
+                                                 const char* process_name,
+                                                 jstring managed_process_name,
+                                                 jstring managed_string) {
+  if (managed_string == nullptr) {
+    return std::optional<std::string>();
+  } else {
+    ScopedUtfChars scoped_string_chars(env, managed_string);
+
+    if (scoped_string_chars.c_str() != nullptr) {
+      return std::optional<std::string>(scoped_string_chars.c_str());
+    } else {
+      ZygoteFailure(env, process_name, managed_process_name, "Failed to extract JString.");
     }
-    if (se_name_c_str == nullptr && is_system_server) {
-      se_name_c_str = "system_server";
+  }
+}
+
+// Utility routine to fork a zygote.
+static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
+                        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore) {
+  SetSignalHandlers();
+
+  // Block SIGCHLD prior to fork.
+  sigset_t sigchld;
+  sigemptyset(&sigchld);
+  sigaddset(&sigchld, SIGCHLD);
+
+  // Curry a failure function.
+  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+                           nullptr, _1);
+
+  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
+  // log, which would result in the logging FDs we close being reopened.
+  // This would cause failures because the FDs are not whitelisted.
+  //
+  // Note that the zygote process is single threaded at this point.
+  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
+    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
+  }
+
+  // Close any logging related FDs before we start evaluating the list of
+  // file descriptors.
+  __android_log_close();
+  stats_log_close();
+
+  // If this is the first fork for this zygote, create the open FD table.  If
+  // it isn't, we just need to check whether the list of open files has changed
+  // (and it shouldn't in the normal case).
+  std::string error_msg;
+  std::vector<int> fds_to_ignore;
+  if (!FillFileDescriptorVector(env, managed_fds_to_ignore, &fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  if (gOpenFdTable == nullptr) {
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
+    if (gOpenFdTable == nullptr) {
+      fail_fn(error_msg);
     }
-    const std::string& error_msg = (se_name_c_str == nullptr)
-        ? msg
-        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
-    env->FatalError(error_msg.c_str());
-    __builtin_unreachable();
-  };
+  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
+
+  pid_t pid = fork();
+
+  if (pid == 0) {
+    // The child process.
+    PreApplicationInit();
+
+    // Clean up any descriptors which must be closed immediately
+    if (!DetachDescriptors(env, managed_fds_to_close, &error_msg)) {
+      fail_fn(error_msg);
+    }
+
+    // Re-open all remaining open file descriptors so that they aren't shared
+    // with the zygote across a fork.
+    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
+      fail_fn(error_msg);
+    }
+
+    // Turn fdsan back on.
+    android_fdsan_set_error_level(fdsan_error_level);
+  }
+
+  // We blocked SIGCHLD prior to a fork, we unblock it here.
+  if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
+    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
+  }
+  return pid;
+}
+
+// Utility routine to specialize a zygote child process.
+static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
+                             jint runtime_flags, jobjectArray rlimits,
+                             jlong permitted_capabilities, jlong effective_capabilities,
+                             jint mount_external, jstring managed_se_info,
+                             jstring managed_nice_name, bool is_system_server,
+                             bool is_child_zygote, jstring managed_instruction_set,
+                             jstring managed_app_data_dir) {
+  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+                           managed_nice_name, _1);
+  auto extract_fn = std::bind(ExtractJString, env, is_system_server ? "system_server" : "zygote",
+                              managed_nice_name, _1);
+
+  auto se_info = extract_fn(managed_se_info);
+  auto nice_name = extract_fn(managed_nice_name);
+  auto instruction_set = extract_fn(managed_instruction_set);
+  auto app_data_dir = extract_fn(managed_app_data_dir);
+
+  std::string error_msg;
 
   // Keep capabilities across UID change, unless we're staying root.
   if (uid != 0) {
@@ -574,26 +684,27 @@
     }
   }
 
-  if (!SetInheritable(permittedCapabilities, &error_msg)) {
+  if (!SetInheritable(permitted_capabilities, &error_msg)) {
     fail_fn(error_msg);
   }
+
   if (!DropCapabilitiesBoundingSet(&error_msg)) {
     fail_fn(error_msg);
   }
 
-  bool use_native_bridge = !is_system_server && (instructionSet != NULL)
-      && android::NativeBridgeAvailable();
-  if (use_native_bridge) {
-    ScopedUtfChars isa_string(env, instructionSet);
-    use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
-  }
-  if (use_native_bridge && dataDir == NULL) {
-    // dataDir should never be null if we need to use a native bridge.
-    // In general, dataDir will never be null for normal applications. It can only happen in
-    // special cases (for isolated processes which are not associated with any app). These are
-    // launched by the framework and should not be emulated anyway.
+  bool use_native_bridge = !is_system_server &&
+                           instruction_set.has_value() &&
+                           android::NativeBridgeAvailable() &&
+                           android::NeedsNativeBridge(instruction_set.value().c_str());
+
+  if (use_native_bridge && !app_data_dir.has_value()) {
+    // The app_data_dir variable should never be empty if we need to use a
+    // native bridge.  In general, app_data_dir will never be empty for normal
+    // applications.  It can only happen in special cases (for isolated
+    // processes which are not associated with any app).  These are launched by
+    // the framework and should not be emulated anyway.
     use_native_bridge = false;
-    ALOGW("Native bridge will not be used because dataDir == NULL.");
+    ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
   }
 
   if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) {
@@ -622,34 +733,33 @@
       }
   }
 
-  if (!SetGids(env, javaGids, &error_msg)) {
+  if (!SetGids(env, gids, &error_msg)) {
     fail_fn(error_msg);
   }
 
-  if (!SetRLimits(env, javaRlimits, &error_msg)) {
+  if (!SetRLimits(env, rlimits, &error_msg)) {
     fail_fn(error_msg);
   }
 
   if (use_native_bridge) {
-    ScopedUtfChars isa_string(env, instructionSet);
-    ScopedUtfChars data_dir(env, dataDir);
-    android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
+    // Due to the logic behind use_native_bridge we know that both app_data_dir
+    // and instruction_set contain values.
+    android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
+                                       instruction_set.value().c_str());
   }
 
-  int rc = setresgid(gid, gid, gid);
-  if (rc == -1) {
+  if (setresgid(gid, gid, gid) == -1) {
     fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
   }
 
-  // Must be called when the new process still has CAP_SYS_ADMIN, in this case, before changing
-  // uid from 0, which clears capabilities.  The other alternative is to call
-  // prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see
-  // b/71859146).  As the result, privileged syscalls used below still need to be accessible in
-  // app process.
+  // Must be called when the new process still has CAP_SYS_ADMIN, in this case,
+  // before changing uid from 0, which clears capabilities.  The other
+  // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that
+  // breaks SELinux domain transition (see b/71859146).  As the result,
+  // privileged syscalls used below still need to be accessible in app process.
   SetUpSeccompFilter(uid);
 
-  rc = setresuid(uid, uid, uid);
-  if (rc == -1) {
+  if (setresuid(uid, uid, uid) == -1) {
     fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
   }
 
@@ -666,6 +776,7 @@
       ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
       RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
   }
+
   if (dumpable == 2 && uid >= AID_APP) {
     if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
       ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
@@ -682,7 +793,7 @@
       }
   }
 
-  if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
+  if (!SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
                        &error_msg)) {
     fail_fn(error_msg);
   }
@@ -691,41 +802,21 @@
     fail_fn(error_msg);
   }
 
-  const char* se_info_c_str = NULL;
-  ScopedUtfChars* se_info = NULL;
-  if (java_se_info != NULL) {
-      se_info = new ScopedUtfChars(env, java_se_info);
-      se_info_c_str = se_info->c_str();
-      if (se_info_c_str == NULL) {
-        fail_fn("se_info_c_str == NULL");
-      }
-  }
-  const char* se_name_c_str = NULL;
-  ScopedUtfChars* se_name = NULL;
-  if (java_se_name != NULL) {
-      se_name = new ScopedUtfChars(env, java_se_name);
-      se_name_c_str = se_name->c_str();
-      if (se_name_c_str == NULL) {
-        fail_fn("se_name_c_str == NULL");
-      }
-  }
-  rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
-  if (rc == -1) {
-    fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
-          is_system_server, se_info_c_str, se_name_c_str));
+  const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
+  const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
+
+  if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
+    fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed",
+                         uid, is_system_server, se_info_ptr, nice_name_ptr));
   }
 
   // Make it easier to debug audit logs by setting the main thread's name to the
   // nice name rather than "app_process".
-  if (se_name_c_str == NULL && is_system_server) {
-    se_name_c_str = "system_server";
+  if (nice_name.has_value()) {
+    SetThreadName(nice_name.value().c_str());
+  } else if (is_system_server) {
+    SetThreadName("system_server");
   }
-  if (se_name_c_str != NULL) {
-    SetThreadName(se_name_c_str);
-  }
-
-  delete se_info;
-  delete se_name;
 
   // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
   UnsetChldSignalHandler();
@@ -743,102 +834,13 @@
   }
 
   env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
-                            is_system_server, is_child_zygote, instructionSet);
+                            is_system_server, is_child_zygote, managed_instruction_set);
+
   if (env->ExceptionCheck()) {
     fail_fn("Error calling post fork hooks.");
   }
 }
 
-// Utility routine to fork zygote and specialize the child process.
-static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server,
-                        jintArray fdsToClose, jintArray fdsToIgnore) {
-  SetSignalHandlers();
-
-  // Block SIGCHLD prior to fork.
-  sigset_t sigchld;
-  sigemptyset(&sigchld);
-  sigaddset(&sigchld, SIGCHLD);
-
-  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
-      __attribute__ ((noreturn)) {
-    const char* se_name_c_str = nullptr;
-    std::unique_ptr<ScopedUtfChars> se_name;
-    if (java_se_name != nullptr) {
-      se_name.reset(new ScopedUtfChars(env, java_se_name));
-      se_name_c_str = se_name->c_str();
-    }
-    if (se_name_c_str == nullptr && is_system_server) {
-      se_name_c_str = "system_server";
-    }
-    const std::string& error_msg = (se_name_c_str == nullptr)
-        ? msg
-        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
-    env->FatalError(error_msg.c_str());
-    __builtin_unreachable();
-  };
-
-  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
-  // log, which would result in the logging FDs we close being reopened.
-  // This would cause failures because the FDs are not whitelisted.
-  //
-  // Note that the zygote process is single threaded at this point.
-  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
-    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
-  }
-
-  // Close any logging related FDs before we start evaluating the list of
-  // file descriptors.
-  __android_log_close();
-  stats_log_close();
-
-  std::string error_msg;
-
-  // If this is the first fork for this zygote, create the open FD table.
-  // If it isn't, we just need to check whether the list of open files has
-  // changed (and it shouldn't in the normal case).
-  std::vector<int> fds_to_ignore;
-  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
-    fail_fn(error_msg);
-  }
-  if (gOpenFdTable == NULL) {
-    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
-    if (gOpenFdTable == NULL) {
-      fail_fn(error_msg);
-    }
-  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
-    fail_fn(error_msg);
-  }
-
-  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();
-
-  pid_t pid = fork();
-
-  if (pid == 0) {
-    // The child process.
-    PreApplicationInit();
-
-    // Clean up any descriptors which must be closed immediately
-    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
-      fail_fn(error_msg);
-    }
-
-    // Re-open all remaining open file descriptors so that they aren't shared
-    // with the zygote across a fork.
-    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
-      fail_fn(error_msg);
-    }
-
-    // Turn fdsan back on.
-    android_fdsan_set_error_level(fdsan_error_level);
-  }
-
-  // We blocked SIGCHLD prior to a fork, we unblock it here.
-  if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
-    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
-  }
-  return pid;
-}
-
 static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) {
     __user_cap_header_struct capheader;
     memset(&capheader, 0, sizeof(capheader));
@@ -851,16 +853,82 @@
         RuntimeAbort(env, __LINE__, "capget failed");
     }
 
-    return capdata[0].effective |
-           (static_cast<uint64_t>(capdata[1].effective) << 32);
+    return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32);
+}
+
+static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids,
+                                   bool is_child_zygote) {
+  jlong capabilities = 0;
+
+  /*
+   *  Grant the following capabilities to the Bluetooth user:
+   *    - CAP_WAKE_ALARM
+   *    - CAP_NET_RAW
+   *    - CAP_NET_BIND_SERVICE (for DHCP client functionality)
+   *    - CAP_SYS_NICE (for setting RT priority for audio-related threads)
+   */
+
+  if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
+    capabilities |= (1LL << CAP_WAKE_ALARM);
+    capabilities |= (1LL << CAP_NET_RAW);
+    capabilities |= (1LL << CAP_NET_BIND_SERVICE);
+    capabilities |= (1LL << CAP_SYS_NICE);
+  }
+
+  /*
+   * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
+   */
+
+  bool gid_wakelock_found = false;
+  if (gid == AID_WAKELOCK) {
+    gid_wakelock_found = true;
+  } else if (gids != nullptr) {
+    jsize gids_num = env->GetArrayLength(gids);
+    ScopedIntArrayRO native_gid_proxy(env, gids);
+
+    if (native_gid_proxy.get() == nullptr) {
+      RuntimeAbort(env, __LINE__, "Bad gids array");
+    }
+
+    for (int gid_index = gids_num; --gids_num >= 0;) {
+      if (native_gid_proxy[gid_index] == AID_WAKELOCK) {
+        gid_wakelock_found = true;
+        break;
+      }
+    }
+  }
+
+  if (gid_wakelock_found) {
+    capabilities |= (1LL << CAP_BLOCK_SUSPEND);
+  }
+
+  /*
+   * Grant child Zygote processes the following capabilities:
+   *   - CAP_SETUID (change UID of child processes)
+   *   - CAP_SETGID (change GID of child processes)
+   *   - CAP_SETPCAP (change capabilities of child processes)
+   */
+
+  if (is_child_zygote) {
+    capabilities |= (1LL << CAP_SETUID);
+    capabilities |= (1LL << CAP_SETGID);
+    capabilities |= (1LL << CAP_SETPCAP);
+  }
+
+  /*
+   * Containers run without some capabilities, so drop any caps that are not
+   * available.
+   */
+
+  return capabilities & GetEffectiveCapabilityMask(env);
 }
 }  // anonymous namespace
 
 namespace android {
 
 static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
-  // security_getenforce is not allowed on app process. Initialize and cache the value before
-  // zygote forks.
+  // security_getenforce is not allowed on app process. Initialize and cache
+  // the value before zygote forks.
   g_is_security_enforced = security_getenforce();
 }
 
@@ -871,76 +939,33 @@
 static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint runtime_flags, jobjectArray rlimits,
-        jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
-        jstring instructionSet, jstring appDataDir) {
-    jlong capabilities = 0;
+        jint mount_external, jstring se_info, jstring nice_name,
+        jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote,
+        jstring instruction_set, jstring app_data_dir) {
+    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
-    // Grant CAP_WAKE_ALARM to the Bluetooth process.
-    // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client.
-    // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for
-    // audio-related threads.
-    // TODO: consider making such functionality an RPC to netd.
-    if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
-      capabilities |= (1LL << CAP_WAKE_ALARM);
-      capabilities |= (1LL << CAP_NET_RAW);
-      capabilities |= (1LL << CAP_NET_BIND_SERVICE);
-      capabilities |= (1LL << CAP_SYS_NICE);
-    }
-
-    // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
-    bool gid_wakelock_found = false;
-    if (gid == AID_WAKELOCK) {
-      gid_wakelock_found = true;
-    } else if (gids != NULL) {
-      jsize gids_num = env->GetArrayLength(gids);
-      ScopedIntArrayRO ar(env, gids);
-      if (ar.get() == NULL) {
-        RuntimeAbort(env, __LINE__, "Bad gids array");
-      }
-      for (int i = 0; i < gids_num; i++) {
-        if (ar[i] == AID_WAKELOCK) {
-          gid_wakelock_found = true;
-          break;
-        }
-      }
-    }
-    if (gid_wakelock_found) {
-      capabilities |= (1LL << CAP_BLOCK_SUSPEND);
-    }
-
-    // If forking a child zygote process, that zygote will need to be able to change
-    // the UID and GID of processes it forks, as well as drop those capabilities.
-    if (is_child_zygote) {
-      capabilities |= (1LL << CAP_SETUID);
-      capabilities |= (1LL << CAP_SETGID);
-      capabilities |= (1LL << CAP_SETPCAP);
-    }
-
-    // Containers run without some capabilities, so drop any caps that are not
-    // available.
-    capabilities &= GetEffectiveCapabilityMask(env);
-
-    pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore);
+    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);
     if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        capabilities, capabilities,
-                       mount_external, se_info, se_name, false,
-                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir);
+                       mount_external, se_info, nice_name, false,
+                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir);
     }
     return pid;
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
         JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
-        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
-        jlong effectiveCapabilities) {
-  pid_t pid = ForkCommon(env, NULL, true, NULL, NULL);
+        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
+        jlong effective_capabilities) {
+  pid_t pid = ForkCommon(env, true,
+                         /* managed_fds_to_close= */ nullptr,
+                         /* managed_fds_to_ignore= */ nullptr);
   if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
-                       permittedCapabilities, effectiveCapabilities,
-                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
-                       false, NULL, NULL);
+                       permitted_capabilities, effective_capabilities,
+                       MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
+                       false, nullptr, nullptr);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -974,7 +999,7 @@
     ScopedUtfChars path_native(env, path);
     const char* path_cstr = path_native.c_str();
     if (!path_cstr) {
-        RuntimeAbort(env, __LINE__, "path_cstr == NULL");
+        RuntimeAbort(env, __LINE__, "path_cstr == nullptr");
     }
     FileDescriptorWhitelist::Get()->Allow(path_cstr);
 }