/**
   * Spawns and connects to a child process. May be called on any thread. It will not block, but
   * will instead callback to {@link #nativeOnChildProcessStarted} when the connection is
   * established. Note this callback will not necessarily be from the same thread (currently it
   * always comes from the main thread).
   *
   * @param context Context used to obtain the application context.
   * @param commandLine The child process command line argv.
   * @param filesToBeMapped File IDs, FDs, offsets, and lengths to pass through.
   * @param clientContext Arbitrary parameter used by the client to distinguish this connection.
   */
  @CalledByNative
  private static void start(
      Context context,
      final String[] commandLine,
      int childProcessId,
      FileDescriptorInfo[] filesToBeMapped,
      long clientContext) {
    assert clientContext != 0;

    int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS;
    boolean inSandbox = true;
    String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE);
    if (SWITCH_RENDERER_PROCESS.equals(processType)) {
      callbackType = CALLBACK_FOR_RENDERER_PROCESS;
    } else if (SWITCH_GPU_PROCESS.equals(processType)) {
      callbackType = CALLBACK_FOR_GPU_PROCESS;
      inSandbox = false;
    } else if (SWITCH_UTILITY_PROCESS.equals(processType)) {
      // We only support sandboxed right now.
      callbackType = CALLBACK_FOR_UTILITY_PROCESS;
    } else {
      assert false;
    }

    startInternal(
        context,
        commandLine,
        childProcessId,
        filesToBeMapped,
        clientContext,
        callbackType,
        inSandbox);
  }