/** Prepare the arguments and fork for the system server process. */
  private static boolean startSystemServer(String abiList, String socketName)
      throws MethodAndArgsCaller, RuntimeException {
    long capabilities =
        posixCapabilitiesAsBits(
            OsConstants.CAP_BLOCK_SUSPEND,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG);
    /* Hardcoded command line to start the system server */
    String args[] = {
      "--setuid=1000",
      "--setgid=1000",
      "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009",
      "--capabilities=" + capabilities + "," + capabilities,
      "--nice-name=system_server",
      "--runtime-args",
      "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
      parsedArgs = new ZygoteConnection.Arguments(args);
      ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
      ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

      /* Request to fork the system server process */
      pid =
          Zygote.forkSystemServer(
              parsedArgs.uid,
              parsedArgs.gid,
              parsedArgs.gids,
              parsedArgs.debugFlags,
              null,
              parsedArgs.permittedCapabilities,
              parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
      throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
      if (hasSecondZygote(abiList)) {
        waitForSecondaryZygote(socketName);
      }

      handleSystemServerProcess(parsedArgs);
    }

    return true;
  }
  /** Prepare the arguments and fork for the system server process. */
  private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException {
    /* Hardcoded command line to start the system server */
    String args[] = {
      "--setuid=1000",
      "--setgid=1000",
      "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
      "--capabilities=130104352,130104352",
      "--runtime-init",
      "--nice-name=system_server",
      "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
      parsedArgs = new ZygoteConnection.Arguments(args);
      ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
      ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

      /* Request to fork the system server process */
      pid =
          Zygote.forkSystemServer(
              parsedArgs.uid,
              parsedArgs.gid,
              parsedArgs.gids,
              parsedArgs.debugFlags,
              null,
              parsedArgs.permittedCapabilities,
              parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
      throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
      handleSystemServerProcess(parsedArgs);
    }

    return true;
  }
  /**
   * Reads one start command from the command socket. If successful, a child is forked and a {@link
   * ZygoteInit.MethodAndArgsCaller} exception is thrown in that child while in the parent process,
   * the method returns normally. On failure, the child is not spawned and messages are printed to
   * the log and stderr. Returns a boolean status value indicating whether an end-of-file on the
   * command socket has been encountered.
   *
   * @return false if command socket should continue to be read from, or true if an end-of-file has
   *     been encountered.
   * @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main() method in child process
   */
  boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
      args = readArgumentList();
      descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
      Log.w(TAG, "IOException on command socket " + ex.getMessage());
      closeSocket();
      return true;
    }

    if (args == null) {
      // EOF reached.
      closeSocket();
      return true;
    }

    /** the stderr of the most recent request, if avail */
    PrintStream newStderr = null;

    if (descriptors != null && descriptors.length >= 3) {
      newStderr = new PrintStream(new FileOutputStream(descriptors[2]));
    }

    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;

    try {
      parsedArgs = new Arguments(args);

      applyUidSecurityPolicy(parsedArgs, peer);
      applyRlimitSecurityPolicy(parsedArgs, peer);
      applyCapabilitiesSecurityPolicy(parsedArgs, peer);
      applyInvokeWithSecurityPolicy(parsedArgs, peer);

      applyDebuggerSystemProperty(parsedArgs);
      applyInvokeWithSystemProperty(parsedArgs);

      int[][] rlimits = null;

      if (parsedArgs.rlimits != null) {
        rlimits = parsedArgs.rlimits.toArray(intArray2d);
      }

      if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
        FileDescriptor[] pipeFds = Libcore.os.pipe();
        childPipeFd = pipeFds[1];
        serverPipeFd = pipeFds[0];
        ZygoteInit.setCloseOnExec(serverPipeFd, true);
      }

      pid =
          Zygote.forkAndSpecialize(
              parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits);
    } catch (IOException ex) {
      logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (ErrnoException ex) {
      logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (IllegalArgumentException ex) {
      logAndPrintError(newStderr, "Invalid zygote arguments", ex);
    } catch (ZygoteSecurityException ex) {
      logAndPrintError(newStderr, "Zygote security policy prevents request: ", ex);
    }

    try {
      if (pid == 0) {
        // in child
        IoUtils.closeQuietly(serverPipeFd);
        serverPipeFd = null;
        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

        // should never get here, the child is expected to either
        // throw ZygoteInit.MethodAndArgsCaller or exec().
        return true;
      } else {
        // in parent...pid of < 0 means failure
        IoUtils.closeQuietly(childPipeFd);
        childPipeFd = null;
        return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
      }
    } finally {
      IoUtils.closeQuietly(childPipeFd);
      IoUtils.closeQuietly(serverPipeFd);
    }
  }