android N進程啓動流程(二)(上一個activity的暫停、進程啓動、綁定進程與創建application)

android N進程啓動流程(二)(上一個activity的暫停、進程啓動、綁定進程與創建application)

第二部分將分爲:上一個activity的暫停、進程啓動、綁定進程與創建application

5. 上一個activity的暫停

上一個activity的暫停
圖5.1 上一個activity的暫停

接着章節3.6的startActivityUnchecked中會調用最後有調用resumeFocusedStackTopActivityLocked,我們接下去從這裏開始講解。

5.1 resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java)

resumeFocusedStackTopActivityLocked恢復當前focus的堆棧stack中的頂端活動對象top activity

1) 上面章節3.6中setTaskFromReuseOrCreateNewTask->computeStackFocus->mSupervisor.getStack已經創建了mTargetStack,並將其添加到ActivityDisplay的mStack中去。
2) 章節3.6中moveToFront的insertTaskAtTop中也設置了需要啓動的應用如test2.com.myapplication成爲堆棧頂端Top的進程
3) 章節4.2中setFocusStackUnchecked也設置了mTargetStack爲test2

    //上面章節3.6中setTaskFromReuseOrCreateNewTask已經創建了mTargetStack,
    //章節3.6中moveToFront的insertTaskAtTop中也設置了需要啓動的應用如test2.com.myapplication
    //成爲堆棧頂端Top的進程
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            //targetStack不爲null,而且isFocusedStack也是test2,故此處是會進來的
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        //...
    }

5.2 resumeTopActivityUncheckedLocked(ActivityStack.java)

resumeFocusedStackTopActivityLocked恢復當前focus堆棧stack中的頂端活動對象
1) 此處的stack this對象是test2上一章節5.1中說的mTargetStack
2) 此時是第一次看到resumeTopActivityInnerLocked,故是第一次進入,傳遞的prev是test2.com.myapplication我們先看第一次進入該函數的處理邏輯(第二次的請忽略先)
3) 此處邏輯依次是resumeTopActivityUncheckedLocked->resumeTopActivityInnerLocked->pauseBackStacks
4) 第一次進入由於在pauseBackStacks返回有需要pause的應用,故pausing==true,pauseBackStacks做完不久就直接返回了

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        //....
        result = resumeTopActivityInnerLocked(prev, options);
        //....
    }

    //第一次進來的時候prev是test2.com.myapplication(所以會先pause上一個應用如com.android.launcher);
    //第二次進來是prev是com.android.launcher,此時launcher已經pause了,
    //會進入下一個應用的resume流程(如test2.com.myapplication)
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        //...
        //第一次進來topRunningActivityLocked是test2,第二次進來也是test2,
        //此處是在moveActivityStackToFront中已經設置過了
        final ActivityRecord next = topRunningActivityLocked();

        //...
        //此處allPausedActivitiesComplete是true,不會進入這裏,
        //說明之前已經沒有需要pause的應用(第一次進來mPausingActivity還沒有設置過==null)
        //或者pause完成(第二次進來)
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            …
            return false;
        }

        //...
        //是否有設置標誌位在pausing的時候resume,默認沒有設置都是false
        final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;

        //此處判斷是否有需要pasue的進程(是所有stack而不僅僅是當前stack),
        //第一次進來會pause launcher(launcher的堆棧中有mResumedActivity,
        //但是章節4.2已經將焦點切換到test2)故反饋pausing==true,第二次直接返回pausing==false
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        //mResumedActivity一直都是null(由於當前mTargetStack是新new出來的給進程test2使用),
        //只有在test2 resume之後纔會設置,如在minimalResumeActivityLocked之後設置,故不會走下面的邏輯
        if (mResumedActivity != null) {
            //...
        }

        //第一次走的pausing是true(代表有需要暫停的應用,如launcher),第二次pausing是false
        if (pausing) {
            //...
            //第一次進來到這裏就結束了
            return true;
        //此處一般都是不走的mResumedActivity == null,第二次pausing是false,
        //但是還是有activity繼續resume(allResumedActivitiesComplete返回false)
        } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                mStackSupervisor.allResumedActivitiesComplete()) {
            ...
            return true;
        }

        //第二次時會進來這裏prev != next,此處next代表test2.com.myapplication,
        //prev代表com.android.launcher
        if (prev != null && prev != next) {
            if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)
                    && next != null && !next.nowVisible) {
                //等待prev的界面launcher隱藏,此處在mStackSupervisor的
                //processStoppingActivitiesLocked時纔會remove
                mStackSupervisor.mWaitingVisibleActivities.add(prev);
            } else {
            //...
        }
        //...
        //第二次進來時prev == com.android.launcher
        if (prev != null) {
            //launcher是沒有finishing的,不進入這裏
            if (prev.finishing) {
                //...
            //準備resume test2.com.myapplication時prev代表com.android.launcher,會進來這裏
            } else {
                //prev.task不等於next.task,mLaunchTaskBehind是false,
                //WMS中傳輸類型是TRANSIT_TASK_OPEN
                mWindowManager.prepareAppTransition(prev.task == next.task
                        ? TRANSIT_ACTIVITY_OPEN
                        : next.mLaunchTaskBehind
                                ? TRANSIT_TASK_OPEN_BEHIND
                                : TRANSIT_TASK_OPEN, false);
            }
        } else {
            //...
        }
        //...
        //此處next(test2.com.myapplication)進程都還沒有起來,不會進入這裏
        if (next.app != null && next.app.thread != null) {
            //...
        //next(test2.com.myapplication)進入的是else
        } else {
            //第一次啓動hasBeenLaunched肯定是false,所以會進入此處
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                ...
            }
            //這裏纔是真正啓動test2進程的地方
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
        //...
    }

5.3 pauseBackStacks(ActivityStackSupervisor.java)

pauseBackStacks遍歷ActivityDisplay顯示設備中的所有棧,當循環到luancher的時候,由於launcher已經不是focus的stack棧,但是它的mResumedActivity仍然存在,代表這個activity需要進行pause暫停的操作。

    boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
        //...
        //遍歷stacks當前顯示設備的所有堆棧
        final ActivityStack stack = stacks.get(stackNdx);
        //stack是launcher,isFocusedStack是false,mResumedActivity是launcher不等於null
        if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
            //launcher的stack進行pause的操作,注意resuming是true,dontWait是false,
            //userLeaving是true,在章節3.6 startActivityUnchecked->setInitialState中設置
            someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
                    dontWait);
        //...
    }

5.4 startPausingLocked(ActivityStack.java)

