android Activity启动流程(4)

/ android / 没有评论 / 558浏览

用到的代码文件

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
frameworks/base/core/java/android/app/ActivityManagerNative.java
frameworks/base/core/java/android/app/IActivityManager.java
frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
frameworks/base/core/java/android/os/Process.java
frameworks/base/core/java/android/os/Process.java中定义ZygoteState静态内部类

代称执行流程图

android activity 查看原图

android activity启动流程

下面的代码是以android N(api 24)为基础。

承接上文android Activity启动流程(3)

ActivityManagerService继承自抽象类ActivityManagerNative,而ActivityManagerNative类实现了IActivityManager接口。

在上文中通过Binder通信,而此时接受消息的是ActivityManagerService类中的activityPaused()方法。
下面是activityPaused()方法的具体实现。

@Override
public final void activityPaused(IBinder token) {
    //Token{620e4da ActivityRecord{7100e85 u0 com.tct.launcher/.Launcher t29}}
    log("token : "+token);
    final long origId = Binder.clearCallingIdentity();
    log("origId : "+origId);//43430709300335
    synchronized(this) {
        /**
          * 进入这里
          */
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        log("stack : "+stack);//ActivityStack{d085fc7 stackId=0, 1 tasks}
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}

接下来调用ActivityStack中的activityPausedLocked()方法。

final void activityPausedLocked(IBinder token, boolean timeout) {
    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
        "Activity paused: token=" + token + ", timeout=" + timeout);
    final ActivityRecord r = isInStackLocked(token);
    //ActivityRecord{ea79a1d u0 com.tct.launcher/.Launcher t31}
    log("ActivityRecord r : "+r);
    if (r != null) {
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        //ActivityRecord{ea79a1d u0 com.tct.launcher/.Launcher t31}
        log("mPausingActivity : "+mPausingActivity);
        if (mPausingActivity == r) { //true
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                    + (timeout ? " (due to timeout)" : " (pause complete)"));
            completePauseLocked(true);
            return;
        } else {
            EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
                    r.userId, System.identityHashCode(r), r.shortComponentName,
                    mPausingActivity != null
                        ? mPausingActivity.shortComponentName : "(none)");
            if (r.state == ActivityState.PAUSING) {
                r.state = ActivityState.PAUSED;
                if (r.finishing) {
                    if (DEBUG_PAUSE) Slog.v(TAG,
                            "Executing finish of failed to pause activity: " + r);
                    finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
                }
            }
        }
    }
    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}

接下来调用ActivityStack中的completePauseLocked()方法。

private void completePauseLocked(boolean resumeNext) {
    ActivityRecord prev = mPausingActivity;
    //ActivityRecord{fca44f3 u0 com.tct.launcher/.Launcher t33}
    log("prev: "+prev); 
    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);

    if (prev != null) {
        final boolean wasStopping = prev.state == ActivityState.STOPPING;
        log("wasStopping: "+wasStopping); //false
        prev.state = ActivityState.PAUSED;
        log("prev.finishing: "+prev.finishing); //false
        if (prev.finishing) {
            if (DEBUG_PAUSE) 
                Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
            prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
        } else if (prev.app != null) { //true
            if (DEBUG_PAUSE) 
                Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
                    + " wasStopping=" + wasStopping + " visible=" + prev.visible);
            if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {
                if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
                        "Complete pause, no longer waiting: " + prev);
            }
            if (prev.deferRelaunchUntilPaused) {//false
                // Complete the deferred relaunch that was waiting for pause to complete.
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
                relaunchActivityLocked(prev, prev.configChangeFlags, false,
                        prev.preserveWindowOnDeferredRelaunch);
            } else if (wasStopping) {
                // We are also stopping, the stop request must have gone soon after the pause.
                // We can't clobber it, because the stop confirmation will not be handled.
                // We don't need to schedule another stop, we only need to let it happen.
                prev.state = ActivityState.STOPPING;
            } else if ((!prev.visible && !hasVisibleBehindActivity())
                    || mService.isSleepingOrShuttingDownLocked()) { // false
                // If we were visible then resumeTopActivities will release resources before
                // stopping.
                addToStopping(prev, true /* immediate */);
            }
        } else {
            if (DEBUG_PAUSE) 
                Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
            prev = null;
        }
        // It is possible the activity was freezing the screen before it was paused.
        // In that case go ahead and remove the freeze this activity has on the screen
        // since it is no longer visible.
        prev.stopFreezingScreenLocked(true /*force*/);
        mPausingActivity = null;
    }

    if (resumeNext) {
        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
        if (!mService.isSleepingOrShuttingDownLocked()) {// -> true
            /**
              * 进入这里
              */
            mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
        } else {
            mStackSupervisor.checkReadyForSleepLocked();
            ActivityRecord top = topStack.topRunningActivityLocked();
            if (top == null || (prev != null && top != prev)) {
                log("top: "+top);
                // If there are no more activities available to run, do resume anyway to start
                // something. Also if the top activity on the stack is not the just paused
                // activity, we need to go ahead and resume it to ensure we complete an
                // in-flight app switch.
                mStackSupervisor.resumeFocusedStackTopActivityLocked();
            }
        }
    }

    if (prev != null) {// -> true
        prev.resumeKeyDispatchingLocked();

        if (prev.app != null && prev.cpuTimeAtResume > 0
                && mService.mBatteryStatsService.isOnBattery()) {
            long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
                    - prev.cpuTimeAtResume;
            if (diff > 0) {
                BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
                synchronized (bsi) {
                    BatteryStatsImpl.Uid.Proc ps =
                            bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
                                    prev.info.packageName);
                    if (ps != null) {
                        ps.addForegroundTimeLocked(diff);
                    }
                }
            }
        }
        prev.cpuTimeAtResume = 0; // reset it
    }

    // Notify when the task stack has changed, but only if visibilities changed (not just focus)
    log("mAppVisibilitiesChangedSinceLastPause : "+mStackSupervisor.mAppVisibilitiesChangedSinceLastPause);
    if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause) {
        mService.notifyTaskStackChangedLocked();
        mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
    }

    mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}

