Whether or not the application should remain running at all times — “true” if it should, and “false” if not. The default value is “false”. Applications should not normally set this flag; persistence mode is intended only for certain system applications.
synchronized (this) { // Only start up encryption-aware persistent apps; once user is // unlocked we'll come back around and start unaware apps // 正是在这里,phone进程被创建 startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE); // Start up initial activity. mBooting = true; // Enable home activity for system user, so that the system can always boot if (UserManager.isSplitSystemUser()) { ComponentNamecName=newComponentName(mContext, SystemUserHomeActivity.class); try { AppGlobals.getPackageManager().setComponentEnabledSetting(cName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, UserHandle.USER_SYSTEM); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } startHomeActivityLocked(currentUserId, "systemReady"); }
if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { app.persistent = true; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. booleanisActivityProcess= (entryPoint == null); // 进程入口为ActivityThread if (entryPoint == null) entryPoint = "android.app.ActivityThread";
privatestatic ProcessStartResult startViaZygote(final String processClass, final String niceName, finalint uid, finalint gid, finalint[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, int category, int accessInfo, String abi, String instructionSet, String appDataDir, boolean mountKnoxPoint, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { ArrayList<String> argsForZygote = newArrayList<String>();
// --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); .... if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } .... argsForZygote.add(processClass);
if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } }
//发送消息到zygote的socket端口,请求创建新的进程 if (Zygote.isEnhancedZygoteASLREnabled) { .... return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); // End of isEnhancedZygoteASLREnabled case } else { // Original case return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } }
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(). returntrue; } 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); } }
privatevoidhandleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws Zygote.MethodAndArgsCaller { /** * By the time we get here, the native code has closed the two actual Zygote * socket connections, and substituted /dev/null in their place. The LocalSocket * objects still need to be closed properly. */ closeSocket(); if (descriptors != null) { try { Os.dup2(descriptors[0], STDIN_FILENO); Os.dup2(descriptors[1], STDOUT_FILENO); Os.dup2(descriptors[2], STDERR_FILENO);
protectedstaticvoidapplicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws Zygote.MethodAndArgsCaller { // If the application calls System.exit(), terminate the process // immediately without running any shutdown hooks. It is not possible to // shutdown an Android application gracefully. Among other things, the // Android runtime shutdown hooks close the Binder driver, which can cause // leftover running threads to crash before the process actually exits. nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args; try { args = newArguments(argv); } catch (IllegalArgumentException ex) { Slog.e(TAG, ex.getMessage()); // let the process exit return; } // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs, classLoader); }
try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { thrownewRuntimeException( "Missing class when invoking static main " + className, ex); }
Method m; try { m = cl.getMethod("main", newClass[] { String[].class }); } catch (NoSuchMethodException ex) { thrownewRuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { thrownewRuntimeException( "Problem getting static main on " + className, ex); }
intmodifiers= m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { thrownewRuntimeException( "Main method is not public and static on " + className); }
/* * This throw gets caught in ZygoteInit.main(), which responds * by invoking the exception's run() method. This arrangement * clears up all the stack frames that were required in setting * up the process. */ thrownewZygote.MethodAndArgsCaller(m, argv); }
// CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore EventLogger.setReporter(newEventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates finalFileconfigDir= Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir);