/** 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; } }
/** * 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); } } } }