1) startPausingLocked這個函數是啓動應用暫停pause(如此處的是上一個應用launcher),設置當前狀態爲pausing
2) 進入ActivityThread處理暫停任務之前會在eventlog中輸出am_pause_activity的信息,表示將要開始該應用的暫停了
3) 不過最重要的函數還是ActivityThread的schedulePauseActivity,該函數會處理pause任務

    //userLeaving==true, uiSleeping==false, resuming==true, dontWait==false
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        //第一次進來mPausingActivity是null,應用沒有暫停就沒有所謂的mPausingActivity
        if (mPausingActivity != null) {
            //...
        }

        //mResumedActivity是當前resume的activity,此處是launcher
        ActivityRecord prev = mResumedActivity;

        //注意此處pause之後將設置mResumedActivity==null,代表沒有該Stack沒有resume的activity了
        mResumedActivity = null;
        //launcher設置爲正在pause的進程
        mPausingActivity = prev;
        //設置上一個暫停的應用
        mLastPausedActivity = prev;
        //標定該進程在PAUSING狀態
        prev.state = ActivityState.PAUSING;

        //此處next是test2,章節4.2的insertTaskAtTop已經設置過
        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();

        //pause應用會觸發cpu狀態更新,可以使用adb shell dumpsys cpuinfo查詢
        mService.updateCpuStats();

        //prev是launcher,裏面的app和thread都是已經創建的,所有此處會進入
        if (prev.app != null && prev.app.thread != null) {
            try {
                //event log中的am_pause_activity,代表應用的pause開始
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                //cpu前後臺切換,用於耗電統計
                mService.updateUsageStats(prev, false);
                //ActivityThread裏面的方法是handle(異步),此處纔是activity的真正的pause執行的地方
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            //...

        //mPausingActivity就是launcher,所以會進來此處。
        if (mPausingActivity != null) {
            //uiSleeping==false
            if (!uiSleeping) {
                //應用的pause的時候,會暫停接收輸入事件,此時系統觸摸了不反饋給上層
                prev.pauseKeyDispatchingLocked();
            }

            //dontWait==false,章節5.2中設置dontWaitForPause
            if (dontWait) {
                //只有當dontWait是true的時候纔會走這裏,就是不等待pause完成
                completePauseLocked(false);
                return false;
            } else {
                //launcher的最後onpause會走到這裏來
                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
                msg.obj = prev;
                prev.pauseTime = SystemClock.uptimeMillis();
                //設置pause的超時時間爲500ms
                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
                //返回ture,代表有響應的activity正在pausing,
                //故在章節5.2 resumeTopActivityInnerLocked運行完該函數後不久就返回了
                return true;
            }

        } else {
        //...
    }

ps:上面也看到了pause的時候會限制輸入事件,如果應用一直重啓又掛掉又重啓,此時如果不停調用pause/finish的話會限制輸入事件的分發pauseKeyDispatchingLocked,當然這種情況只是極端情況,一般不會出現

5.5 schedulePauseActivity(ActivityThread.java)

1) schedulePauseActivity這個是通過handler(一直想吐槽這個hander也類名也太簡潔了的點吧,一個”H”就搞定)在UI主線程裏面做的事情
2) 主要流程是schedulePauseActivity->PAUSE_ACTIVITY->handlePauseActivity->performPauseActivity->performPauseActivityIfNeeded
3) 我們主要關注performPauseActivityIfNeeded當前activity暫停(這部分本章節講解)、activityPaused通知AMS上一個activity暫停完成(這部分下一章裏講解)。

    //ActivityThread給外部提供的接口,pause暫停是通過應用的主線程進行處理
    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        int seq = getLifecycleSeq();
        //...
        //finished等於false,走的是PAUSE_ACTIVITY,userLeaving==true,dontReport==dontWait==false
        sendMessage(
                finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                token,
                (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                configChanges,
                seq);
    }

    //handler傳遞,調用的是handlePauseActivity
    case PAUSE_ACTIVITY: {
        //...
        //進入pause的處理
        handlePauseActivity((IBinder) args.arg1, false,
                (args.argi1 & USER_LEAVING) != 0, args.argi2,
                (args.argi1 & DONT_REPORT) != 0, args.argi3);
        //...
    } break;

    //finished是false,userLeaving==true,dontReport==false
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        ...
        if (r != null) {
            //userLeaving一般都是true
            if (userLeaving) {
                //會進入此處,會調用activity.performUserLeaving,當離開用戶可視的時候會調用
                performUserLeavingActivity(r);
            }

            //...
            //此處是pause上一個應用launcher,isPreHoneycomb是android3.0之前用的,此處是false
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

            //dontReport一般沒有設置都是false,故一般都是進入此處的
            if (!dontReport) {
                try {
                    //通知AMS上一個應用完成pause了,這裏接下去就會resume下一個應用(先啓動進程),
                    //下一章會講到
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }


    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {

        //saveState是false,不跑這裏
        if (!r.activity.mFinished && saveState) {
            callCallActivityOnSaveInstanceState(r);
        }

        //這裏纔是pause activity的地方
        performPauseActivityIfNeeded(r, reason);

        // 將當前pause的應用的OnActivityPausedListener暫停監聽去除
        ArrayList<OnActivityPausedListener> listeners;
        synchronized (mOnPauseListeners) {
            listeners = mOnPauseListeners.remove(r.activity);
        }
        //...
        for (int i = 0; i < size; i++) {
            //此處是調用註冊了該activity thread的監聽onPaused的回調,
            //如NfcAdapter.java中的ActivityThread.currentActivityThread()
            //.registerOnActivityPausedListener(activity,mForegroundDispatchListener);
            listeners.get(i).onPaused(r.activity);
        }
        //...
    }

5.6 performPauseActivityIfNeeded(ActivityThread.java)

1) 通過代理類Instrumentation調用callActivityOnPause,其調用的是activity的performPause(分別會調用mFragments.dispatchPause、activity的onPause,application的ActivityLifecycleCallback生命週期回調方法onActivityPaused)
2) OnPause調用完成後會在event log中寫入am_on_paused_called,代表activity的OnPause已經完成(如果你使用onpause有問題,可以從am_pause_activity到am_on_paused_called之間所花費的時間做初步判斷)
3) 注意OnPause完成之後paused會賦值爲true,代表當前是暫停狀態

    private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        if (r.paused) {
            //如果之前paused==true了就直接返回,activitythread創建設置成false,
            //oncreate將設置成ture,onresume將設置成false
            //上一個activity的上一個狀態是onresume,正在pause,故此處是paused==false
            return;
        }

        try {
            //這裏解釋一下mCalled,這個值是用來判斷是否有調用activity生命週期的函數
            r.activity.mCalled = false;

            //這就就是具體調用activity的performPause的地方
            //(包括mFragments.dispatchPause、activity的onPause,
            //application的ActivityLifecycleCallback生命週期回調方法onActivityPaused),
            //運行完之後mCalled會設置成true
            mInstrumentation.callActivityOnPause(r.activity);

            //寫event log,am_on_paused_called,說明pause已經調用
            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName(), reason);
            //...
        //運行了之後設置標緻位paused==true
        r.paused = true;
    }

到目前爲止基本上把上一個activity的OnPause流程講解完了。

6. 進程啓動(一)am_proc_start

講了一大堆,是不是發現我們需要啓動的進程test2怎麼還沒到呢,流程有點長,目前android的默認架構就是這樣,大家耐心的繼續看下去,我們這一章節就開始講到進程啓動(這部分應該很多文章都有提到,瞭解的同學可以不必細看)。

其實這些流程只是學習作用,對我們瞭解android架構有一定幫助,解決問題(僅針對那些代碼不規範自己改出來的問題)時有幫助,不過這些都不是關注的重點,我們關注的是如何優化整個流程,如果沒有明確這個目的,對我們來說是沒有很大提升的。路漫漫其修遠,我們先把流程梳理清楚,一步步來…

進程啓動(一)
圖6.1 進程啓動(一)

6.1 activityPaused(ActivityManagerService.java)

在章節5.5中的ActivityManagerNative.getDefault().activityPaused(token),這個函數的意思是告訴AMS,上一個應用已經完成OnPause了,接下去的工作可以繼續下去。

    public final void activityPaused(IBinder token) {
        //...
        //調用的是ActivityStack的activityPausedLocked,第二個參數timeout==false
        stack.activityPausedLocked(token, false);
        //...
    }

其中token是上一個應用的Ibinder對象,我們認爲是launcher就行了

6.2 activityPausedLocked(ActivityStack.java)