下面进入ActivityStackSupervisor类中resumeFocusedStackTopActivityLocked方法。

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    // ActivityStack{3cd83b1 stackId=1, 1 tasks}
    Log.i(MTAG,"targetStack: "+targetStack); 
    //ActivityRecord{fca44f3 u0 com.tct.launcher/.Launcher t33}
    Log.i(MTAG,"target: "+target);
    Log.i(MTAG,"targetOptions: "+targetOptions); //null

    if (targetStack != null && isFocusedStack(targetStack)) { //->true
        /*
          * 进入这里
          */
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {// -> false
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
}

接下来进入ActivityStack中的resumeTopActivityUncheckedLocked()方法。

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    if (mStackSupervisor.inResumeTopActivity) { //->false
        // Don't even start recursing.
        return false;
    }

    boolean result = false;
    try {
        // Protect against recursion.
        mStackSupervisor.inResumeTopActivity = true;
        if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { // -> false
            mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
            mService.updateSleepIfNeededLocked();
        }
        /**
          * 进入这里
          */
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    return result;
}

接下来进入ActivityStack中的resumeTopActivityInnerLocked()方法。
resumeTopActivityInnerLocked()这个方法涉及到的逻辑判断太多了,有点复杂...

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    log("prev: "+prev); //ActivityRecord{4bc32e u0 com.tct.launcher/.Launcher t35}
    log("options: "+options); //null
    if (DEBUG_LOCKSCREEN) mService.logLockScreen("");

    if (!mService.mBooting && !mService.mBooted) {
        // Not ready yet!
        return false;
    }

    log("mActivityContainer: "+mActivityContainer);//ActivtyContainer{1}A
    ActivityRecord parent = mActivityContainer.mParentActivity;
    log("parent: "+parent);//null
    if ((parent != null && parent.state != ActivityState.RESUMED) ||
            !mActivityContainer.isAttachedLocked()) {
        // Do not resume this stack if its parent is not resumed.
        // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
        return false;
    }

    mStackSupervisor.cancelInitializingActivities();

    // Find the first activity that is not finishing.
    final ActivityRecord next = topRunningActivityLocked();
    log("next: "+next);//ActivityRecord{9522249 u0 com.jrdcom.filemanager/.activity.FileBrowserActivity t36}

    // Remember how we'll process this pause/resume situation, and ensure
    // that the state is reset however we wind up proceeding.
    final boolean userLeaving = mStackSupervisor.mUserLeaving;
    mStackSupervisor.mUserLeaving = false;

    final TaskRecord prevTask = prev != null ? prev.task : null;

    log("userLeaving: "+userLeaving);//false
    log("prevTask: "+prevTask);//TaskRecord{f2dc1ac #35 I=com.tct.launcher/.Launcher U=0 StackId=0 sz=1}

    if (next == null) {// ->false
        ......
    }

    next.delayedResume = false;

    // If the top activity is the resumed one, nothing to do.
    if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) { //->false
        ......
    }

    final TaskRecord nextTask = next.task;
    if (prevTask != null && prevTask.stack == this &&
            prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { //-> false
        ......
    }

    // If we are sleeping, and there is no resumed activity, and the top
    // activity is paused, well that is the state we want.
    if (mService.isSleepingOrShuttingDownLocked()
            && mLastPausedActivity == next
            && mStackSupervisor.allPausedActivitiesComplete()) { // -> false
        ......
    }

    // Make sure that the user who owns this activity is started.  If not,
    // we will just leave it as is because someone should be bringing
    // another user's activities to the top of the stack.
    if (!mService.mUserController.hasStartedUserState(next.userId)) { //-> false
        ......
    }

    // The activity may be waiting for stop, but that is no longer
    // appropriate for it.
    mStackSupervisor.mStoppingActivities.remove(next);
    mStackSupervisor.mGoingToSleepActivities.remove(next);
    next.sleeping = false;
    mStackSupervisor.mWaitingVisibleActivities.remove(next);

    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

    mActivityTrigger.activityResumeTrigger(next.intent, next.info, next.appInfo);

    // If we are currently pausing an activity, then don't do anything
    // until that is done.
    if (!mStackSupervisor.allPausedActivitiesComplete()) {// -> false
        ......
    }

    mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

    // We need to start pausing the current activity so the top one can be resumed...
    final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
    log("dontWaitForPause: "+dontWaitForPause);//false
    log("pausing: "+pausing);//false
    log("mResumedActivity: "+mResumedActivity); //null
    if (mResumedActivity != null) {// -> false
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
    }
    if (pausing) {
        if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                "resumeTopActivityLocked: Skip resume: need to start pausing");
        // At this point we want to put the upcoming activity's process
        // at the top of the LRU list, since we know we will be needing it
        // very soon and it would be a waste to let it get killed if it
        // happens to be sitting towards the end.
        if (next.app != null && next.app.thread != null) {
            mService.updateLruProcessLocked(next.app, true, null);
        }
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
            mStackSupervisor.allResumedActivitiesComplete()) {//-> false
        log("if judge 7 true");
        // It is possible for the activity to be resumed when we paused back stacks above if the
        // next activity doesn't have to wait for pause to complete.
        // So, nothing else to-do except:
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        mWindowManager.executeAppTransition();
        mNoAnimActivities.clear();
        ActivityOptions.abort(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

    // If the most recent activity was noHistory but was only stopped rather
    // than stopped+finished because the device went to sleep, we need to make
    // sure to finish it as we're making a new activity topmost.
    if (mService.isSleepingLocked() && mLastNoHistoryActivity != null &&
            !mLastNoHistoryActivity.finishing) { //-> false
        log("if judge 8 true");
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "no-history finish of " + mLastNoHistoryActivity + " on new resume");
        requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
                null, "resume-no-history", false);
        mLastNoHistoryActivity = null;
    }

    if (prev != null && prev != next) {//-> true
        ......
    }

    // Launching this app's activity, make sure the app is no longer
    // considered stopped.
    try {
        AppGlobals.getPackageManager().setPackageStoppedState(
                next.packageName, false, next.userId); /* TODO: Verify if correct userid */
    } catch (RemoteException e1) {
    } catch (IllegalArgumentException e) {
        Slog.w(TAG, "Failed trying to unstop package "
                + next.packageName + ": " + e);
    }

    // We are starting up the next activity, so tell the window manager
    // that the previous one will be hidden soon.  This way it can know
    // to ignore it when computing the desired screen orientation.
    boolean anim = true;
    if (mIsAnimationBoostEnabled == true && mPerf == null) {
        mPerf = new BoostFramework();
    }

    ......


    ActivityStack lastStack = mStackSupervisor.getLastStack();
    log("lastStack: "+lastStack);//ActivityStack{64d7bc0 stackId=0, 1 tasks}
    if (next.app != null && next.app.thread != null) { // -> false
        ......
    } else {
        log("get in else");
        // Whoops, need to restart this activity!
        if (!next.hasBeenLaunched) {
            next.hasBeenLaunched = true;
        } else {
            if (SHOW_APP_STARTING_PREVIEW) {
                next.showStartingWindow(null, true);
            }
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
        }
        if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
        /*
          * 当前这个方法最终进入这里(ps: 把我找的累的......)
          */
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
    return true;
}

