ActivityManagerService之深入理解Activity启动流程(三)

    技术2023-04-13  104

    由于排版原因文章下面的部分承接ActivityManagerService之深入理解Activity启动流程(二)

    二、第二阶段 应用进程创建

       2.1.1 AMS startProcessLocked

    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType, hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); } final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; if (!isolated) { //根据processName和uid寻找是否已经存在ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge); checkTime(startTime, "startProcess: after getProcessRecord"); if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { // If we are in the background, then check to see if this process // is bad. If so, we will just silently fail. //如果是后台进程并且启动的是奔溃的进程 if (mAppErrors.isBadProcessLocked(info)) { if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid + "/" + info.processName); return null; } } else { // When the user is explicitly starting a process, then clear its // crash count so that we won't make it bad until they see at // least one crash dialog again, and make the process good again // if it had been bad. if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid + "/" + info.processName); mAppErrors.resetProcessCrashTimeLocked(info); if (mAppErrors.isBadProcessLocked(info)) { EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, UserHandle.getUserId(info.uid), info.uid, info.processName); mAppErrors.clearBadProcessLocked(info); if (app != null) { app.bad = false; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; } // We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName + " app=" + app + " knownToBeDead=" + knownToBeDead + " thread=" + (app != null ? app.thread : null) + " pid=" + (app != null ? app.pid : -1)); if (app != null && app.pid > 0) { if ((!knownToBeDead && !app.killed) || app.thread == null) { // We already have the app running, or are waiting for it to // come up (we have a pid but not yet its thread), so keep it. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app); // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: done, added package to proc"); return app; } // An application record is attached to a previous process, // clean it up now. if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app); checkTime(startTime, "startProcess: bad proc running, killing"); killProcessGroup(app.uid, app.pid);//杀死进程 handleAppDiedLocked(app, true, true); checkTime(startTime, "startProcess: done killing old proc"); } String hostingNameStr = hostingName != null ? hostingName.flattenToShortString() : null; if (app == null) { checkTime(startTime, "startProcess: creating new process record"); //创建一个ProcessRecord,并保存到mProcessNames中。注意,此时还没有创建实际进程 app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); return null; } app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; checkTime(startTime, "startProcess: done creating new process record"); } else { // If this is a new package in the process, add the package to the list app.addPackage(info.packageName, info.versionCode, mProcessStats); checkTime(startTime, "startProcess: added package to existing proc"); } // If the system is not ready yet, then hold off on starting this // process until it is. if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "System not ready, putting on hold: " + app); checkTime(startTime, "startProcess: returning with proc on hold"); return app; } checkTime(startTime, "startProcess: stepping in to startProcess"); //②调用另外一个startProcessLocked函数 startProcessLocked(app, hostingType, hostingNameStr, abiOverride); checkTime(startTime, "startProcess: done starting proc!"); return (app.pid != 0) ? app : null; }

    2.1.2 AMS startProcessLocked

    private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride) { long startTime = SystemClock.elapsedRealtime(); if (app.pid > 0 && app.pid != MY_PID) { checkTime(startTime, "startProcess: removing from pids map"); synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid);//移除app.pid的进程 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } checkTime(startTime, "startProcess: done removing from pids map"); app.setPid(0);//初始化pid值0 } if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES, "startProcessLocked removing on hold: " + app); mProcessesOnHold.remove(app); //mProcessesOnHold用于保存那些在系统还没有准备好就提前请求启动的ProcessRecord checkTime(startTime, "startProcess: starting to update cpu stats"); updateCpuStats();//更新cpu状态 checkTime(startTime, "startProcess: done updating cpu stats"); try { try { final int userId = UserHandle.getUserId(app.uid); AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } /// M: onStartProcess @{ mAmsExt.onStartProcess(hostingType, app.info.packageName); /// M: onStartProcess @} int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { int[] permGids = null; try { checkTime(startTime, "startProcess: getting gids from package manager"); final IPackageManager pm = AppGlobals.getPackageManager(); //从PKMS中查询该进程所属的gid permGids = pm.getPackageGids(app.info.packageName, MATCH_DEBUG_TRIAGED_MISSING, app.userId); StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); mountExternal = storageManagerInternal.getExternalStorageMountMode(uid, app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } /* * Add shared application and profile GIDs so applications can share some * resources like shared libraries and access user-wide resources */ if (ArrayUtils.isEmpty(permGids)) { gids = new int[3]; } else { gids = new int[permGids.length + 3]; System.arraycopy(permGids, 0, gids, 3, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid)); gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); // Replace any invalid GIDs if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2]; if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2]; } checkTime(startTime, "startProcess: building args"); if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) { if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL && mTopComponent != null && app.processName.equals(mTopComponent.getPackageName())) { uid = 0; } if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) { uid = 0; } } int debugFlags = 0; //下面添加debugFlags属性都是为了后续在Zygote创建进程而准备的 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { debugFlags |= Zygote.DEBUG_ENABLE_JDWP; debugFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE; // Also turn on CheckJNI for debuggable apps. It's quite // awkward to turn on otherwise. debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } // Run the app in safe mode if its manifest requests so or the // system is booted in safe mode. if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 || mSafeMode == true) { debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE; } if ("1".equals(SystemProperties.get("debug.checkjni"))) { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info"); if ("true".equals(genDebugInfoProperty)) { debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; } if ("1".equals(SystemProperties.get("debug.jni.logging"))) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) { // Enable all debug flags required by the native debugger. debugFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anything debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizations mNativeDebuggingApp = null; } String invokeWith = null; if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // Debuggable apps may include a wrapper script with their library directory. String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh"; StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { if (new File(wrapperFileName).exists()) { invokeWith = "/system/bin/logwrapper " + wrapperFileName; } } finally { StrictMode.setThreadPolicy(oldPolicy); } } //动态库abi String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi; if (requiredAbi == null) { requiredAbi = Build.SUPPORTED_ABIS[0]; } String instructionSet = null; if (app.info.primaryCpuAbi != null) { instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi); } app.gids = gids; app.requiredAbi = requiredAbi; app.instructionSet = instructionSet; // the per-user SELinux context must be set if (TextUtils.isEmpty(app.info.seInfoUser)) { Slog.wtf(TAG, "SELinux tag not defined", new IllegalStateException("SELinux tag not defined for " + app.info.packageName + " (uid " + app.uid + ")")); } final String seInfo = app.info.seInfo + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser); // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. final String entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); //发送消息给Zygote,它将派生一个子进程,该子进程执行ActivityThread的main函数 //注意,我们传递给Zygote的参数并没有包含任何与Activity相关的信息。现在仅仅启动 //一个应用进程 ProcessStartResult startResult; if (hostingType.equals("webview_service")) { startResult = startWebView(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, null); } else { startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, null); } checkTime(startTime, "startProcess: returned from zygote!"); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); //电量统计项 mBatteryStatsService.noteProcessStart(app.processName, app.info.uid); checkTime(startTime, "startProcess: done updating battery stats"); EventLog.writeEvent(EventLogTags.AM_PROC_START, UserHandle.getUserId(uid), startResult.pid, uid, app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); try { //app进程log启动 AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid, seInfo, app.info.sourceDir, startResult.pid); } catch (RemoteException ex) { // Ignore } /// M: Boot time profiling @{ sMtkSystemServerIns.addBootEvent("AP_Init:[" + hostingType + "]:[" + app.processName + ((hostingNameStr != null) ? "]:[" + hostingNameStr : "") + "]:pid:" + startResult.pid + (app.persistent ? ":(PersistAP)" : "")); /// M: @} if (app.persistent) {//看门狗监听进程 Watchdog.getInstance().processStarted(app.processName, startResult.pid); } checkTime(startTime, "startProcess: building log message"); StringBuilder buf = mStringBuilder; buf.setLength(0); buf.append("Start proc "); buf.append(startResult.pid); buf.append(':'); buf.append(app.processName); buf.append('/'); UserHandle.formatUid(buf, uid); if (app.isolatedEntryPoint != null) { buf.append(" ["); buf.append(app.isolatedEntryPoint); buf.append("]"); } buf.append(" for "); buf.append(hostingType); if (hostingNameStr != null) { buf.append(" "); buf.append(hostingNameStr); } Slog.i(TAG, buf.toString()); app.setPid(startResult.pid);//重新设置pid app.usingWrapper = startResult.usingWrapper; app.removed = false; app.killed = false; app.killedByAm = false; checkTime(startTime, "startProcess: starting to update pids map"); ProcessRecord oldApp; //mPidsSelfLocked里面还保持startResult.pid进程信息,后续会把它清空,保证是一个新的进程 synchronized (mPidsSelfLocked) { oldApp = mPidsSelfLocked.get(startResult.pid); } // If there is already an app occupying that pid that hasn't been cleaned up if (oldApp != null && !app.isolated) { // Clean up anything relating to this pid first Slog.w(TAG, "Reusing pid " + startResult.pid + " while app is still mapped to it"); cleanUpApplicationRecordLocked(oldApp, false, false, -1, true /*replacingPid*/); } synchronized (mPidsSelfLocked) { //重新把此进程存储到mPidsSelfLocked //正常的超时时间为10秒。不过如果该应用进程通过valgrind加载,则延长到1200秒 //valgrind是Linux平台上一款检查内存泄露的程序,被加载的应用将在它的环境中工作 this.mPidsSelfLocked.put(startResult.pid, app); Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, startResult.usingWrapper ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT); } checkTime(startTime, "startProcess: done updating pids map"); } catch (RuntimeException e) { Slog.e(TAG, "Failure starting process " + app.processName, e); // Something went very wrong while trying to start this process; one // common case is when the package is frozen due to an active // upgrade. To recover, clean up any active bookkeeping related to // starting this process. (We already invoked this method once when // the package was initially frozen through KILL_APPLICATION_MSG, so // it doesn't hurt to use it again.) //如果出错的话就暂停进程 forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false, false, true, false, false, UserHandle.getUserId(app.userId), "start failure"); } }

    2.1.3 Process.start

      

    public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { return zygoteProcess.start(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs); }

    2.1.4 zygoteProcess.start

    public final Process.ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); } }

    2.1.5 zygoteProcess.startViaZygote

    private Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<String>(); // --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) { argsForZygote.add("--enable-jni-logging"); } if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) { argsForZygote.add("--enable-safemode"); } if ((debugFlags & Zygote.DEBUG_ENABLE_JDWP) != 0) { argsForZygote.add("--enable-jdwp"); } if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) { argsForZygote.add("--enable-checkjni"); } if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) { argsForZygote.add("--generate-debug-info"); } if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) { argsForZygote.add("--always-jit"); } if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) { argsForZygote.add("--native-debuggable"); } if ((debugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) { argsForZygote.add("--java-debuggable"); } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) { argsForZygote.add("--mount-external-default"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) { argsForZygote.add("--mount-external-read"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) { argsForZygote.add("--mount-external-write"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); int sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); } argsForZygote.add(sb.toString()); } if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); } if (seInfo != null) { argsForZygote.add("--seinfo=" + seInfo); } if (instructionSet != null) { argsForZygote.add("--instruction-set=" + instructionSet); } if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } if (invokeWith != null) { argsForZygote.add("--invoke-with"); argsForZygote.add(invokeWith); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held"); if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(mSocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(mSecondarySocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); } private static Process.ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { // Throw early if any of the arguments are malformed. This means we can // avoid writing a partial response to the zygote. int sz = args.size(); for (int i = 0; i < sz; i++) { if (args.get(i).indexOf('\n') >= 0) { throw new ZygoteStartFailedEx("embedded newlines not allowed"); } } /** * See com.android.internal.os.SystemZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine(); for (int i = 0; i < sz; i++) { String arg = args.get(i); writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? Process.ProcessStartResult result = new Process.ProcessStartResult(); // Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. result.pid = inputStream.readInt(); result.usingWrapper = inputStream.readBoolean(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }

    上面三个函数,给argsForZygote添加时候的参数,连接Zogte  Socket,向Zogte SocketServer 写入值。那么Zogte SocketServer在哪里接受这些信息?答案是ZygoteInit

    2.1.6 ZygoteInit.main

    public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); // Mark zygote start. This ensures that thread creation will throw // an error. ZygoteHooks.startZygoteNoThreadCreation(); // Zygote goes into its own process group. try { Os.setpgid(0, 0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)", ex); } final Runnable caller; try { // Report Zygote start time to tron unless it is a runtime restart if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.elapsedRealtime()); } String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); bootTimingsTraceLog.traceBegin("ZygoteInit"); RuntimeInit.enableDdms(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = 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."); } zygoteServer.registerServerSocket(socketName); // In some configurations, we avoid preloading resources and classes eagerly. // In such cases, we will preload things prior to our first fork. if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); /// M: Added for BOOTPROF addBootEvent("Zygote:Preload Start"); /// @} preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); } // Do an initial gc to clean up after startup bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); gcAndFinalize(); bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC bootTimingsTraceLog.traceEnd(); // ZygoteInit // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false, 0); // Zygote process unmounts root storage spaces. Zygote.nativeUnmountStorageOnInit(); // Set seccomp policy Seccomp.setPolicy(); /// M: Added for BOOTPROF addBootEvent("Zygote:Preload End"); /// @} ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // {@code r == null} in the parent (zygote) process, and {@code r != null} in the // child (system_server) process. if (r != null) { r.run(); return; } } Log.i(TAG, "Accepting command socket connections"); // The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); } // We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run(); } }

    这个函数是Zygote进程启动的主入口,在上面的函数可以看到zygoteServer.registerServerSocket(socketName);这个就是我们之前连接的socketServer的创建入口。zygoteServer.runSelectLoop(abiList);这个函数就是不停的从socket那边获取信息创建进程

    2.1.6 ZygoteServer.runSelectLoop

    Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); fds.add(mServerSocket.getFileDescriptor()); peers.add(null); while (true) { StructPollfd[] pollFds = new StructPollfd[fds.size()]; for (int i = 0; i < pollFds.length; ++i) { pollFds[i] = new StructPollfd(); pollFds[i].fd = fds.get(i); pollFds[i].events = (short) POLLIN; } try { Os.poll(pollFds, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { try { ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this); if (mIsForkChild) { // We're in the child. We should always have a command to run at this // stage if processOneCommand hasn't called "exec". if (command == null) { throw new IllegalStateException("command == null"); } return command; } else { // We're in the server - we should never have any commands to run. if (command != null) { throw new IllegalStateException("command != null"); } // We don't know whether the remote side of the socket was closed or // not until we attempt to read from it from processOneCommand. This shows up as // a regular POLLIN event in our regular processing loop. if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(i); fds.remove(i); } } } catch (Exception e) { if (!mIsForkChild) { // We're in the server so any exception here is one that has taken place // pre-fork while processing commands or reading / writing from the // control socket. Make a loud noise about any such exceptions so that // we know exactly what failed and why. Slog.e(TAG, "Exception executing zygote command: ", e); // Make sure the socket is closed so that the other end knows immediately // that something has gone wrong and doesn't time out waiting for a // response. ZygoteConnection conn = peers.remove(i); conn.closeSocket(); fds.remove(i); } else { // We're in the child so any exception caught here has happened post // fork and before we execute ActivityThread.main (or any other main() // method). Log the details of the exception and bring down the process. Log.e(TAG, "Caught post-fork exception in child process.", e); throw e; } } } } } }

    看connection.processOneCommand这个方法

    2.1.7 ZygoteConnection.processOneCommand

    Runnable processOneCommand(ZygoteServer zygoteServer) { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { throw new IllegalStateException("IOException on command socket", ex); } // readArgumentList returns null only when it has reached EOF with no available // data to read. This will only happen when the remote socket has disconnected. if (args == null) { isEof = true; return null; } int pid = -1; FileDescriptor childPipeFd = null; FileDescriptor serverPipeFd = null; parsedArgs = new Arguments(args); if (parsedArgs.abiListQuery) { handleAbiListQuery(); return null; } if (parsedArgs.preloadDefault) { handlePreload(); return null; } if (parsedArgs.preloadPackage != null) { handlePreloadPackage(parsedArgs.preloadPackage, parsedArgs.preloadPackageLibs, parsedArgs.preloadPackageCacheKey); return null; } if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) { throw new ZygoteSecurityException("Client may not specify capabilities: " + "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) + ", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities)); } applyUidSecurityPolicy(parsedArgs, peer); applyInvokeWithSecurityPolicy(parsedArgs, peer); applyDebuggerSystemProperty(parsedArgs); applyInvokeWithSystemProperty(parsedArgs); int[][] rlimits = null; if (parsedArgs.rlimits != null) { rlimits = parsedArgs.rlimits.toArray(intArray2d); } int[] fdsToIgnore = null; if (parsedArgs.invokeWith != null) { try { FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC); childPipeFd = pipeFds[1]; serverPipeFd = pipeFds[0]; Os.fcntlInt(childPipeFd, F_SETFD, 0); fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()}; } catch (ErrnoException errnoEx) { throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx); } } /** * In order to avoid leaking descriptors to the Zygote child, * the native code must close the two Zygote socket descriptors * in the child process before it switches from Zygote-root to * the UID and privileges of the application being launched. * * In order to avoid "bad file descriptor" errors when the * two LocalSocket objects are closed, the Posix file * descriptors are released via a dup2() call which closes * the socket and substitutes an open descriptor to /dev/null. */ int [] fdsToClose = { -1, -1 }; FileDescriptor fd = mSocket.getFileDescriptor(); if (fd != null) { fdsToClose[0] = fd.getInt$(); } fd = zygoteServer.getServerSocketFileDescriptor(); if (fd != null) { fdsToClose[1] = fd.getInt$(); } fd = null; pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet, parsedArgs.appDataDir); try { if (pid == 0) { // in child zygoteServer.setForkChild(); zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs, descriptors, childPipeFd); } else { // In the parent. A pid < 0 indicates a failure and will be handled in // handleParentProc. IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid, descriptors, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }

    2.1.8 Zygote.forkAndSpecialize

    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, String instructionSet, String appDataDir) { VM_HOOKS.preFork(); // Resets nice priority for zygote process. resetNicePriority(); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, instructionSet, appDataDir); // Enable tracing as soon as possible for the child process. if (pid == 0) { Trace.setTracingEnabled(true, debugFlags); // Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); } VM_HOOKS.postForkCommon(); return pid; }

    最终会调用nativeForkAndSpecialize的native方法,而这个native方法的实现是在com_android_internal_os_Zygote.cpp会调用linux的方法pid_t pid = fork()。到此处我们的app进程创建完成,那app进程创建完成后怎么执行java程序呢?启动activity呢?在ZygoteConnection.processOneCommand方法中执行了Zygote.forkAndSpecialize 会判断pid是否为0,并且也会启动handleChildProc方法

    2.1.9 ZygoteConnection.handleChildProc

    private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd) { /** * 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); for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } } catch (ErrnoException ex) { Log.e(TAG, "Error reopening stdio", ex); } } if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } // End of the postFork event. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.remainingArgs); // Should not get here. throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); } }

    2.2.1WrapperInit.execApplication

    public static void execApplication(String invokeWith, String niceName, int targetSdkVersion, String instructionSet, FileDescriptor pipeFd, String[] args) { StringBuilder command = new StringBuilder(invokeWith); final String appProcess; if (VMRuntime.is64BitInstructionSet(instructionSet)) { appProcess = "/system/bin/app_process64"; } else { appProcess = "/system/bin/app_process32"; } command.append(' '); command.append(appProcess); command.append(" /system/bin --application"); if (niceName != null) { command.append(" '--nice-name=").append(niceName).append("'"); } command.append(" com.android.internal.os.WrapperInit "); command.append(pipeFd != null ? pipeFd.getInt$() : 0); command.append(' '); command.append(targetSdkVersion); Zygote.appendQuotedShellArgs(command, args); preserveCapabilities(); Zygote.execShell(command.toString()); }

    从上面的代码就能比较容易的看出来通过shell脚本来启动Activity,这个方法主要是填写一些启动参数。查看execshell果然跟我们猜想的一样/system/bin/sh

    public static void execShell(String command) { String[] args = { "/system/bin/sh", "-c", command }; try { Os.execv(args[0], args); } catch (ErrnoException e) { throw new RuntimeException(e); } }

    到目前来说我们的app进程算是创建完成。

    三、应用进程创建后activity的启动

       那有个问题是应用进程运行的第一个java代码是哪个呢?答案是:ActivityThread.main .可能有些读者会问为什么呢?

    还记得我们在AMS中startProcessLocked的方法里面有个字段 final String entryPoint = "android.app.ActivityThread";如果有兴趣的读者可以自己打印相关的信息以及追踪。

    3.1.1 ActivityThread.main

       

    public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); // 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(new EventLoggingReporter()); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); //设置进程名为"<pre-initialized>" Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//准备主线程消息循环 ActivityThread thread = new ActivityThread();//创建一个ActivityThread对象 thread.attach(false); if (sMainThreadHandler == null) {//app 进程第一次启动sMainThreadHandler=null,这也是主线程的handler sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); /// M: ANR Debug Mechanism mAnrAppManager.setMessageLogger(Looper.myLooper()); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

    3.1.1 ActivityThread.attach

    private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) {//应用进程的处理流程 //view在绘画的时候回调 ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled();//启动即时编译 } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder());//设置IBinder,主要是为后续跨进程使用 //获取和AMS交互的Binder客户端 final IActivityManager mgr = ActivityManager.getService(); try { //①调用AMS的attachApplication,mAppThread为ApplicationThread类型,它是应用进程和AMS交互的接口 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { mgr.releaseSomeActivities(mAppThread);//清除这个进程中不活跃的ActivityRecord } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }); } else { // Don't set application object here -- if the system crashes, // we can't display an alert, we just want to die die die. //系统进程的处理流程 //设置DDM的进程名称system_process android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId()); try { // 一个工具类,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了 mInstrumentation = new Instrumentation(); //创建属于这个进程的context ContextImpl context = ContextImpl.createAppContext( this, getSystemContext().mPackageInfo); //启动application oncreate 方法 //Application是Android中的一个概念,可理解为一种容器,它内部包含四大组件。另外,一个进程可以运行多个Application。 mInitialApplication = context.mPackageInfo.makeApplication(true, null); mInitialApplication.onCreate(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate Application():" + e.toString(), e); } } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); //注册Configuration变化的回调通知 ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { synchronized (mResourcesManager) { // We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig, null /* compat */)) { updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(), mResourcesManager.getConfiguration().getLocales()); // This actually changed the resources! Tell everyone about it. if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(globalConfig)) { mPendingConfiguration = globalConfig; sendMessage(H.CONFIGURATION_CHANGED, globalConfig); } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }

    3.1.2 AMS attachApplication

    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { // Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; long startTime = SystemClock.uptimeMillis(); //MY_PID是AMS的服务进程id,这个判断就是不是系统进程 if (pid != MY_PID && pid >= 0) { //mPidsSelfLocked管理所有的application进程 //那这个app进程是什么时候添加到mPidsSelfLocked? //答案是:startProcessLocked函数中创建了新的进程,并且执行了this.mPidsSelfLocked.put(startResult.pid, app); synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; } /* 如果该应用进程由AMS启动,则它一定在AMS中有对应的ProcessRecord,读者可回顾前面创建 应用进程的代码:AMS先创建了一个ProcessRecord对象,然后才发命令给Zygote。 如果此处app为null,表示AMS没有该进程的记录,故需要“杀死”它 */ if (app == null) { Slog.w(TAG, "No pending application record for pid " + pid + " (IApplicationThread " + thread + "); dropping process"); EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid); if (pid > 0 && pid != MY_PID) { killProcessQuiet(pid); //TODO: killProcessGroup(app.info.uid, pid); } else { try { //调用ApplicationThread的scheduleExit函数。应用进程完成处理工作 //将退出运行 thread.scheduleExit(); } catch (Exception e) { // Ignore exceptions. } } return false; } // If this application record is still attached to a previous // process, clean it up now. //app进程存在,并且之前也有主线程,清空已经存在的线程 if (app.thread != null) { handleAppDiedLocked(app, true, true); } // Tell the process all about itself. if (DEBUG_ALL) Slog.v( TAG, "Binding process pid " + pid + " to record " + app); /* 创建一个应用进程讣告接收对象。当应用进程退出时,该对象的binderDied将被调 用。这样,AMS就能做相应处理。binderDied函数将在另外一个线程中执行,其内部也会 调用handleAppDiedLocked。 */ final String processName = app.processName; try { //app死亡监听服务 AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); return false; } EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName); //设置该进程的调度优先级和oom_adj等成员 app.makeActive(thread, mProcessStats); app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ; app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.forcingToImportant = null; updateProcessForegroundLocked(app, false, false);//更新作为前台进程 //在这个阶段是不允许进程被杀死。 app.hasShownUi = false; app.debugging = false; app.cached = false; app.killedByAm = false; app.killed = false; // We carefully use the same state that PackageManager uses for // filtering, since we use this flag to decide if we need to install // providers when user is unlocked later app.unlocked = StorageManager.isUserKeyUnlocked(app.userId); //启动成功,从消息队列中撤销PROC_START_TIMEOUT_MSG消息 //那么这个广播是在什么时候发送的? //startProcessLocked->Process.start 进程创建的时候就开始发送的。 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); //SystemServer早就启动完毕,所以normalMode为true boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); //在该函数内部将查询(根据进程名,uid确定)PKMS以获取需运行在该进程中的ContentProvider List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; if (providers != null && checkAppInLaunchingProvidersLocked(app)) { Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT); } checkTime(startTime, "attachApplicationLocked: before bindApplication"); if (!normalMode) { Slog.i(TAG, "Launching preboot mode app: " + app); } if (DEBUG_ALL) Slog.v( TAG, "New app record " + app + " thread=" + thread.asBinder() + " pid=" + pid); try { int testMode = ApplicationThreadConstants.DEBUG_OFF; if (mDebugApp != null && mDebugApp.equals(processName)) { testMode = mWaitForDebugger ? ApplicationThreadConstants.DEBUG_WAIT : ApplicationThreadConstants.DEBUG_ON; app.debugging = true; if (mDebugTransient) { mDebugApp = mOrigDebugApp; mWaitForDebugger = mOrigWaitForDebugger; } } ProfilerInfo profilerInfo = null; String agent = null; //用于记录性能文件 if (mProfileApp != null && mProfileApp.equals(processName)) { mProfileProc = app; profilerInfo = (mProfilerInfo != null && mProfilerInfo.profileFile != null) ? new ProfilerInfo(mProfilerInfo) : null; agent = mProfilerInfo != null ? mProfilerInfo.agent : null; } else if (app.instr != null && app.instr.mProfileFile != null) { profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false, null); } boolean enableTrackAllocation = false; if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) { enableTrackAllocation = true; mTrackAllocationApp = null; } // If the app is being launched for restore or full backup, set it up specially boolean isRestrictedBackupMode = false; if (mBackupTarget != null && mBackupAppName.equals(processName)) { isRestrictedBackupMode = mBackupTarget.appInfo.uid >= FIRST_APPLICATION_UID && ((mBackupTarget.backupMode == BackupRecord.RESTORE) || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL) || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL)); } if (app.instr != null) { notifyPackageUse(app.instr.mClass.getPackageName(), PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION); } if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc " + processName + " with config " + getGlobalConfiguration()); ApplicationInfo appInfo = app.instr != null ? app.instr.mTargetInfo : app.info; app.compat = compatibilityInfoForPackageLocked(appInfo); if (profilerInfo != null && profilerInfo.profileFd != null) { profilerInfo.profileFd = profilerInfo.profileFd.dup(); } // We deprecated Build.SERIAL and it is not accessible to // apps that target the v2 security sandbox. Since access to // the serial is now behind a permission we push down the value. String buildSerial = appInfo.targetSandboxVersion < 2 ? sTheRealBuildSerial : Build.UNKNOWN; // Check if this is a secondary process that should be incorporated into some // currently active instrumentation. (Note we do this AFTER all of the profiling // stuff above because profiling can currently happen only in the primary // instrumentation process.) if (mActiveInstrumentation.size() > 0 && app.instr == null) { for (int i = mActiveInstrumentation.size() - 1; i >= 0 && app.instr == null; i--) { ActiveInstrumentation aInstr = mActiveInstrumentation.get(i); if (!aInstr.mFinished && aInstr.mTargetInfo.uid == app.uid) { if (aInstr.mTargetProcesses.length == 0) { // This is the wildcard mode, where every process brought up for // the target instrumentation should be included. if (aInstr.mTargetInfo.packageName.equals(app.info.packageName)) { app.instr = aInstr; aInstr.mRunningProcesses.add(app); } } else { for (String proc : aInstr.mTargetProcesses) { if (proc.equals(app.processName)) { app.instr = aInstr; aInstr.mRunningProcesses.add(app); break; } } } } } } // If we were asked to attach an agent on startup, do so now, before we're binding // application code. if (agent != null) { thread.attachAgent(agent); } checkTime(startTime, "attachApplicationLocked: immediately before bindApplication"); mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app); if(DEBUG_ACTIVITY_START)Log.i("ActivityManagerService-xiao", "bindApplication" ); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } else if (app.instr != null) { //①通过ApplicationThread和应用进程交互,调用其bindApplication函数 thread.bindApplication(processName, appInfo, providers, app.instr.mClass, profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial); } checkTime(startTime, "attachApplicationLocked: immediately after bindApplication"); updateLruProcessLocked(app, false, null);//更新进程 checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked"); //记录两个时间 app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { // todo: Yikes! What should we do? For now we will try to // start another process, but that could easily get us in // an infinite loop of restarting processes... Slog.wtf(TAG, "Exception thrown during bind of " + app, e); app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); startProcessLocked(app, "bind fail", processName); return false; } // Remove this record from the list of starting applications. mPersistentStartingProcesses.remove(app); if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES, "Attach application locked removing on hold: " + app); mProcessesOnHold.remove(app); boolean badApp = false; boolean didSomething = false; // See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked"); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } // Check if a next-broadcast receiver is in this process... if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked"); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e); badApp = true; } } // Check whether the next backup agent is in this process... if (!badApp && mBackupTarget != null && mBackupTarget.app == app) { if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "New app is backup target, launching agent for " + app); notifyPackageUse(mBackupTarget.appInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_BACKUP); try { thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e); badApp = true; } } if (badApp) { app.kill("error during init", true); handleAppDiedLocked(app, false, true); return false; } if (!didSomething) { updateOomAdjLocked(); checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked"); } return true; }

    3.1.3 ActivityThread  bindApplication

    public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings, String buildSerial) { if (services != null) {//保存AMS传递过来的系统Service信息 // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings);//向主线程消息队列添加SET_CORE_SETTINGS消息 AppBindData data = new AppBindData();//将AMS传过来的参数保存到AppBindData中 data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableBinderTracking = enableBinderTracking; data.trackAllocation = trackAllocation; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; sendMessage(H.BIND_APPLICATION, data);//绑定data }

    3.1.4 ActivityThread handleBindApplication

    private void handleBindApplication(AppBindData data) { // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); if (data.trackAllocation) { DdmVmInternal.enableRecentAllocations(true); } // Note when this process has started. //设置进程开始时间 Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); mProfiler = new Profiler();//初始化性能统计对象 if (data.initProfilerInfo != null) { mProfiler.profileFile = data.initProfilerInfo.profileFile; mProfiler.profileFd = data.initProfilerInfo.profileFd; mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput; } // send up app name; do this *before* waiting for debugger Process.setArgV0(data.processName);//设置进程名称 android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); if (mProfiler.profileFd != null) { mProfiler.startProfiling();//开启性能统计 } // If the app is Honeycomb MR1 or earlier, switch its AsyncTask // implementation to use the pool executor. Normally, we use the // serialized executor as the default. This has to happen in the // main thread so the main looper is set right. if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);//SDK小于12,更改AsyncTask的初始值 } Message.updateCheckRecycle(data.appInfo.targetSdkVersion); /* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the * the spawning of this process. Without doing this this process would have the incorrect * system time zone. */ TimeZone.setDefault(null); /* * Set the LocaleList. This may change once we create the App Context. */ LocaleList.setDefault(data.config.getLocales());//设置app的本地,locale synchronized (mResourcesManager) { /* * Update the system configuration since its preloaded and might not * reflect configuration changes. The configuration object passed * in AppBindData can be safely assumed to be up to date */ //设置资源及兼容模式 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi;//dpi // This calls mResourcesManager so keep it within the synchronized block. applyCompatConfiguration(mCurDefaultDisplayDpi); } data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); /** * Switch this process to density compatibility mode if needed. */ if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } updateDefaultDensity(); final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);//是时间默认格式 Boolean is24Hr = null; if (use24HourSetting != null) { is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE; } // null : use locale default for 12/24 hour formatting, // false : use 12 hour format, // true : use 24 hour format. DateFormat.set24HourTimePref(is24Hr); View.mDebugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; /** * For system applications on userdebug/eng builds, log stack * traces of disk and network access to dropbox for analysis. */ //对于系统APK,如果当前系统为userdebug/eng版,则需要记录log信息到dropbox的日志记录 if ((data.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { StrictMode.conditionallyEnableDebugLogging(); } /** * For apps targetting Honeycomb or later, we don't allow network usage * on the main event loop / UI thread. This is what ultimately throws * {@link NetworkOnMainThreadException}. */ // 如目标SDK版本大于11,则不允许在主线程使用网络操作(如Socketconnect等) if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) { StrictMode.enableDeathOnNetwork(); } /** * For apps targetting N or later, we don't allow file:// Uri exposure. * This is what ultimately throws {@link FileUriExposedException}. */ if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) { StrictMode.enableDeathOnFileUriExposure(); } // We deprecated Build.SERIAL and only apps that target pre NMR1 // SDK can see it. Since access to the serial is now behind a // permission we push down the value and here we fix it up // before any app code has been loaded. try { Field field = Build.class.getDeclaredField("SERIAL"); field.setAccessible(true); field.set(Build.class, data.buildSerial); } catch (NoSuchFieldException | IllegalAccessException e) { /* ignore */ } if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) { // XXX should have option to change the port. Debug.changeDebugPort(8100); if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) { Slog.w(TAG, "Application " + data.info.getPackageName() + " is waiting for the debugger on port 8100..."); IActivityManager mgr = ActivityManager.getService(); try { mgr.showWaitingForDebugger(mAppThread, true); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } Debug.waitForDebugger(); try { mgr.showWaitingForDebugger(mAppThread, false); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } else { Slog.w(TAG, "Application " + data.info.getPackageName() + " can be debugged on port 8100..."); } } // Allow application-generated systrace messages if we're debuggable. boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; Trace.setAppTracingAllowed(isAppDebuggable); if (isAppDebuggable && data.enableBinderTracking) { Binder.enableTracing(); } /** * Initialize the default http proxy in this process for the reasons we set the time zone. */ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies"); final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { // In pre-boot mode (doing initial launch to collect password), not // all system is up. This includes the connectivity service, so don't // crash if we can't get it. final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo);//设置Http代理信息 } catch (RemoteException e) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw e.rethrowFromSystemServer(); } } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // Instrumentation info affects the class loader, so load it before // setting up the app context. final InstrumentationInfo ii; if (data.instrumentationName != null) {//在正常情况下,此条件不满足 try { ii = new ApplicationPackageManager(null, getPackageManager()) .getInstrumentationInfo(data.instrumentationName, 0); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( "Unable to find instrumentation info for: " + data.instrumentationName); } //创建Instrumentation对象,在正常情况都再这个条件下执行 mInstrumentationPackageName = ii.packageName; mInstrumentationAppDir = ii.sourceDir; mInstrumentationSplitAppDirs = ii.splitSourceDirs; mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii); mInstrumentedAppDir = data.info.getAppDir(); mInstrumentedSplitAppDirs = data.info.getSplitAppDirs(); mInstrumentedLibDir = data.info.getLibDir(); } else { ii = null; } //创建app 内部使用的Context final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); //更新Locale信息 updateLocaleListFromAppContext(appContext, mResourcesManager.getConfiguration().getLocales()); if (!Process.isIsolated()) { setupGraphicsSupport(appContext); } // If we use profiles, setup the dex reporter to notify package manager // of any relevant dex loads. The idle maintenance job will use the information // reported to optimize the loaded dex files. // Note that we only need one global reporter per app. // Make sure we do this before calling onCreate so that we can capture the // complete application startup. if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) { BaseDexClassLoader.setReporter(DexLoadReporter.getInstance()); } // Install the Network Security Config Provider. This must happen before the application // code is loaded to prevent issues with instances of TLS objects being created before // the provider is installed. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install"); NetworkSecurityConfigProvider.install(appContext); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); // Continue loading instrumentation. if (ii != null) { final ApplicationInfo instrApp = new ApplicationInfo(); ii.copyTo(instrApp); instrApp.initForUser(UserHandle.myUserId()); final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); //创建安装ContextImpl,这个需要用到framwork-res的资源 final ContextImpl instrContext = ContextImpl.createAppContext(this, pi); try { final ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " + data.instrumentationName + ": " + e.toString(), e); } //创建组件 final ComponentName component = new ComponentName(ii.packageName, ii.name); mInstrumentation.init(this, instrContext, appContext, component, data.instrumentationWatcher, data.instrumentationUiAutomationConnection); if (mProfiler.profileFile != null && !ii.handleProfiling && mProfiler.profileFd == null) { mProfiler.handlingProfiling = true; final File file = new File(mProfiler.profileFile); file.getParentFile().mkdirs(); Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } } else { mInstrumentation = new Instrumentation(); } //如果Package中声明了FLAG_LARGE_HEAP,则可跳过虚拟机的内存限制,放心使用内存 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } // Allow disk access during application and provider setup. This could // block processing ordered broadcasts, but later processing would // probably end up doing the same disk access. Application app; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy(); try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. //创建一个Application,data.info为LoadedApk类型,在其内部会通过Java反射机制 //创建一个在该APK AndroidManifest.xml中声明的Application对象 app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { //mInstrumentation 做一些初始化工作 mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { //调用Application的onCreate函数,做一些初始工作 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion <= Build.VERSION_CODES.O || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } } // Preload fonts resources FontsContract.setApplicationContextForResources(appContext); try { final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); if (info.metaData != null) { final int preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }

    其中创建了application,所以在在一个进程中只有一个application并且它的启动时间是最早的, mInstrumentation.onCreate,mInstrumentation.callApplicationOnCreate(app);会调用Application中的oncreate方法

    3.1.5  之前的AMS attachApplicationLocked方法中,我们刚才只走了bindApplication的流程,其后面还有代码块mStackSupervisor.attachApplicationLocked(app) 

    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { final String processName = app.processName; boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); if (!isFocusedStack(stack)) { continue; } stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList); //获取前台栈顶第一个非finishing的Activity final ActivityRecord top = stack.topRunningActivityLocked(); final int size = mTmpActivityList.size(); for (int i = 0; i < size; i++) { final ActivityRecord activity = mTmpActivityList.get(i); //为什么是activity.app == null //在进程启动前我们就创建了ActivityRecord,并且把它放在顶层的activity,但是我们并没有 //为它分配相应的进程,现在进程创建完了,我们再来找它,并且把进程分配给它 if (activity.app == null && app.uid == activity.info.applicationInfo.uid && processName.equals(activity.processName)) { try { //开始启动activity, if (realStartActivityLocked(activity, app, top == activity /* andResume */, true /* checkConfig */)) { didSomething = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + top.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { //启动Activity不成功,确保有可见的Activity ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } return didSomething; }

    3.1.6 ActivityStackSuppervisor 

     

    Processed: 0.009, SQL: 10