1) 通知launcher自身Stack棧中的activityPausedLocked,當前已經完成pause暫停操作了,可以將之前章節5.4中說的PAUSE_TIMEOUT_MSG超時去掉。
2) mPausingActivity也是在章節5.4開始暫停的時候設置的,如果發現真正暫停的應用和完成暫停的應用是一個,代表暫停完成,調用completePauseLocked,並傳遞resumeNext==true,代表需要resume下一個應用

    //AMS調用的timeout==false
    final void activityPausedLocked(IBinder token, boolean timeout) {
        //代表該task仍在堆棧中,此時launcher是launcher的paused
        final ActivityRecord r = isInStackLocked(token);
        if (r != null) {
            //pause已經完成,不需要PAUSE_TIMEOUT_MSG了
            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            //之前在startPausingLocked的時候設置了當前pause的應用,
            //這個時候AMS返回代表pause成功,會進入這裏
            if (mPausingActivity == r) {
                //pause成功,傳遞的參數是resumeNext==true,代表需要resume下一個應用
                completePauseLocked(true);
                return;
            } else {
            ...
    }

6.3 completePauseLocked(true)

1) mWaitingVisibleActivities這裏代表的是需要隱藏的可視界面,到目前爲止我們沒有設置過,這個是在第二次進入章節5.2 resumeTopActivityInnerLocked的時候纔會設置。(準備resume恢復下一個應用test2,上一個應用launcher就會放入等待隱藏的列表mWaitingVisibleActivities中)
2) 非睡眠或者關機狀態的時候會進入下一個activity的resume操作resumeFocusedStackTopActivityLocked
3) 最後ensureActivitiesVisibleLocked(ActivityStackSupervisor.java/ActivityStack.java)會更新界面相關操作,屬於WMS範疇,本文不過多涉及
{

    //啓動進程後會更新界面,此處僅僅把流程列出來,由於這篇文章本身太長了,不想在額外增加內容
    ensureActivitiesVisibleLocked
        ->ensureActivityConfigurationLocked
        ->makeVisibleAndRestartIfNeeded->startSpecificActivityLocked()
        ->screenshotActivitiesLocked
        ->makeInvisible->addToStopping->scheduleIdleLocked

}

    private void completePauseLocked(boolean resumeNext) {
        //prev,mPausingActivity是launcher
        ActivityRecord prev = mPausingActivity;
        //prev是不等於null的會進來這裏
        if (prev != null) {
            //state在startPausingLocked時設置了ActivityState.PAUSING,
            //所以一般情況wasStopping都是false
            final boolean wasStopping = prev.state == ActivityState.STOPPING;

            //重新設置標誌位是ActivityState.PAUSED,這個是已經暫停的狀態
            prev.state = ActivityState.PAUSED;

            //一般情況launcher啓動應用,prev.finishing==false,故不會進入這裏面
            if (prev.finishing) {
                //...
            //prev.app是launcher
            } else if (prev.app != null) {
                //pause com.android.launcher時,此處會進來,prev就是com.android.launcher,
                //wasStopping==false,visible==true

               //第一次進來時mWaitingVisibleActivities還沒有prev(resumeTopActivityInnerLocked
               //第二次運行是纔會設置),故不會進來這個
                if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) {
                    //...
                }

                //這個是在pause之後重新啓動,一般都是false
                if (prev.deferRelaunchUntilPaused) {
                    //...
                //wasStopping==false,也不走這裏
                } else if (wasStopping) {
                    //...
                //由於visible==true,也不是在睡眠狀態,這裏也不會進來
                } else if ((!prev.visible && !hasVisibleBehindActivity())
                        || mService.isSleepingOrShuttingDownLocked()) {
                    //...
                }
            } else {
                //這裏實在app在onpause過程中died掉纔會進入,正常不會運行
                prev = null;
            }

            if (prev != null) {
                //如果界面是凍屏的話,由於界面不再可見,將移除凍屏狀態
                prev.stopFreezingScreenLocked(true /*force*/);
            }
            //mPausingActivity設置爲null,此時pause已經全部完成
            mPausingActivity = null;
        }

        //上面都是AMS進來的activityPausedLocked,resumeNext == true
        if (resumeNext) {
            //之前的moveActivityStackToFront中有設置過focus stack爲test2
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();

            //非睡眠或者關機會進入這裏
            if (!mService.isSleepingOrShuttingDownLocked()) {
                //一般進入這裏,會resume 下一個應用(next),
                //同步的,執行了Process.start之後纔會繼續往下跑
                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
            } else {
            ...
        }

        if (prev != null) {
            //重新恢復接收輸入事件
            prev.resumeKeyDispatchingLocked();

            //如果是在使用電池
            if (prev.app != null && prev.cpuTimeAtResume > 0
                    && mService.mBatteryStatsService.isOnBattery()) {
                //cpuTimeAtResume是在activity resume的時候設置的,
                //代表從resume到pause的時間,將作爲前臺運行時間
                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
                        - prev.cpuTimeAtResume;
                //...
                //addForegroundTimeLocked這個是電量估算的時候用的,判斷該activity前臺運行的時常
                if (ps != null) {
                    ps.addForegroundTimeLocked(diff);
                //...
            }
            //當前已經是onpause暫停了,清空進入resume的時間
            prev.cpuTimeAtResume = 0;
        }

        //有界面可視的時候mAppVisibilitiesChangedSinceLastPause==true(setVisible時設置),
        //所以這裏會進來
        if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause) {
            //...
            //launcher已經pause,設置mAppVisibilitiesChangedSinceLastPause==false
            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
        }

        //最後是更新顯示界面,這裏是第一次調用ensureActivitiesVisibleLocked,
        //遍歷所有stack的ensureActivitiesVisibleLocked
        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
    }

6.4 resumeFocusedStackTopActivityLocked/startSpecificActivityLocked(ActivityStackSupervisor.java)

resumeFocusedStackTopActivityLocked在章節5.1-5.2已經看過,此處傳遞的targetStack是test2,pre是launcher,resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java) -> resumeTopActivityUncheckedLocked(ActivityStack.java) -> resumeTopActivityInnerLocked -> startSpecificActivityLocked(ActivityStackSupervisor.java),啓動的是next==test2

這裏就不翻回去講了,接下去講startSpecificActivityLocked(ActivityStackSupervisor.java)這個啓動應用的函數(注意此處是第一次進入,章節6.3提到的那一次是第二次進入,是在之後)

    //r==test2,andResume==true,checkConfig==true
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        //...
        //當進程都未啓動時不走這裏,thread肯定是null,熱啓動相關邏輯本次不討論
        if (app != null && app.thread != null) {
            ...
        }
        //AMS中去啓動進程
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

6.5 startProcessLocked(ActivityManagerService.java)

