/** Finish remaining work for the newly forked system server process. */
  private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {

    closeServerSocket();

    // set umask to 0077 so new files and directories will default to owner-only permissions.
    FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);

    if (parsedArgs.niceName != null) {
      Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.invokeWith != null) {
      WrapperInit.execApplication(
          parsedArgs.invokeWith,
          parsedArgs.niceName,
          parsedArgs.targetSdkVersion,
          null,
          parsedArgs.remainingArgs);
    } else {
      /*
       * Pass the remaining arguments to SystemServer.
       */
      RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
    }

    /* should never reach here */
  }
  /** Finish remaining work for the newly forked system server process. */
  private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {

    closeServerSocket();

    // set umask to 0077 so new files and directories will default to owner-only permissions.
    Os.umask(S_IRWXG | S_IRWXO);

    if (parsedArgs.niceName != null) {
      Process.setArgV0(parsedArgs.niceName);
    }

    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    if (systemServerClasspath != null) {
      performSystemServerDexOpt(systemServerClasspath);
    }

    if (parsedArgs.invokeWith != null) {
      String[] args = parsedArgs.remainingArgs;
      // If we have a non-null system server class path, we'll have to duplicate the
      // existing arguments and append the classpath to it. ART will handle the classpath
      // correctly when we exec a new process.
      if (systemServerClasspath != null) {
        String[] amendedArgs = new String[args.length + 2];
        amendedArgs[0] = "-cp";
        amendedArgs[1] = systemServerClasspath;
        System.arraycopy(
            parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
      }

      WrapperInit.execApplication(
          parsedArgs.invokeWith,
          parsedArgs.niceName,
          parsedArgs.targetSdkVersion,
          VMRuntime.getCurrentInstructionSet(),
          null,
          args);
    } else {
      ClassLoader cl = null;
      if (systemServerClasspath != null) {
        cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
        Thread.currentThread().setContextClassLoader(cl);
      }

      /*
       * Pass the remaining arguments to SystemServer.
       */
      RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }

    /* should never reach here */
  }
  /** Finish remaining work for the newly forked system server process. */
  private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
      throws ZygoteInit.MethodAndArgsCaller {
    /*
     * First, set the capabilities if necessary
     */

    if (parsedArgs.uid != 0) {
      try {
        setCapabilities(parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities);
      } catch (IOException ex) {
        Log.e(TAG, "Error setting capabilities", ex);
      }
    }

    closeServerSocket();

    /*
     * Pass the remaining arguments to SystemServer.
     * "--nice-name=system_server com.android.server.SystemServer"
     */
    RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
    /* should never reach here */
  }
  public static void main(String argv[]) {
    try {
      Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
      RuntimeInit.enableDdms();
      // Start profiling the zygote initialization.
      SamplingProfilerIntegration.start();

      boolean startSystemServer = false;
      String socketName = "zygote";
      String abiList = null;
      for (int i = 1; i < argv.length; i++) {
        if ("start-system-server".equals(argv[i])) {
          startSystemServer = true;
        } else if (argv[i].startsWith(ABI_LIST_ARG)) {
          abiList = argv[i].substring(ABI_LIST_ARG.length());
        } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
          socketName = argv[i].substring(SOCKET_NAME_ARG.length());
        } else {
          throw new RuntimeException("Unknown command line argument: " + argv[i]);
        }
      }

      if (abiList == null) {
        throw new RuntimeException("No ABI list supplied.");
      }

      registerZygoteSocket(socketName);
      Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
      EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
      preload();
      EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
      Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

      // Finish profiling the zygote initialization.
      SamplingProfilerIntegration.writeZygoteSnapshot();

      // Do an initial gc to clean up after startup
      Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
      gcAndFinalize();
      Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

      Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

      // Disable tracing so that forked processes do not inherit stale tracing tags from
      // Zygote.
      Trace.setTracingEnabled(false);

      if (startSystemServer) {
        startSystemServer(abiList, socketName);
      }

      Log.i(TAG, "Accepting command socket connections");
      runSelectLoop(abiList);

      closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
      caller.run();
    } catch (RuntimeException ex) {
      Log.e(TAG, "Zygote died with exception", ex);
      closeServerSocket();
      throw ex;
    }
  }
예제 #5
0
  /**
   * Handles post-fork setup of child proc, closing sockets as appropriate, reopen stdio as
   * appropriate, and ultimately throwing MethodAndArgsCaller if successful or returning if failed.
   *
   * @param parsedArgs non-null; zygote args
   * @param descriptors null-ok; new file descriptors for stdio if available.
   * @param pipeFd null-ok; pipe for communication back to Zygote.
   * @param newStderr null-ok; stream to use for stderr until stdio is reopened.
   * @throws ZygoteInit.MethodAndArgsCaller on success to trampoline to code that invokes static
   *     main.
   */
  private void handleChildProc(
      Arguments parsedArgs,
      FileDescriptor[] descriptors,
      FileDescriptor pipeFd,
      PrintStream newStderr)
      throws ZygoteInit.MethodAndArgsCaller {

    /*
     * Close the socket, unless we're in "peer wait" mode, in which
     * case it's used to track the liveness of this process.
     */

    if (parsedArgs.peerWait) {
      try {
        ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true);
        sPeerWaitSocket = mSocket;
      } catch (IOException ex) {
        Log.e(TAG, "Zygote Child: error setting peer wait " + "socket to be close-on-exec", ex);
      }
    } else {
      closeSocket();
      ZygoteInit.closeServerSocket();
    }

    if (descriptors != null) {
      try {
        ZygoteInit.reopenStdio(descriptors[0], descriptors[1], descriptors[2]);

        for (FileDescriptor fd : descriptors) {
          IoUtils.closeQuietly(fd);
        }
        newStderr = System.err;
      } catch (IOException ex) {
        Log.e(TAG, "Error reopening stdio", ex);
      }
    }

    if (parsedArgs.niceName != null) {
      Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.runtimeInit) {
      if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(
            parsedArgs.invokeWith,
            parsedArgs.niceName,
            parsedArgs.targetSdkVersion,
            pipeFd,
            parsedArgs.remainingArgs);
      } else {
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
      }
    } else {
      String className;
      try {
        className = parsedArgs.remainingArgs[0];
      } catch (ArrayIndexOutOfBoundsException ex) {
        logAndPrintError(newStderr, "Missing required class name argument", null);
        return;
      }

      String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
      System.arraycopy(parsedArgs.remainingArgs, 1, mainArgs, 0, mainArgs.length);

      if (parsedArgs.invokeWith != null) {
        WrapperInit.execStandalone(
            parsedArgs.invokeWith, parsedArgs.classpath, className, mainArgs);
      } else {
        ClassLoader cloader;
        if (parsedArgs.classpath != null) {
          cloader = new PathClassLoader(parsedArgs.classpath, ClassLoader.getSystemClassLoader());
        } else {
          cloader = ClassLoader.getSystemClassLoader();
        }

        try {
          ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
        } catch (RuntimeException ex) {
          logAndPrintError(newStderr, "Error starting.", ex);
        }
      }
    }
  }