下面进入ActivityStackSupervisor类中的startSpecificActivityLocked()方法。

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);
    //app is null,没有找到指定activity所属应用进程信息

    r.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    /**
      * 执行这里,启动一个新的进程
      */
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

进入ActivityManagerService中的startProcessLocked()方法。

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    log("mthod called startProcessLocked()");
    log("processName : "+processName); //com.jrdcom.filemanager
    log("info : "+info); //ApplicationInfo{21e8530 com.jrdcom.filemanager}
    log("knownToBeDead : "+knownToBeDead); //true
    log("intentFlags : "+intentFlags); //0
    log("hostingType : "+hostingType); //activity
    log("hostingName : "+hostingName); //ComponentInfo{com.jrdcom.filemanager/com.jrdcom.filemanager.activity.FileBrowserActivity}
    log("allowWhileBooting : "+allowWhileBooting);//false
    log("isolated : "+isolated); //false
    log("keepIfLarge : "+keepIfLarge);//true
    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) {
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkTime(startTime, "startProcess: after getProcessRecord");
        log("app : "+app); // app is null
        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { // -> false
            // 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)) { // -> false
                log("if judge 3 true");
                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;
    }

    // app launch boost for big.little configurations
    // use cpusets to migrate freshly launched tasks to big cores
    nativeMigrateToBoost();
    mIsBoosted = true;
    mBoostStartTime = SystemClock.uptimeMillis();
    Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
    mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);

    // 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.
    log("startProcess: name=" + processName
            + " app=" + app + " knownToBeDead=" + knownToBeDead
            + " thread=" + (app != null ? app.thread : null)
            + " pid=" + (app != null ? app.pid : -1));
    // startProcess: name=com.jrdcom.filemanager app=null knownToBeDead=true thread=null pid=-1
    if (app != null && app.pid > 0) { // -> false
        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) { // -> true
        checkTime(startTime, "startProcess: creating new process record");
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) { // -> false
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        app.crashHandler = crashHandler;
        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) { // -> false
        if (!mProcessesOnHold.contains(app)) { // -> false
            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(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");
    return (app.pid != 0) ? app : null;
}

下面进入ActivityManagerService中的startProcessLocked()方法。

/**
  * rom 定制可以在这里统计进程启动相关的信息
  */
private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    long startTime = SystemClock.elapsedRealtime();
    log("method called startProcessLocked()");
    log("app : "+app); //ProcessRecord{93ffdff 0:com.jrdcom.filemanager/u0a105}
    log("hostingType : "+hostingType); //activity
    log("hostingNameStr : "+hostingNameStr); //com.jrdcom.filemanager/.activity.FileBrowserActivity
    log("abiOverride : "+abiOverride); //null
    log("entryPoint : "+entryPoint); // null
    log("entryPointArgs : "+entryPointArgs); //null
    if (app.pid > 0 && app.pid != MY_PID) { // ->false
        checkTime(startTime, "startProcess: removing from pids map");
        synchronized (mPidsSelfLocked) {
            mPidsSelfLocked.remove(app.pid);
            mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        }
        checkTime(startTime, "startProcess: done removing from pids map");
        app.setPid(0);
    }

    if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
            "startProcessLocked removing on hold: " + app);
    mProcessesOnHold.remove(app);

    checkTime(startTime, "startProcess: starting to update cpu stats");
    updateCpuStats();
    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();
        }

        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
        log("uid : "+uid);//10105
        log("mountExternal : "+mountExternal); // 0
        if (!app.isolated) { // -> true
            int[] permGids = null;
            try {
                checkTime(startTime, "startProcess: getting gids from package manager");
                final IPackageManager pm = AppGlobals.getPackageManager();
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DEBUG_TRIAGED_MISSING, app.userId);
                MountServiceInternal mountServiceInternal = LocalServices.getService(
                        MountServiceInternal.class);
                mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
                log("mountExternal : "+mountExternal); // 1
            } 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[2];
            } else {
                gids = new int[permGids.length + 2];
                System.arraycopy(permGids, 0, gids, 2, permGids.length);
            }
            gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
            gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
        }
        checkTime(startTime, "startProcess: building args");
        if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) { // -> false
            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;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // -> false
            debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
            // 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) { // -> false
            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)) { // -> false
            // 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 requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) { // -> true
            requiredAbi = Build.SUPPORTED_ABIS[0];
        }

        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) { // -> false
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }

        app.gids = gids;
        app.requiredAbi = requiredAbi;
        app.instructionSet = instructionSet;

        // Start the process.  It will either succeed and return a result containing
        // the PID of the new process, or else throw a RuntimeException.
        log("entryPoint: "+entryPoint); // null
        boolean isActivityProcess = (entryPoint == null);
        log("isActivityProcess: "+isActivityProcess); //true
        if (entryPoint == null) entryPoint = "android.app.ActivityThread";
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkTime(startTime, "startProcess: asking zygote to start proc");
        /*
          * 进入这里
          */
        Process.ProcessStartResult startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                app.info.dataDir, entryPointArgs);
        checkTime(startTime, "startProcess: returned from zygote!");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        log("app.isolated: "+app.isolated); //false
        if (app.isolated) {
            mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
        }
        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 {
            AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
                    app.info.seinfo, app.info.sourceDir, startResult.pid);
        } catch (RemoteException ex) {
            // Ignore
        }

        // ATT_IQI_CHANGE
        AppStateBroadcaster.sendApplicationStart(app.info.packageName, startResult.pid);

        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 (!isActivityProcess) {
            buf.append(" [");
            buf.append(entryPoint);
            buf.append("]");
        }
        buf.append(" for ");
        buf.append(hostingType);
        if (hostingNameStr != null) {
            buf.append(" ");
            buf.append(hostingNameStr);
        }
        log( buf.toString());
        //Start proc 3886:com.jrdcom.filemanager/u0a105 for activity com.jrdcom.filemanager/.activity.FileBrowserActivity
        if(hostingType.equals("activity")) { // -> true
            BoostFramework perf = new BoostFramework();

            if (perf != null) {
                perf.perfIOPrefetchStart(startResult.pid,app.processName);
            }

            // Start Freq Aggregation boost
            if (mIsFreqAggrEnabled == true && sFreqAggr_init == null
                && sFreqAggr == null) {
               sFreqAggr_init = new BoostFramework();
               sFreqAggr = new BoostFramework();
            }
            if (sFreqAggr_init != null && sFreqAggr != null) {
               sFreqAggr_init.perfLockAcquire(lFreqAggr_TimeOut, lFreqAggr_Init_ParamVal);
               sIsFreqAggrBoostSet = true;
               // Frequency Aggr perflock can only be passed one opcode-pair
               if (lFreqAggr_ParamVal.length == 2) {
                   lFreqAggr_ParamVal[1] = startResult.pid;
                   sFreqAggr.perfLockAcquire(lFreqAggr_TimeOut, lFreqAggr_ParamVal);
               } else {
                   //Opcodes improperly defined. Disable Perflock FA support.
                   sFreqAggr = null;
                   sFreqAggr_init.perfLockRelease();
                   sIsFreqAggrBoostSet = false;
               }
            }

            // Start launch boost v2
            if (mIsLaunchBoostv2_enabled == true && sPerfBoost_v2 == null) {
                sPerfBoost_v2 = new BoostFramework();
            }
            if (sPerfBoost_v2 != null) {
               sPerfBoost_v2.perfLockAcquire(lBoost_v2_TimeOut, lBoost_v2_ParamVal);
               sIsLaunchBoostv2_set = true;
            }
        }

        log("startResult : "+startResult); //android.os.Process$ProcessStartResult@744aa15
        app.setPid(startResult.pid);
        app.usingWrapper = startResult.usingWrapper;
        app.removed = false;
        app.killed = false;
        app.killedByAm = false;
        checkTime(startTime, "startProcess: starting to update pids map");
        ProcessRecord oldApp;
        synchronized (mPidsSelfLocked) {
            oldApp = mPidsSelfLocked.get(startResult.pid);
        }
        log("oldApp : "+oldApp); //null
        // If there is already an app occupying that pid that hasn't been cleaned up
        if (oldApp != null && !app.isolated) { // -> false
            // 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) {
            this.mPidsSelfLocked.put(startResult.pid, app);
            if (isActivityProcess) {
                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");
        if ("activity".equals(hostingType) || "service".equals(hostingType)) { // -> true
            mActivityTrigger.activityStartProcessTrigger(app.processName, startResult.pid);
        }
    } 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");
    }
}

接下来调用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[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}


private static 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[] extraArgs)
                              throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        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_DEBUGGER) != 0) {
            argsForZygote.add("--enable-debugger");
        }
        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_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);

        //TODO optionally enable debuger
        //argsForZygote.add("--enable-debugger");

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

        argsForZygote.add(processClass);

        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }
        Log.i("tz process","argsForZygote list : "+argsForZygote);
        /*
            argsForZygote list : [--runtime-args, --setuid=10105, --setgid=10105, --mount-external-default, --target-sdk-version=24,
                    --setgroups=50105,9997,1023,1015,3003, --nice-name=com.jrdcom.filemanager, --seinfo=default:privapp,
                    --app-data-dir=/data/user/0/com.jrdcom.filemanager, android.app.ActivityThread]
        */

        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

最终进入zygoteSendArgsAndGetResult()这个方法。
这个方法的实质就是通过socket通信与Zygote进行交互。

private static 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.ZygoteInit.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?
        ProcessStartResult result = new 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);
    }
}

前三篇文章都是Binder通信结尾,这篇以socket通信结尾,换种口味~!