重要看到startProcessLocked啓動進程相關名字,這個是AMS的啓動進程的api。
先關注第一次進入的邏輯:
1) 新建一個進程對象的實例new ProcessRecord,該對象可以代表一個進程
2) 判斷應用是32位還是64位的,用於虛擬機參數配置
3) Process.start進程啓動
4) event log寫入am_proc_start,代表進程已經啓動,這句話出來的時候應用進程已經創建

    //9個參數(r.processName==test2, r.info.applicationInfo, true, 0, 
    //"activity", r.intent.getComponent(), false, false, true)
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        //注意此處entryPoint==null
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

    //14個參數,新建ProcessRecord
    final ProcessRecord startProcessLocked(String processName, ...) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        //isolated(孤立應用)是false,knownToBeDead是true
        if (!isolated) {
            //第一次進來app肯定是null
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            //...

            //設置了後臺運行,桌面啓動應用一般都不會走這裏
            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                ...
            } else {
                //重新計算崩潰次數(crash大於等於2次服務將不會再啓動)
                mAppErrors.resetProcessCrashTimeLocked(info);
                //...
            }
        }

        //這個是用來設置啓動進程時cpu的策略,可以加快app啓動速度
        //默認沒有用到,需要設置USE_SCHED_BOOST纔會生效
        nativeMigrateToBoost();

        //3s鍾後會關閉啓動進程的cpu策略,同樣此處默認沒有用到
        mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);

        //第一次進入時沒有啓動過app/thread是null,pid是沒有的.
        //第二次進來時此處app是有了,pid也生成了,但是thread還沒有

        //第一次沒啓動不走這裏,第二次會進來
        if (app != null && app.pid > 0) {
            //knownToBeDead是true,第二次進來app.thread還是null,故會進來,
            //第二次是從章節6.3中ensureActivitiesVisibleLocked調用過來的
            if ((!knownToBeDead && !app.killed) || app.thread == null) {
                //第二次進程已經創建了,直接返回
                //...
                return app;
            }
            //...
        }

        //...
        //第一次走這裏,app是null
        if (app == null) {
            //這個是google的,用於調試卡頓的,不過除了特別有問題一般情況不會出現問題,
            //50ms去掉系統或許更快,如果是給用戶的穩定版本可以考慮把這段調試代碼刪除
            checkTime(startTime, "startProcess: creating new process record");

            //此處是new ProcessRecord
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            //...
            //新建ProcessRecord完成,該監控操作(newProcessRecordLocked)完成
            checkTime(startTime, "startProcess: done creating new process record");
        }

        //監控進程啓動的時常是否超時
        checkTime(startTime, "startProcess: stepping in to startProcess");
        //這裏纔是真正的啓動進程的地方
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");

        //如果有pid產生代表進程創建完成
        return (app.pid != 0) ? app : null;
    }

    //真正啓動進程的地方
    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        //...
        if (app.pid > 0 && app.pid != MY_PID) {//第一次啓動app.pid == -1,不走這裏
            ...
        }

        //...
        updateCpuStats();//啓動進程也會更新CPU狀態

        try {
            try {
                //用於檢測是否可以啓動,如:是否安裝,是否正在凍屏等
                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
            }

            //isolated初始值是false
            if (!app.isolated) {
                //...
                //返回應用用戶組的gid,如果是uid不一樣,同一個應用該值也會不一樣
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DEBUG_TRIAGED_MISSING, app.userId);

                MountServiceInternal mountServiceInternal = LocalServices.getService(
                        MountServiceInternal.class);

                //獲取應用讀寫外部存儲的權限
                //如果是孤立應用(uid是99000-99999)將返回MOUNT_EXTERNAL_NONE;
                //能讀返回MOUNT_EXTERNAL_READ,能寫返回MOUNT_EXTERNAL_WRITE
                mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
                //...
            }

            //...
            //android:multiArch="true"代表所有架構都支持,一般都不設置,
            //一般應用庫文件需要判斷是否32位還算64位,判斷方法使用
            //com_android_internal_content_NativeLibraryHelper.cpp的findSupportedAbi
            //requiredAbi就是爲了兼容32位&64位系統設計的
            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
            if (requiredAbi == null) {
                //此處如果應用沒有設置實在32位還是64位運行的化,
                //默認使用屬性值ro.product.cpu.abilist的第一個值arm64-v8a(64bit),
                //armeabi-v7a(32bit),armeabi(32bit)
                requiredAbi = Build.SUPPORTED_ABIS[0];
            }

            String instructionSet = null;
            if (app.info.primaryCpuAbi != null) {
                //通過應用的庫文件獲取虛擬機要使用那種參數
                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
            }


            //上面傳遞的entryPoint==null,isActivityProcess==true
            boolean isActivityProcess = (entryPoint == null);

            //將ActivityThread作爲應用默認的入口函數entryPoint
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";

            //此處纔是調用Process.start啓動進程的地方
            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);//此處纔是調用Process.start啓動進程的地方

            //此處就是event log中am_proc_start
            EventLog.writeEvent(EventLogTags.AM_PROC_START,
                    UserHandle.getUserId(uid), startResult.pid, uid,
                    app.processName, hostingType,
                    hostingNameStr != null ? hostingNameStr : "");


            //設置進程的pid
            app.setPid(startResult.pid);

            //一般usingWrapper==false
            app.usingWrapper = startResult.usingWrapper;

            //代表正在運行
            app.removed = false;
            app.killed = false;

            //代表沒有給AMS殺死
            app.killedByAm = false;

            synchronized (mPidsSelfLocked) {
                //process start之後就會有pid了,此處是test2.com.myapplication的pid會生成
                //會將該pid放入AMS的pid列表中
                this.mPidsSelfLocked.put(startResult.pid, app);

                if (isActivityProcess) {//isActivityProcess==true
                    //10s沒有啓動將不再啓動,該app,Process.start虛擬機進程創建是同步的,
                    //但是attachApplicationLocked是異步的,在attachApplication的時候
                    //會remove這個超時PROC_START_TIMEOUT_MSG
                    mHandler.sendMessageDelayed(msg, startResult.usingWrapper
                            ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
                ...
    }

7. 進程啓動(二)Process.start

Process.start這個是新建進程通用的系統方法,代碼位置:
frameworks/base/core/java/android/os/Process.java。
接下去從這個開始,這裏面大家熟悉的內容可能更多。

進程啓動(二)
圖7.1 進程啓動(二)

7.1 Process.start(Process.java)

我們注意傳遞的參數processClass是android.app.ActivityThread,niceName是processName,debugFlags一般都是等於0,mountExternal代表是否可讀寫外部存儲,targetSdkVersion是這個應用的targetSdkVersion,seInfo是簽名相關(默認是”default”),abi是這個應用要運行的cpu架構(32還是64位),instructionSet是指的是arm或者arm64,appDataDir一般指的是/data這個目錄,zygoteArgs==null。

後面這些參數都會有用到,對於理解流程有很大的幫助。

    //processClass是android.app.ActivityThread,niceName是processName,
    //debugFlags一般都是等於0,mountExternal代表是否可讀寫外部存儲,
    //targetSdkVersion是這個應用的targetSdkVersion,seInfo是簽名相關(默認是”default”),
    //abi是這個應用要運行的cpu架構(32還是64位),instructionSet是指的是arm或者arm64,
    //appDataDir一般指的是/data這個目錄,zygoteArgs==null
    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);
        //...
    }

7.2 startViaZygote-> zygoteSendArgsAndGetResult

1) startViaZygote通將參數全部轉化成Zygote的數組String
2) openZygoteSocketIfNeeded/zygoteSocket.connect創建Socket鏈接,並獲取輸入輸出流對象
3) zygoteSendArgsAndGetResult通過Socket與底層交互,傳遞相應的事件內容,並獲取返回的結果

    private static ProcessStartResult startViaZygote(final String processClass,
        //...
        ArrayList<String> argsForZygote = new ArrayList<String>();
        //...添加虛擬機參數
        //最後添加的是ActivityThread應用的入口類
        argsForZygote.add(processClass);

        //extraArgs==null,所以後面沒有參數了
        if (extraArgs != null) {
            for (String arg : extraArgs) {
                argsForZygote.add(arg);
            }
        }

        //注意openZygoteSocketIfNeeded是connect Socket,
        //zygoteSendArgsAndGetResult是向Socket傳遞參數
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }

    private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                //ZYGOTE_SOCKET的名字是"zygote",連接socket
                primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
            //...
    }

    public static ZygoteState connect(String socketAddress) throws IOException {
        //...
        try {
            //這裏是connect的地方,會通知相應的鏈接對象
            zygoteSocket.connect(new LocalSocketAddress(socketAddress,
                    LocalSocketAddress.Namespace.RESERVED));

            //輸入流,是用來讀東西的,例如設備有數據輸出,然後我們讀取
            zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());

            //輸出流是用來寫東西的,例如寫東西然後輸出到什麼位置
            zygoteWriter = new BufferedWriter(new OutputStreamWriter(
                    zygoteSocket.getOutputStream()), 256);
        //...
    }

    private static ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            //...
           //第一個先寫的是參數大小
            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();
            }

            //清空輸出流,並寫入,運行完成之後代表寫入成功,此時Socket會接受到相應消息
            writer.flush();

            //...
            //讀取返回的pid數據
            result.pid = inputStream.readInt();
            //讀取返回的usingWrapper數據
            result.usingWrapper = inputStream.readBoolean();
            ...
    }

