/**
   * 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 fileIds The ID that should be used when mapping files in the created process.
   * @param fileFds The file descriptors that should be mapped in the created process.
   * @param fileAutoClose Whether the file descriptors should be closed once they were passed to the
   *     created process.
   * @param clientContext Arbitrary parameter used by the client to distinguish this connection.
   */
  @CalledByNative
  static void start(
      Context context,
      final String[] commandLine,
      int childProcessId,
      int[] fileIds,
      int[] fileFds,
      boolean[] fileAutoClose,
      long clientContext) {
    TraceEvent.begin();
    assert fileIds.length == fileFds.length && fileFds.length == fileAutoClose.length;
    FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[fileFds.length];
    for (int i = 0; i < fileFds.length; i++) {
      filesToBeMapped[i] = new FileDescriptorInfo(fileIds[i], fileFds[i], fileAutoClose[i]);
    }
    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;
    } else if (SWITCH_PPAPI_BROKER_PROCESS.equals(processType)) {
      inSandbox = false;
    }

    ChildProcessConnection allocatedConnection = null;
    synchronized (ChildProcessLauncher.class) {
      if (inSandbox) {
        allocatedConnection = sSpareSandboxedConnection;
        sSpareSandboxedConnection = null;
      }
    }
    if (allocatedConnection == null) {
      allocatedConnection = allocateBoundConnection(context, commandLine, inSandbox);
      if (allocatedConnection == null) {
        // Notify the native code so it can free the heap allocated callback.
        nativeOnChildProcessStarted(clientContext, 0);
        Log.e(TAG, "Allocation of new service failed.");
        TraceEvent.end();
        return;
      }
    }

    Log.d(TAG, "Setting up connection to process: slot=" + allocatedConnection.getServiceNumber());
    triggerConnectionSetup(
        allocatedConnection,
        commandLine,
        childProcessId,
        filesToBeMapped,
        callbackType,
        clientContext);
    TraceEvent.end();
  }
예제 #2
0
  private static void startInternal(
      Context context,
      final String[] commandLine,
      int childProcessId,
      FileDescriptorInfo[] filesToBeMapped,
      long clientContext,
      int callbackType,
      boolean inSandbox) {
    try {
      TraceEvent.begin("ChildProcessLauncher.startInternal");

      ChildProcessConnection allocatedConnection = null;
      synchronized (ChildProcessLauncher.class) {
        if (inSandbox) {
          allocatedConnection = sSpareSandboxedConnection;
          sSpareSandboxedConnection = null;
        }
      }
      if (allocatedConnection == null) {
        boolean alwaysInForeground = false;
        if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true;
        allocatedConnection =
            allocateBoundConnection(context, commandLine, inSandbox, alwaysInForeground);
        if (allocatedConnection == null) {
          Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn.");
          sPendingSpawnQueue.enqueue(
              new PendingSpawnData(
                  context,
                  commandLine,
                  childProcessId,
                  filesToBeMapped,
                  clientContext,
                  callbackType,
                  inSandbox));
          return;
        }
      }

      Log.d(
          TAG, "Setting up connection to process: slot=" + allocatedConnection.getServiceNumber());
      triggerConnectionSetup(
          allocatedConnection,
          commandLine,
          childProcessId,
          filesToBeMapped,
          callbackType,
          clientContext);
    } finally {
      TraceEvent.end("ChildProcessLauncher.startInternal");
    }
  }