7.3 ZygoteInit.main(ZygoteInit.java)

1) 開機運行app_process進程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main,Zygote受精卵進程是由init進程創建,如下通過ps可知:init進程是Zygote64受精卵進程的父進程,而system_server是通過zygote64受精卵進程創建的。(pid是該進程的id,ppid是其父進程的id)

USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAME
root      1     0     28524  1932  SyS_epoll_ 0000000000 S /init
root      428   1     1771768 22020 poll_sched 0000000000 S zygote64   //此處代表是64bit的
system    996   428   2086288 190084 SyS_epoll_ 0000000000 S system_server

2) 獲取當前操作系統的32&64位架構abiList,這個在socket connect的時候用於
2) 註冊zygote的LocalServerSocket對象(Socket的服務端,可以給別人connect)
3) 啓動系統服務startSystemServer
4) 等待Socket消息的通知來執行相應的任務runSelectLoop
5) MethodAndArgsCaller的run方法

    //開機運行app_process進程(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main
    public static void main(String argv[]) {
        //...
        try {
            //Socket的名字是zygote
            String socketName = "zygote";
            String abiList = null; 
            for (int i = 1; i < argv.length; i++) {
                //第一次進來會設置startSystemServer==true
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    //讀的是系統屬性ro.product.cpu.abilist64或者ro.product.cpu.abilist32裏面的值
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                //...

            //android的Socket名字:ANDROID_SOCKET_ + zygote
            registerZygoteSocket(socketName);

            //event log中會出現boot_progress_preload_start
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());

            //重新加載Cache,Classes,Resources,OpenGL,SharedLibraries,
            //TextResources,WebView,AndroidKeyStoreProvider
            preload();

            //event log中會出現boot_progress_preload_end
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            //...
            //做GC,清除一些軟引用對象
            gcAndFinalize();
            //...

            //在初始化時unmount根目錄"/storage"
            Zygote.nativeUnmountStorageOnInit();

            //允許zygote創建進程
            ZygoteHooks.stopZygoteNoThreadCreation();

            //如果需要啓動系統服務則進入這裏
            if (startSystemServer) {
                //啓動系統服務system_server,先後調用fork順序是init
                //->zygote64(64位系統)->system_server,如果是系統進程的話,
                //這裏是永遠不會返回的startSystemServer->handleSystemServerProcess
                //->RuntimeInit.zygoteInit->SystemServer.main/run->Looper.loop()
                //->(pollInner/epoll_wait)Looper.cpp,
                //這個除了Loop裏面調用mQueue.quit是不會退出的
                startSystemServer(abiList, socketName); 
            }

            //會跑下來的是zygote進程,zygote進程會一直在此運行
            runSelectLoop(abiList);

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            //對於此處zygote frok的子進程會進入此處,拋出MethodAndArgsCaller異常,
            //會執行run方法,其實是反射調用ActivityThread.main,這個後面會講到
            caller.run();
        //...
    }

ps: Zygote進程是用來fork各個子進程的,如system_server就是其創建的,其中zygote64是所有64位進程的父進程,zygote是所有32位進程的父進程。

7.4 runSelectLoop

runSelectLoop循環等待Socket的數據反饋,這裏寫的是Select的Loop,目前androidN使用的方法是Os.poll不再有1024個Socket的限制(androidL和之前的版本使用的是select方法),後續android版本升級的話可能使用epoll(目前上層的Looper、MessageQueue就是使用epoll)

1) 循環遍歷等待Socket緩衝區有可讀的數據
2) Socket.connect時會創建新的ZygoteConnection
3) ZygoteConnection執行runOnce
4) 創建子進程後,子進程退出循環,父進程繼續等待下一個Socket數據

    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        //...

        // sServerSocket是AMS Process.java中的ZYGOTE_SOCKET鏈接的對象, 用來創建進程
        //sServerSocket是LocalServerSocket,代表整個socket
        //fds是所有zygote Socket相關的文件描述符
        fds.add(sServerSocket.getFileDescriptor());

        //peers是ZygoteConnection對象,是zygote鏈接之後的對象
        peers.add(null);

        while (true) {
            //...
            //events代表等待的事件類型,POLLIN類型代表我們只關心緩衝區是否有數據可讀
            pollFds[i].events = (short) POLLIN;

            //...
            try {
                //poll函數與select類似都是,可以監視多個描述符,-1代表永不超時,
                //輪詢一遍之後等待,當設備驅動發生自身資源可讀寫後,會喚醒其等待隊列上睡眠的進程
                Os.poll(pollFds, -1);
            }
            //...

            for (int i = pollFds.length - 1; i >= 0; --i) {
                //revents域是文件描述符的操作結果事件掩碼,POLLIN代表有數據可讀
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }

                //i==0是就是外部有創建socket的時候,如Socket.connect,
                //這個時候Os.poll中LocalServerSocket會有數據返回,
                //此時LocalServerSocket會accept並創建新的ZygoteConnection
                if (i == 0) {
                    //創建新的受精卵的Socket鏈接ZygoteConnection
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    //添加到ZygoteConnection數組peers
                    peers.add(newPeer);
                    //添加到zygote Socket相關的文件描述符數組中去
                    fds.add(newPeer.getFileDesciptor());

                //非第一次運行時,如果之前創建的Socket鏈接對象ZygoteConnection有數據可以讀,
                //如OutputStream(zygoteWriter就是輸出流)有寫入,那麼此處會有數據,
                //進入runOnce函數。
                } else {
                    //創建子進程會拋出MethodAndArgsCaller的異常,
                    //給ZygoteInit.main捕獲,然後運行ActivityThread的main函數,
                    //子進程拋出異常後退出該循環,但是Zygote父進程還算會繼續循環的
                    boolean done = peers.get(i).runOnce();

                    //創建子進程後,父進程也就是zygote進程纔會進入這裏
                    //...
                }
            }
        }
    }

runSelectLoop函數就是在監聽Socket端是否有數據可以讀,如果有數據來了,那麼就是創建進程,這個Zygote進程主要作用就是創建進程(子進程的一些基本信息都不用再初始化,因爲Zygote已經初始過了,相當於優化了啓動進程的流程)。

7.5 runOnce(ZygoteConnection.java)

1) 讀取相應的參數列表
2) 創建子進程forkAndSpecialize(Zygote.forkAndSpecialize -> com_android_internal_os_Zygote_nativeForkAndSpecialize/ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp)),通過jni調用com_android_internal_os_Zygote_nativeForkAndSpecialize,最後調用的是fork函數,該函數用於創建進程,具體在這裏不展開,具體可以參考之前的一篇文章Android上層如何調用一個底層函數的章節2.1.3 com_android_internal_os_Zygote.cpp本地函數裏面有關於fork的講解。最終子進程返回的是pid==0,父進程返回的是子進程的pid。
3) 處理父進程的內容handleParentProc,如返回給AMS章節6.5中startProcessLocked的Process.start,其值是Process.ProcessStartResult startResult,包含子進程pid
4) 處理子進程的內容handleChildProc,這個放在下一節講解

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ...
        try {
            //讀取相應的參數列表
            args = readArgumentList();
            descriptors = mSocket.getAncillaryFileDescriptors();
        }
        //...
        //invokeWith==null,目前沒有設置
        if (parsedArgs.invokeWith != null) {
            //...
        }

        //...
        int [] fdsToClose = { -1, -1 };
        FileDescriptor fd = mSocket.getFileDescriptor();
        if (fd != null) {
            //客戶端的文件描述符
            fdsToClose[0] = fd.getInt$();
        }
        fd = ZygoteInit.getServerSocketFileDescriptor();
        if (fd != null) {
            //服務端的文件描述符
            fdsToClose[1] = fd.getInt$();
        }

        //調用native fork進程的地方
        //此處是fock進程(Zygote.forkAndSpecialize
        //->com_android_internal_os_Zygote_nativeForkAndSpecialize
        //->ForkAndSpecializeCommon/fork(com_android_internal_os_Zygote.cpp))
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
        //...
        try {
            //如果是子進程pid會等於0,父進程此處pid會返回子進程的pid
            if (pid == 0) {
                //...
                //處理子進程邏輯
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

                //子進程是永遠不會到這個位置來的,因爲之前已經拋出MethodAndArgsCaller異常
                return true;
            } else {
                //...
                //處理父進程邏輯
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        ...
    }

    private String[] readArgumentList()
            throws IOException {
        //...
        try {
            //讀取第一個參數
            String s = mSocketReader.readLine();
            //第一個參數上面章節7.2 Process.java中zygoteSendArgsAndGetResult寫的就是參數個數
            argc = Integer.parseInt(s);
        }
        //傳遞的參數最多是1024個,超過的話系統可能受到DOS攻擊
        if (argc > MAX_ZYGOTE_ARGC) {
            throw new IOException("max arg count exceeded");
        }
        for (int i = 0; i < argc; i++) {
            //讀出每一個參數返回result數組中去
            result[i] = mSocketReader.readLine();
            ...
    }

    private boolean handleParentProc(int pid,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {
        if (pid > 0) {
            //如果返回的pid大於0,說明子進程創建成功,此時設置子進程的pid
            setChildPgid(pid);
        }

        //...
        try {
            //傳遞pid回去,最後寫入章節7.2中zygoteSendArgsAndGetResult的result.pid
            mSocketOutStream.writeInt(pid);
            //傳遞是否wrapped進程,此處一般都是false
            mSocketOutStream.writeBoolean(usingWrapper);
        }
        //...
        return false;
    }

8. 綁定進程am_proc_bound

上一章節我們知道了Process.start用於創建進程,父進程會直接返回子進程的pid,那麼接下去我們需要從子進程處理的內容開始分析,看看子進程是怎樣關聯到上層的application中去的,這裏講解第一步am_proc_bound

這裏寫圖片描述
圖8.1 綁定進程

8.1 handleChildProc(ZygoteConnection.java)

1) 關閉相應的子進程Socket鏈接
2) 設置進程的名字,這個時候通過ps就可以看到進程名字變成應用聲明的進程(如果沒有定義android:process那麼默認該進程名字就是應用的包名)
3) RuntimeInit.zygoteInit子進程的初始化

    private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
        //關閉自己的Socket
        closeSocket();
        //關閉ZygoteInit中服務端的Socket
        ZygoteInit.closeServerSocket();
        //...
        if (parsedArgs.niceName != null) {
            //自己設置自己的名字,此處設置進程名字爲之前傳進來的processName
            Process.setArgV0(parsedArgs.niceName);
        }

        //這裏是不運行的
        if (parsedArgs.invokeWith != null) {
            //...
        //此處會進來
        } else {
            //運行初始化RuntimeInit中的進程(受精卵)初始化zygoteInit
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }

ps:Process.setArgV0會通過prctl(PR_SET_NAME…),裁剪後(process_name.c),只保留processName後面15個字符(kernel實際還會裁剪到最後一個字符,其實是14個字符),設置進程名字(內核標識進程的名字是task_struc->comm).
進程的名字在某些地方顯示不是無限長的,如在systrace顯示的進程名字就不超過15個字符。

8.2 zygoteInit(RuntimeInit.java)

1) log重定向redirectLogStreams
2) 通用設置初始化commonInit
3) 初始化zygote:nativeZygoteInit
4) 應用初始化applicationInit

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        //重新定向log的輸入地方,此處設置log輸出到Android log中
        redirectLogStreams();

        //一些通用設置的初始化
        commonInit();

        //初始化zygote,這裏AppRuntime繼承的是AndroidRuntime,運行的是啓動線程池startThreadPool
        nativeZygoteInit();

        //應用初始化,此處是接下來運行的地方
        applicationInit(targetSdkVersion, argv, classLoader);
    }

    private static final void commonInit() {
        //...
        //設置默認的異常捕獲
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
        TimezoneGetter.setInstance(new TimezoneGetter() {
            @Override
            public String getId() {
                //設置時區id
                return SystemProperties.get("persist.sys.timezone");
            }
        });
        //設置時區
        TimeZone.setDefault(null);
        LogManager.getLogManager().reset();
        //Android log相關初始化
        new AndroidConfig();
        String userAgent = getDefaultUserAgent();
        //網絡用戶代理初始化
        System.setProperty("http.agent", userAgent);
        //網絡Socket相關
        NetworkManagementSocketTagger.install();
        //...
        initialized = true;
    }

8.3 applicationInit

1) 設置虛擬機GC回收比例,正在使用的對象/堆棧大小 = 0.75
2) 設置虛擬機sdk的版本號
3) 獲取相應的參數,如args.startClass就是在章節7.2 startViaZygote設置的processClass(ActivityThread)
4) 通過反射查找ActivityThread的main函數,並將其作爲MethodAndArgsCaller異常的參數

    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        //設置退出時不調用onExit()函數
        nativeSetExitWithoutCleanup(true);

        //設置GC回收後的比例,正在使用的對象/堆棧大小 = 0.75,對應於dalvik.vm.heaptargetutilization
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        //設置sdk的版本號,這個是進程啓動Process.start時就傳遞過來的
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        //獲取相應的參數,如args.startClass就是第一個非"--"開頭的參數
        final Arguments args;
        try {
            args = new Arguments(argv);
        }

        //...
        //反射調用main函數,注意startClass是Process.start時傳遞進來的android.app.ActivityThread
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        //...
        //查找android.app.ActivityThread類
        cl = Class.forName(className, true, classLoader);

        //...
        //查找其中的main函數
        m = cl.getMethod("main", new Class[] { String[].class });

        //...
        //獲取函數的調用屬性
        int modifiers = m.getModifiers();

        //必須是靜態而且是public的方法,否則拋出RuntimeException異常
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        //拋出MethodAndArgsCaller異常
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

在章節7.3 ZygoteInit.main方法裏面有捕獲MethodAndArgsCaller異常,並調用MethodAndArgsCaller的run方法。

8.4 MethodAndArgsCaller.run()

反射調用ActivityThread的main靜態函數

   public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        //...
        public MethodAndArgsCaller(Method method, String[] args) {
            //mMethod是ActivityThread的main方法
            mMethod = method;
            //mArgs一般都是null
            mArgs = args;
        }
        public void run() {
            try {
                //調用方法method,傳遞的是args參數,傳遞第一個參數是類對象爲null,代表靜態函數
                mMethod.invoke(null, new Object[] { mArgs });
            //...

到這裏進程已經啓動完成,將進入應用相關流程

8.5 MethodAndArgsCaller.run()

1) 消息隊列初始化Looper.prepareMainLooper
2) 新建ActivityThread並附着thread.attach
3) 進入消息隊列的循環Looper.loop

    public static void main(String[] args) {
        //默認是沒有用到SamplingProfilerIntegration的,
        //該類用於監聽性能數據,包含進程名字、應用信息、線程啓動與關閉,
        //還有默認persist.sys.profiler_ms毫秒dump一次該進程堆棧信息
        SamplingProfilerIntegration.start();

        //在嚴格模式或者調試的時候打開,默認不打卡
        CloseGuard.setEnabled(false);

        //初始化環境(這裏主要是存儲設備的環境,用user id初始化)
        Environment.initForCurrentUser();

        //主要是libcore中使用event log的方法,Reporter的report類似於EventLog.writeEvent
        EventLogger.setReporter(new EventLoggingReporter());

        //配置文件目錄在/data/misc/user/1000
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        //設置認證相關的目錄cacerts-added,cacerts-removed
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        //設置進程名字爲<pre-initialized>,這個很快在handleBindApplication時就會給修改
        Process.setArgV0("<pre-initialized>");

        //消息隊列初始化,主進程是不允許退出的,無法調用MessageQueue.quit退出
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        //新建一個ActivityThread並attach附着,這個跟接下去的attachApplication相關
        thread.attach(false);

        if (sMainThreadHandler == null) {
            //獲取thread的handler,將其作爲應用的主線程
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            //用戶調試log,用於消息隊列Message的事件分發log輸出,
            //調試消息隊列的時候可以打開
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        //Looper.loop()裏面是個for (;;)死循環,只要Message不爲null,會一直運行
        //Looper.loop() -> MessageQueue.next() 
        //-> nativePollOnce(android_os_MessageQueue.cpp) 
        //->(pollOnce/pollInner/epoll_wait) Looper.cpp,
        //這個Message==null情況只有調用MessageQueue.quit纔會發生,
        //目前沒有看到主動調用MessageQueue.quit,故這個消息隊列循環是不會退出的
        Looper.loop();

        //如果進入到這裏代表程序出錯了,這裏程序正常運行是不會進來的
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

在調用靜態方法ActivityThread.main之後會新建一個ActivityThread對象,相當於該進程的主線程(UI線程),創建之後首先跑的就是ActivityThread的attach函數

8.6 attach

這裏我們主要關注attachApplication,也就是AMS的應用附着即可

    private void attach(boolean system) {
        //...
        //是否system,應用啓動肯定不是system,會進入此處
        if (!system) {
            //...

            //設置ddms中的進程名字爲"<pre-initialized>",臨時的
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId());

            //設置ApplicationObject爲ActivityThread
            RuntimeInit.setApplicationObject(mAppThread.asBinder());

            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                //此處就是attachApplication
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }

            //Java允許在類中定義一個名爲finalize()的方法。
            //它的工作原理是:一旦垃圾回收器準備好釋放對象佔用的存儲空間,將首先調用其finalize()方法。
            //並且在下一次垃圾回收動作發生時,纔會真正回收對象佔用的內存
            //BinderInternal裏面實現的是Object finalize,
            //當資源釋放的時候會調用finalize,然後會調用
            BinderInternal.addGcWatcher(new Runnable() {
                //ActivityThread對象沒有再使用時會進行回收
                @Override public void run() {
                    if (!mSomeActivitiesChanged) {
                        return;
                    }
                    Runtime runtime = Runtime.getRuntime();

                    //這個是HeapGrowthLimit,正常應用虛擬機內存最大值dalvik.vm.heapgrowthlimit, 
                    //AndroidRuntime.cpp/runtime.cc/heap.cc
                    long dalvikMax = runtime.maxMemory();
                    long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();

                    //當前使用內存,如果最大內存的3/4將進行activity的釋放操作
                    if (dalvikUsed > ((3*dalvikMax)/4)) {
                        //...
                        mSomeActivitiesChanged = false;
                        try {
                            //此處釋放指的是activity的ondestroy,
                            //目前可以destroy的activity是處於onstop狀態的activity
                            mgr.releaseSomeActivities(mAppThread);
                        //...
        //讓DropBox在libcore可用
        DropBox.setReporter(new DropBoxReporter());

    }

8.7 attachApplication/attachApplicationLocked

1) 首先是ActivityManagerNative.java的attachApplication會傳遞ActivityThread和調用者的pid給到AMS的attachApplicationLocked
2) eventlog中設置服務綁定進程am_proc_bound,說明進程啓動完成,而且該進程的主線程ActivityThread已經創建,並且通知到AMS中
3) ActivityThread的綁定應用bindApplication, 這個會在下面章節講解
4) 由於我們這個例子是桌面啓動應用,那麼最後mStackSupervisor.attachApplicationLocked堆棧中的綁定應用會真正啓動activity活動對象,這個會在下面章節講解

    //ActivityManagerNative.java
    public final void attachApplication(IApplicationThread thread) {
        ...
            attachApplicationLocked(thread, callingPid);
        ...

    //ActivityManagerService.java
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        //...
        ProcessRecord app;
        //調用者非系統進程,且調用者的pid大於0
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                //在進程啓動Process.start後就將pid添加進入mPidsSelfLocked了(父進程調用)
                //現在是子進程調用,這個時候已經添加
                app = mPidsSelfLocked.get(pid);
            //...

        //app.thread還沒有設置過,下面makeActive將進行設置,會將app.thread設置成
        //IApplicationThread(在ActivityThread中),app.thread不爲null了
        if (app.thread != null) {
            //...
        }

        //...
        try {
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            //設置binder died掉之後的的回調地方是binderDied
            thread.asBinder().linkToDeath(adr, 0);
            //設置目前誰在監控死亡狀態
            app.deathRecipient = adr;

        //...
        //eventlog中設置服務綁定am_proc_bound
        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

        //設置ProcessRecord的IApplicationThread(在ActivityThread中)
        app.makeActive(thread, mProcessStats);

        //默認設置一個adj
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
        //...

        //用戶更新電量估算mBatteryStatsService的FOREGROUND時間
        updateProcessForegroundLocked(app, false, false);
        //...
        //判斷是否解鎖
        app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);

        //去除進程啓動超時的msg PROC_START_TIMEOUT_MSG,
        //此處有ActivityThread回傳,代表進程啓動完成
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        //一般情況normalMode都是true
        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);

        //generateApplicationProvidersLocked是開始創建應用的ContentProvider對象
        List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
        //...
        //一般不會進入這裏,這裏是自動化測試的時候會進來
        if (app.instrumentationClass != null) {
            //...
        }
        //...

        //應用兼容性相關,該參數會傳入AcitiviyThread中
        app.compat = compatibilityInfoForPackageLocked(appInfo);

        //一般profilerInfo==null
        ProfilerInfo profilerInfo = profileFile == null ? null
                : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);

        //回到AcitiviyThread中的bindApplication,processName==test2,
        //instrument相關都等於null,mBinderTransactionTrackingEnabled/
        //enableTrackAllocation/isRestrictedBackupMode默認等於false,
        //normalMode默認是true,persistent代表是否常駐內存,compat是兼容性相關,
        //isolated==false,getCommonServicesLocked是將PMS、WMS、ALARM相關服務傳入,
        //mCoreSettingsObserver用於監聽一些參數變化(長按超時,12/24小時顯示時間變化,
        //調試界面屬性),bindApplication是異步的
        thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                app.instrumentationUiAutomationConnection, testMode,
                mBinderTransactionTrackingEnabled, enableTrackAllocation,
                isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat,
                getCommonServicesLocked(app.isolated),
                mCoreSettingsObserver.getCoreSettingsLocked());

        //將進程添加進入mLruProcesses中
        //mLruProcesses保存的是正在運行應用的列表,第一個是最近使用的
        updateLruProcessLocked(app, false, null);

        //觸發GC的時間重新計算
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();

        //...
        //一般normalMode都是true
        if (normalMode) {
            try {
                //如果是activity導致的進程啓動,activity從這裏開始啓動
                //此處用於am_restart_activity,此處設置了didSomething = true
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            //...

        //一般badApp==false
        if (!badApp) {
            try {
                //如果之前該進程有需要啓動的服務,此處開始啓動服務
                //啓動進程了之後纔會去啓動服務
                didSomething |= mServices.attachApplicationLocked(app, processName);
        //...
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                //如果該進程之前有掛起的廣播,現在可以開始發送了
                didSomething |= sendPendingBroadcastsLocked(app);
           // ...

到目前爲止綁定進程的邏輯已經講解完了,接下去我們僅需要關注thread.bindApplication和mStackSupervisor.attachApplicationLocked這2個函數

9 創建application

這一章節將會講到application的實例化、application進程上下文context的創建、application的OnCreate

創建application
圖9.1 創建application

9.1 bindApplication(ActivityThread.java)

我們關注的重點:
1) getPackageInfoNoCheck新建new LoadedApk,該類用於加載apk
2) makeApplication新建一個Application對象new newApplication(這裏面會createAppContext創建application的進程上下文context)
3) callApplicationOnCreate調用Application的OnCreate

    private void handleBindApplication(AppBindData data) {
        //設置art實時編譯更加敏感,更新art配置相關信息的計數count會乘10=((10000/500)/2),
        //會讓art更容易更新配置(如做實時編譯還是解釋執行等)
        VMRuntime.registerSensitiveThread();

        //...
        //設置process的啓動時間,這個主要是給上層調用的
        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());

        //AMS傳遞進來的參數全部放在data上
        mBoundApplication = data;

        //進程啓動時如果你沒有設置固定方向或者手動改變方向,這個config就是AMS中的mConfiguration
        mConfiguration = new Configuration(data.config);
        mCompatConfiguration = new Configuration(data.config);

        mProfiler = new Profiler();
        //一般情況initProfilerInfo都是null,除了使用instrumentation(如自動化測試相關會使用到)
        if (data.initProfilerInfo != null) {
            ...
        }

        //此處會通過prctl(PR_SET_NAME...),裁剪後(process_name.c)
        //只保留processName後面15個字符(kernel實際還會裁剪到最後一個字符,其實是14個字符),
        //設置進程名字(內核標識進程的名字是task_struc->comm).
        Process.setArgV0(data.processName);

        //此處設置的是ddms調試使用的名字
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());

        //常駐內存的進程
        if (data.persistent) {
            //如果在不能使用GPU加速(如低內存設備
            //或者顯示定義config_avoidGfxAccel爲ture的情況都會進來)
            if (!ActivityManager.isHighEndGfx()) {
                //當前進程停止使用硬件渲染,這裏的作用主要是爲了減少運存RAM的消耗,
                //對於低內存手機,這個是有幫助的
                ThreadedRenderer.disable(false);
            }
        }

        //...
        //回覆系統默認時區
        TimeZone.setDefault(null);
        //設置默認的語言
        LocaleList.setDefault(data.config.getLocales());

        //...
        //新建new LoadedApk,該類用於加載apk
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

        //...
        //可以通過config對分辨率進行設置,默認是沒有設置的
        updateDefaultDensity();

        //設置是否24小時
        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
        DateFormat.set24HourTimePref(is24Hr);

        //...
        //網絡代理相關設置
        final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
        if (b != null) {
            final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
            try {
                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
                Proxy.setHttpProxySystemProperty(proxyInfo);

        //...
        //新建一個appContext
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

        //...
        //應用一般是isIsolated == false,這裏講的不是系統進程,是普通app的進程的啓動,故會進入此處
        if (!Process.isIsolated() && !"android".equals(appContext.getPackageName())) {
            //獲取應用緩存目錄,如("/data/user_de/0/com.android.settings/cache")
            final File cacheDir = appContext.getCacheDir();

            //...
            //獲取應用代碼緩存目錄,"/data/user_de/0/com.android.settings/code_cache"
            //此處主要是存放的opengl和renderscript部分的緩存代碼
            //類似於com.android.opengl.shaders_cache、com.android.renderscript.cache這樣的數據
            final File codeCacheDir = deviceContext.getCodeCacheDir();
        }

        //...
        //ii非自動化測試一般都是null
        if (ii != null) {
            ...
        } else {
            //一般情況下走的是這裏
            mInstrumentation = new Instrumentation();
        }

        //設置虛擬機堆棧最大能增長到的內存是多少,根據largeHeap屬性判斷是否大應用
        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
            //如果是大應用的話,應用虛擬機內存可以增長到堆棧大小dalvik.vm.heapsize
            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
        } else {
            //默認只能增長到dalvik.vm.heapgrowthlimit受限制的堆棧大小
            dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
        }

        // allowThreadDiskWrites在應用oncreate的時候允許寫的操作,
        //返回的值是就得策略,此處僅用於臨時修改
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        try {
            //restrictedBackupMode是flase,data.info是上面new的LoadedApk,
            //這裏面的createAppContext和上面的createAppContext傳遞的參數是一樣的
            //此處會新建一個Application對象new newApplication,此處是Application的實例化
            //此處傳遞的第二個參數instrumentation==null,故application不會在此處OnCreate
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);

            //保存當前的Application對象
            mInitialApplication = app;

            //一般沒有限制備份模式,restrictedBackupMode == false
            if (!data.restrictedBackupMode) {
                //如果apk有provider就會進入這裏(如靜態註冊的providers)
                if (!ArrayUtils.isEmpty(data.providers)) {
                    //初始化app中的所有provider
                    installContentProviders(app, data.providers);
                    //...
                }
            }
            try {
                //如果沒有複寫Instrumentation,一般此處沒有做任何事情
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            //...
            try {
                //此處調用的就是Application的OnCreate方法,
                //activity的OnCreate後面會講到,這裏先調用的是Application的OnCreate
                mInstrumentation.callApplicationOnCreate(app);
            //...
    }

9.2 getPackageInfoNoCheck/getPackageInfo

getPackageInfoNoCheck/getPackageInfo返回的是LoadedApk,用於加載apk

    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
        return getPackageInfo(ai, compatInfo, null, false, true, false);
    }

    //(ai, compatInfo, null, false, true, false);
    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
            boolean registerPackage) {
        //...

        //此處apk是包含代碼的,故是從mPackages取,第一次進來此處是null
        ref = mPackages.get(aInfo.packageName);
        LoadedApk packageInfo = ref != null ? ref.get() : null;

        //新建LoadedApk加載apk的類
        packageInfo =
            new LoadedApk(this, aInfo, compatInfo, baseLoader,
                    securityViolation, includeCode &&
                    (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);

        //...
        //將新建的LoadedApk放到mPackages中
        mPackages.put(aInfo.packageName,
                new WeakReference<LoadedApk>(packageInfo));
        //...
        return packageInfo;
    }

9.3 makeApplication(LoadedApk.java)

1) 創建Application的進程上下文
2) 調用代理Instrumentation新建Application
3) Application實例化、Application設置進程上下文context

    //LoadedApk.java
    //forceDefaultAppClass==false,instrumentation==null
    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        //...
        Application app = null;

        //如果應用沒有重載Application類的話,直接使用默認的"android.app.Application"
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            //...
            //創建Application的進程上下文
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            //調用代理Instrumentation新建Application
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        }
        //...
        return app;
    }

    //Instrumentation.java
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }
    static public Application newApplication(Class<?> clazz, Context context)
            ... {
        //Application類的實例化,如類非靜態變量等會在此處生成
        Application app = (Application)clazz.newInstance();
        //調用Application的attach附着,用於設置進程上下文context
        app.attach(context);
        return app;
    }

    //Application.java
    final void attach(Context context) {
        //設置base應用基本的進程上下文
        attachBaseContext(context);
        //設置類的加載器
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

現在有了Application這個對象,下面接着會進行Application的OnCreate

9.4 callApplicationOnCreate(Instrumentation.java)

callApplicationOnCreate這個函數通過代理調用Application的OnCreate

    //Instrumentation.java
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }

    //Application.java
    public void onCreate() {
    }

進程啓動會先調用Application的OnCreate,這個也是算在應用啓動生命週期內的。

目前Application創建了,Application的OnCreate也調用了,接下去就是Activity相關的邏輯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章