Android M應(yīng)用啟動(dòng)流程分析

Android M應(yīng)用啟動(dòng)流程分析

更新:
2016-10-29:更新handleBindApplication部分。

我這個(gè)版本的原則是,有話則長(zhǎng)鞋拟,無(wú)話則短.

以下分析基于6.0.1_r10版本。
先看一張大圖:


android_app_startup
android_app_startup

1. 桌面的onClick事件(進(jìn)程:桌面應(yīng)用的進(jìn)程)

我們暫時(shí)忽略Input處理的過程惹资,以桌面的onClick事件被觸發(fā)為起點(diǎn)贺纲。
這部分根據(jù)Launcher的不同而大同小異。

2. ActivityManagerService之startActivity(進(jìn)程AmS)

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
桌面調(diào)用framework褪测,最后會(huì)調(diào)到AmS的startActivity方法.
現(xiàn)在是多用戶時(shí)代了猴誊,startActivity現(xiàn)在唯一做的事兒,就是通過UserHandle.getCallingUserId()去獲取當(dāng)前的user id侮措,然后調(diào)用startActivityAsUser方法懈叹。

3848    @Override
3849    public final int startActivity(IApplicationThread caller, String callingPackage,
3850            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
3851            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
3852        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
3853            resultWho, requestCode, startFlags, profilerInfo, options,
3854            UserHandle.getCallingUserId());
3855    }

3. ActivityManagerService之startActivityAsUser

這個(gè)方法如其名,還真是只處理跟user相關(guān)的工作分扎,調(diào)用handleIncomingUser澄成。
之后,調(diào)用ActivityStackSupervisor來(lái)去處理跟Activity狀態(tài)相關(guān)真正邏輯畏吓。

3857    @Override
3858    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
3859            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
3860            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
3861        enforceNotIsolatedCaller("startActivity");
3862        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
3863                false, ALLOW_FULL_ONLY, "startActivity", null);
3864        // TODO: Switch to user app stacks here.
3865        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
3866                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
3867                profilerInfo, null, null, options, false, userId, null, null);
3868    }

4. ActivityStackSupervisor之startActivityMayWait(進(jìn)程AmS)

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
先解釋一下為什么叫MayWait墨状,因?yàn)檎{(diào)用startActivity是可能要等待結(jié)果的startActivityForResult,那就要掛起調(diào)用者菲饼。
首先肾砂,startActivityMayWait要讀取一些信息。從4.4開始宏悦,這部分邏輯寫到resolveActivity方法中镐确,它會(huì)調(diào)用PackageManagerService的resolveIntent方法。這個(gè)方法會(huì)先調(diào)用queryIntentActivities方法出查詢相關(guān)的列表饼煞,然后再調(diào)用chooseBestActivity方法去選擇辫塌。為了不影響主線,這些支線內(nèi)容后面再講派哲。
主線往下走臼氨,進(jìn)入startActivityLocked。Locked意思是調(diào)用者需要保證加鎖保護(hù)芭届,不能重復(fù)調(diào)用储矩,在startActivityMayWait中感耙,是采用mService對(duì)象,也就是構(gòu)造ActivityStackSupervisor時(shí)傳進(jìn)來(lái)的ActivityManagerService的對(duì)象持隧。
調(diào)用成功了之后即硼,如果需要wait,就讓mService.wait()去等待吧屡拨。新Activity還在征途上只酥。

925    final int startActivityMayWait(IApplicationThread caller, int callingUid,
926            String callingPackage, Intent intent, String resolvedType,
927            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
928            IBinder resultTo, String resultWho, int requestCode, int startFlags,
929            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
930            Bundle options, boolean ignoreTargetSecurity, int userId,
931            IActivityContainer iContainer, TaskRecord inTask) {
...
941        // Collect information about the target of the Intent.
942        ActivityInfo aInfo =
943                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
...
1045            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
1046                    voiceSession, voiceInteractor, resultTo, resultWho,
1047                    requestCode, callingPid, callingUid, callingPackage,
1048                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
1049                    componentSpecified, null, container, inTask);
...

5. ActivityStackSupervisor之startActivityLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

前面先做一系列檢查的工作,比如權(quán)限呀狼,比如Intent防火墻檢查裂允。
準(zhǔn)備做好之后,就new一個(gè)ActivityRecord哥艇,用于存儲(chǔ)Activity的各種狀態(tài)和歷史信息绝编。
然后,通過getFocusedStack方法獲取當(dāng)前獲取焦點(diǎn)的ActivityStack貌踏。ActivityStackSupervisor中的mFocusedStack中保存了當(dāng)前的前臺(tái)ActivityStack十饥。
下面就準(zhǔn)備切換新進(jìn)程了,先判斷一下是否可以切換祖乳,如果處于通話中界面等無(wú)法馬上切換的情況逗堵。通過ActivityManagerService的checkAppSwitchAllowedLocked方法來(lái)做檢查,如果當(dāng)前不允許做進(jìn)程切換眷昆,就先存到PendingActivityLaunch的列表中蜒秤,等待以后有機(jī)會(huì)再調(diào)用。
如果允許做切換隙赁,那么先檢查一下當(dāng)前是否有以前的等待任務(wù)垦藏,如果有就先執(zhí)行它們梆暖,調(diào)用doPendingActivityLaunchesLocked方法去執(zhí)行這個(gè)循環(huán)伞访。
如果以上都完成了,就調(diào)用startActivityUncheckedLocked轰驳。

1399    final int startActivityLocked(IApplicationThread caller,
1400            Intent intent, String resolvedType, ActivityInfo aInfo,
1401            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1402            IBinder resultTo, String resultWho, int requestCode,
1403            int callingPid, int callingUid, String callingPackage,
1404            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
1405            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
1406            ActivityContainer container, TaskRecord inTask) {
...
1675        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
1676                startFlags, true, options, inTask);
1677
1678        if (err < 0) {
1679            // If someone asked to have the keyguard dismissed on the next
1680            // activity start, but we are not actually doing an activity
1681            // switch...  just dismiss the keyguard now, because we
1682            // probably want to see whatever is behind it.
1683            notifyActivityDrawnForKeyguard();
1684        }
1685        return err;
1686    }

6. ActivityStackSupervisor之startActivityUncheckedLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
通過一系列分析厚掷,找到了該執(zhí)行的目標(biāo)ActivityStack,然后調(diào)用該ActivityStack的startActivityLocked方法針對(duì)該任務(wù)做具體的操作级解。

1828    final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
1829            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
1830            boolean doResume, Bundle options, TaskRecord inTask) {
...
2457        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
2458        targetStack.mLastPausedActivity = null;
2459        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
2460        if (!launchTaskBehind) {
2461            // Don't set focus on an activity that's going to the back.
2462            mService.setFocusedActivityLocked(r, "startedActivity");
2463        }
2464        return ActivityManager.START_SUCCESS;
2465    }

7. ActivityStack之startActivityLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
如果需要的話冒黑,這一步中會(huì)調(diào)用到WmS的setAppStartingWindow,開始準(zhǔn)備新應(yīng)用的啟動(dòng)窗口勤哗。
這其中抡爹,有重要一步是調(diào)用WindowManagerService的addAppToken方法去將信息共步給WmS,為下一步的顯示做準(zhǔn)備芒划。
最后冬竟,調(diào)用ActivityStackSupervisor的resumeTopActivitiesLocked方法欧穴,將顯示的Activities都resume一下。

2074    final void startActivityLocked(ActivityRecord r, boolean newTask,
2075            boolean doResume, boolean keepCurTransition, Bundle options) {
...
2232        if (doResume) {
2233            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
2234        }
2235    }

8. ActivityStackSupervisor之resumeTopActivitiesLocked

先獲取當(dāng)前焦點(diǎn)顯示的ActivityStack泵殴,調(diào)其resumeTopActivityLocked涮帘。完成后,遍歷所有能顯示的Activity的stack笑诅。

2727    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2728            Bundle targetOptions) {
2729        if (targetStack == null) {
2730            targetStack = mFocusedStack;
2731        }
2732        // Do targetStack first.
2733        boolean result = false;
2734        if (isFrontStack(targetStack)) {
2735            result = targetStack.resumeTopActivityLocked(target, targetOptions);
2736        }
2737
2738        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2739            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2740            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2741                final ActivityStack stack = stacks.get(stackNdx);
2742                if (stack == targetStack) {
2743                    // Already started above.
2744                    continue;
2745                }
2746                if (isFrontStack(stack)) {
2747                    stack.resumeTopActivityLocked(null);
2748                }
2749            }
2750        }
2751        return result;
2752    }

9. ActivityStack之resumeTopActivityLocked

調(diào)用resumeTopActivityInnerLocked

1540    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1541        if (mStackSupervisor.inResumeTopActivity) {
1542            // Don't even start recursing.
1543            return false;
1544        }
1545
1546        boolean result = false;
1547        try {
1548            // Protect against recursion.
1549            mStackSupervisor.inResumeTopActivity = true;
1550            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
1551                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
1552                mService.updateSleepIfNeededLocked();
1553            }
1554            result = resumeTopActivityInnerLocked(prev, options);
1555        } finally {
1556            mStackSupervisor.inResumeTopActivity = false;
1557        }
1558        return result;
1559    }

10. ActivityStack之resumeTopActivityInnerLocked

這是第一次進(jìn)入這個(gè)方法调缨,這次我們是走pause桌面這一支,下一次我們就走到最后的startSpecificActivityLocked那一支吆你。
調(diào)用startPausingLocked去pause弦叶。

1561    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
...
1729        if (mResumedActivity != null) {
1730            if (DEBUG_STATES) Slog.d(TAG_STATES,
1731                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
1732            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
1733        }

11. ActivityStack之startPausingLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
AmS開始發(fā)起pause桌面的操作
如果不是從桌面啟動(dòng)的話,就要去為上一個(gè)應(yīng)用抓個(gè)用于顯示在近期任務(wù)里的圖早处。
prev.updateThumbnailLocked(screenshotActivities(prev), null);
處理完成之后湾蔓,通知桌面應(yīng)用去執(zhí)行onPause。
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags, dontWait);
這個(gè)thread就是IPC的ApplicationThreadNative對(duì)象砌梆。

802    /**
803     * Start pausing the currently resumed activity.  It is an error to call this if there
804     * is already an activity being paused or there is no resumed activity.
805     *
806     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
807     * @param uiSleeping True if this is happening with the user interface going to sleep (the
808     * screen turning off).
809     * @param resuming True if this is being called as part of resuming the top activity, so
810     * we shouldn't try to instigate a resume here.
811     * @param dontWait True if the caller does not want to wait for the pause to complete.  If
812     * set to true, we will immediately complete the pause here before returning.
813     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
814     * it to tell us when it is done.
815     */
816    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
817            boolean dontWait) {
...
860        if (prev.app != null && prev.app.thread != null) {
861            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
862            try {
863                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
864                        prev.userId, System.identityHashCode(prev),
865                        prev.shortComponentName);
866                mService.updateUsageStats(prev, false);
867                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
868                        userLeaving, prev.configChangeFlags, dontWait);

12. ApplicationThreadNative的schedulePauseActivity

路徑:frameworks/base/core/java/android/app/ApplicationThreadNative.java
AmS要通過IPC來(lái)通知給桌面默责,于是通過Proxy來(lái)發(fā)送IPC操作.

718    public final void schedulePauseActivity(IBinder token, boolean finished,
719            boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
720        Parcel data = Parcel.obtain();
721        data.writeInterfaceToken(IApplicationThread.descriptor);
722        data.writeStrongBinder(token);
723        data.writeInt(finished ? 1 : 0);
724        data.writeInt(userLeaving ? 1 :0);
725        data.writeInt(configChanges);
726        data.writeInt(dontReport ? 1 : 0);
727        mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
728                IBinder.FLAG_ONEWAY);
729        data.recycle();
730    }

13. ActivityThread之schedulePauseActivity (桌面進(jìn)程)

路徑:frameworks/base/core/java/android/app/ActivityThread.java
通過IPC,運(yùn)行桌面應(yīng)用的ActivityThread的schedulePauseActivity咸包。此處ActivityThread會(huì)將這個(gè)請(qǐng)求放入隊(duì)列中桃序,等待運(yùn)行。

588        public final void schedulePauseActivity(IBinder token, boolean finished,
589                boolean userLeaving, int configChanges, boolean dontReport) {
590            sendMessage(
591                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
592                    token,
593                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
594                    configChanges);
595        }

在這段期間烂瘫,WmS也沒閑著媒熊,類似于之前我們?cè)趕tartActivityLocked時(shí)做的addWindow之類的操作一直在干活。

14. ActivityThread之handlePauseActivity (桌面進(jìn)程)

終于從隊(duì)列中輪到出場(chǎng)了坟比,開始執(zhí)行桌面的onPause吧芦鳍。

不過先別急,執(zhí)行onPause之前葛账,先執(zhí)行performUserLeavingActivity柠衅,最后會(huì)調(diào)到Activity的performUserLeaving。
這個(gè)方法做兩步:

final void performUserLeaving() {
    onUserInteraction();
    onUserLeaveHint();
}

這些都做完了籍琳,調(diào)用performPauseActivity菲宴。

3305    private void handlePauseActivity(IBinder token, boolean finished,
3306            boolean userLeaving, int configChanges, boolean dontReport) {
...
3310            if (userLeaving) {
3311                performUserLeavingActivity(r);
3312            }
...
3315            performPauseActivity(token, finished, r.isPreHoneycomb());
...
3325                    ActivityManagerNative.getDefault().activityPaused(token);
...
}

15. ActivityThread之performPauseActivity

首先判斷一下狀態(tài),如果已經(jīng)pause了趋急,那就需要先resume之喝峦。當(dāng)然,如果pause了之后正在finishing中呜达,就算了谣蠢,不是的話,拋個(gè)RuntimeException,問問調(diào)用者不先resume是為哪般眉踱。
沒有異常的話勋颖,先調(diào)用callCallActivityOnSaveInstanceState,這個(gè)會(huì)通過Instrumentation的callActivityOnSaveInstanceState去調(diào)用Activity的performSaveInstanceState, 然后會(huì)調(diào)到Activity的onSaveInstanceState勋锤。還會(huì)將對(duì)話框的信息做保存操作饭玲。
保存完?duì)顟B(tài)之后,再調(diào)用Instrumentation的callActivityOnPause叁执。然后調(diào)用Activity的performPause茄厘。
Activity在onPause之前,先通知各個(gè)Fragment去onPause谈宛,再調(diào)用Activity的onPause.
performPauseActivity結(jié)束后次哈,回到launchPauseActivity,下面通知AMS吆录,調(diào)IPC來(lái)做activityPaused窑滞。

16. ActivityManagerNative 之a(chǎn)ctivityPaused

路徑:frameworks/base/core/java/android/app/ActivityManagerNative.java
桌面的onPause執(zhí)行完了,通過IPC通知AmS恢筝,可以啟動(dòng)新應(yīng)用了哀卫。

17. ActivityManagerService之a(chǎn)ctivityPaused

路徑:services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到activityPaused的消息,然后找到對(duì)應(yīng)的ActivityStack的activityPausedLocked撬槽。

18. ActivityStack之a(chǎn)ctivityPausedLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
然后調(diào)用completePausedLocked此改。

19. ActivityStack之completePauseLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
到此,桌面的onPause正式告一段落侄柔。
結(jié)束之后共啃,再次調(diào)用前面我們已經(jīng)遇到過的ActivityStackSupervisor的resumeTopActivitiesLocked,前一次我們走了一半就調(diào)pause過程去了暂题,這次我們將走到最后移剪。

20. ActivityStackSupervisor之resumeTopActivitiesLocked

還跟上次一樣,調(diào)相應(yīng)的ActivityStack的resumeTopActivityLocked薪者。

21. ActivityStack之resumeTopActivityLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
這個(gè)方法只是一個(gè)十幾行的wrapper纵苛,除了設(shè)了個(gè)flag和處理鎖屏之外,直接調(diào)用resumeTopActivityInnerLocked方法啸胧。

22. ActivityStack之resumeTopActivityInnerLocked

這個(gè)大方法走到最后赶站,執(zhí)行ActivityStackSupervisor的startSpecificActivityLocked幔虏。
(注:這個(gè)方法是5.0之后分出來(lái)的纺念,4.4上還在resumeTopActivityLocked里面)

23. ActivityStackSupervisor之startSpecificActivityLocked (AmS進(jìn)程)

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
從這里,又從ActivityStackSupervisor調(diào)回ActivityManagerService想括,調(diào)用startProcessLocked陷谱。

24. ActivityManagerService 之startProcessLocked

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
通過調(diào)用android.os.Process的start去啟動(dòng)新進(jìn)程。

25. Process.start

路徑:frameworks/base/ core/java/android/os/Process.java
其實(shí)就是startViaZygote的一個(gè)簡(jiǎn)單封裝。

481    public static final ProcessStartResult start(final String processClass,
482                                  final String niceName,
483                                  int uid, int gid, int[] gids,
484                                  int debugFlags, int mountExternal,
485                                  int targetSdkVersion,
486                                  String seInfo,
487                                  String abi,
488                                  String instructionSet,
489                                  String appDataDir,
490                                  String[] zygoteArgs) {
491        try {
492            return startViaZygote(processClass, niceName, uid, gid, gids,
493                    debugFlags, mountExternal, targetSdkVersion, seInfo,
494                    abi, instructionSet, appDataDir, zygoteArgs);
495        } catch (ZygoteStartFailedEx ex) {
496            Log.e(LOG_TAG,
497                    "Starting VM process through Zygote failed");
498            throw new RuntimeException(
499                    "Starting VM process through Zygote failed", ex);
500        }
501    }

26. Process.startViaZygote

路徑:frameworks/base/core/java/android/os/Process.java
主要是處理參數(shù)烟逊,然后調(diào)用zygoteSendArgsAndGetResult去通過socket通信去通知zygote渣窜。

27. Process.zygoteSendArgsAndGetResult

路徑:frameworks/base/core/java/android/os/Process.java
通過socket通知Zygote進(jìn)程去fork新進(jìn)程。接收方是ZygoteConnection宪躯。

28. ZygoteConnection.runOnce

路徑:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
從socket中讀取命令并執(zhí)行乔宿。
這個(gè)可以往下再分為4步:

  • readArgumentList
  • apply security policies
  • apply security policies
  • preForkAndSpecialize

29. Zygote之forkAndSpecialize

路徑:/frameworks/base/core/java/com/android/internal/os/Zygote.java
這步分為三個(gè)子步驟:

  • preFork
  • nativeForkAndSpecialize
  • postForkCommon

29-1. ZygoteHooks.PreFork

路徑:/libcore/dalvik/src/main/java/dalvik/system/ ZygoteHooks.java
這步離開了frameworks/base,進(jìn)入了libcore访雪。這里面要注意详瑞,不能調(diào)用Android的API,打個(gè)log什么的都要注意臣缀。

  • Daemons.stop()
    停掉GC坝橡,停掉finalizer等,fork進(jìn)程時(shí)不需要這些
  • waitUntilAllThreadsStopped()
    確保fork之前只有一個(gè)線程在運(yùn)行
  • nativePreFork()
    給虛擬機(jī)一個(gè)機(jī)會(huì)去在fork之前做點(diǎn)處理

29-2. com_android_internal_os_Zygote_nativeForkAndSpecialize

路徑:/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
這是我們第一次進(jìn)入C++層精置。真正做事的函數(shù)是ForkAndSpecializeCommon计寇。

真正開始fork新進(jìn)程

  • SetSigChldHandler
  • Fork and detach(新進(jìn)程從這一步開始誕生)
  • child process setup

這一步是值得大書特書的一步,因?yàn)閺倪@一步開始脂倦,更具體地說(shuō)是從Fork and detach開始番宁,新應(yīng)用的進(jìn)程終于fork出來(lái)了。從此zygote老進(jìn)程的事情我們不再關(guān)心赖阻,我們來(lái)看新進(jìn)程號(hào)就好了贝淤。

Child process setup之后,有一個(gè)重要的函數(shù)會(huì)被執(zhí)行到政供,這就是ZygoteHooks_nativePostForkChild播聪。
在這個(gè)函數(shù)中,ART版本號(hào)會(huì)被打印出來(lái)布隔。說(shuō)明Android Runtime已經(jīng)正式開始工作了离陶。

29-3. postForkCommon

路徑:/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
只干一件事,把preFork里面stop的monitor們重新打開衅檀。這一步要注意招刨,原來(lái)的Zygote里面的不要去管了,只看新進(jìn)程的就好哀军。

30. RuntimeInit.zygoteInit

路徑:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

31. RuntimeInit.invokeStaticMain

路徑:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
初始化完成沉眶,通過反射來(lái)調(diào)用ActivityThread的main方法

32. ActivityThread main

路徑:frameworks/base/ core/java/android/app/ActivityThread.java
執(zhí)行ActivityThread的main方法,新的應(yīng)用正式上路

33. Proxy:attachApplication

路徑:frameworks/base/
新的Activity建好了杉适,要通知AmS谎倔,走IPC。

34. ActivityManagerService之a(chǎn)ttachApplication

路徑: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到attach的通知猿推,一切準(zhǔn)備就緒片习。

35. AMS:attachApplicationLocked

路徑:frameworks/base/ services/core/java/com/android/server/am/ActivityManagerService.java
其它部分都是線性的捌肴,這部分我們不得不分成兩個(gè)部分各表一支了。這兩部分分別走IPC藕咏,最后在ActivityThread的隊(duì)列中匯合状知。
首先是bindApplication。

36. ApplicationThreadProxy之bindApplication

IPC調(diào)用
路徑:frameworks/base/core/java/android/app/ApplicationThreadNative.java

37. ActivityThread之bindApplication

路徑:frameworks/base/core/java/android/app/ActivityThread.java
主要包括兩部分的操作孽查,雖然這個(gè)方法不叫做scheduleXXX饥悴,但是實(shí)際上兩步的操作都是放到隊(duì)列中。
到這一步的時(shí)候盲再,其實(shí)我們只是啟動(dòng)了一個(gè)空進(jìn)程而己铺坞,跟實(shí)際的apk還一點(diǎn)關(guān)系也沒有。
首先洲胖,如果services不為空的話济榨,先初始化一下services cache。
ServiceManager.initServiceCache(services);
然后绿映,schedule第一個(gè)任務(wù)擒滑,setCoreSettings(coreSettings);
這個(gè)最終會(huì)走到handleSetCoreSettings。
下面叉弦,PM才出場(chǎng)去讀真正的package的信息丐一。讀好之后,再去將BIND_APPLICATION消息放到隊(duì)列里去淹冰,這時(shí)候可能正在執(zhí)行setCoreSettings库车。

38. ActivityThread之handleBindApplication

真正啟動(dòng)Activity之前,還得做一些準(zhǔn)備工作樱拴。比如install provider就是在這時(shí)候做的柠衍。

38-1 LoadedApk之makeApplication

我們都知道,在Activity之外晶乔,對(duì)于每個(gè)應(yīng)用珍坊,還對(duì)應(yīng)一個(gè)Application類。這個(gè)Application就是在LoadApk的makeApplication方法時(shí)構(gòu)造的正罢。

554    public Application makeApplication(boolean forceDefaultAppClass,
555            Instrumentation instrumentation) {
556        if (mApplication != null) {
557            return mApplication;
558        }
559
560        Application app = null;
561
562        String appClass = mApplicationInfo.className;
563        if (forceDefaultAppClass || (appClass == null)) {
564            appClass = "android.app.Application";
565        }

下面調(diào)用ClassLoader阵漏,并且生成ApplicationContext.

567        try {
568            java.lang.ClassLoader cl = getClassLoader();
569            if (!mPackageName.equals("android")) {
570                initializeJavaContextClassLoader();
571            }
572            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

下面將通過Intrumentation的newApplication方法去真正創(chuàng)建Application

573            app = mActivityThread.mInstrumentation.newApplication(
574                    cl, appClass, appContext);
575            appContext.setOuterContext(app);
576        } catch (Exception e) {
577            if (!mActivityThread.mInstrumentation.onException(app, e)) {
578                throw new RuntimeException(
579                    "Unable to instantiate application " + appClass
580                    + ": " + e.toString(), e);
581            }
582        }
583        mActivityThread.mAllApplications.add(app);
584        mApplication = app;

38-2 Application之newApplication

通過反射構(gòu)造對(duì)象,然后調(diào)用Application的attach方法翻具。

993    static public Application newApplication(Class<?> clazz, Context context)
994            throws InstantiationException, IllegalAccessException,
995            ClassNotFoundException {
996        Application app = (Application)clazz.newInstance();
997        app.attach(context);
998        return app;
999    }

38-3 Application之a(chǎn)ttach

attach再調(diào)用attachBaseContext履怯。

183    /**
184     * @hide
185     */
186    /* package */ final void attach(Context context) {
187        attachBaseContext(context);
188        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
189    }
?????```

### 38-4 ContextThemeWrapper之a(chǎn)ttachBaseContext

```java
50    @Override
51    protected void attachBaseContext(Context newBase) {
52        super.attachBaseContext(newBase);
53    }

38-5 ContextWrapper的attachBaseContext

65    protected void attachBaseContext(Context base) {
66        if (mBase != null) {
67            throw new IllegalStateException("Base context already set");
68        }
69        mBase = base;
70    }

Application構(gòu)造好之后,將調(diào)用Application的onCreate方法裆泳。

586        if (instrumentation != null) {
587            try {
588                instrumentation.callApplicationOnCreate(app);
589            } catch (Exception e) {
590                if (!instrumentation.onException(app, e)) {
591                    throw new RuntimeException(
592                        "Unable to create application " + app.getClass().getName()
593                        + ": " + e.toString(), e);
594                }
595            }
596        }

最后更新所有R常量的值

598        // Rewrite the R 'constants' for all library apks.
599        SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
600                .getAssignedPackageIdentifiers();
601        final int N = packageIdentifiers.size();
602        for (int i = 0; i < N; i++) {
603            final int id = packageIdentifiers.keyAt(i);
604            if (id == 0x01 || id == 0x7f) {
605                continue;
606            }
607
608            rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
609        }
610
611        return app;
612    }

下面花開兩朵說(shuō)另一枝叹洲,回到attachApplicationLocked方法,它將會(huì)調(diào)用到realStartActivityLocked晾虑。

39. ActivityStackSupervisor之realStartActivityLocked(AmS進(jìn)程)

路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
這時(shí)算是真正啟動(dòng)疹味,通過Activity,可以執(zhí)行onCreate了帜篇。

40. ApplicationThreadNative之scheduleLaunchActivity

路徑:frameworks/base/core/java/android/app/ApplicationThreadNative.java
IPC通道糙捺,通知本地進(jìn)程

41. ActivityThread之scheduleLaunchActivity

路徑:frameworks/base/ core/java/android/app/ActivityThread.java
ActivityThread收到,將命令放入隊(duì)列笙隙。

42. ActivityThread之handleLaunchActivity

路徑:frameworks/base/ core/java/android/app/ActivityThread.java
正式開始Activity的啟動(dòng)流程洪灯。

43. ActivityThread之performLaunchActivity

路徑:frameworks/base/ core/java/android/app/ActivityThread.java
負(fù)責(zé)new出Activity的實(shí)例,makeApplication竟痰,然后調(diào)用Activity.attach向系統(tǒng)注冊(cè)签钩。
最后,通過callActivityOnCreate來(lái)調(diào)用應(yīng)用的onCreate方法坏快。

44. ActivityThread之handleResumeActivity

路徑:frameworks/base/ core/java/android/app/ActivityThread.java
首先铅檩,通過performResumeActivity方法調(diào)用應(yīng)用的onResume方法。
如大家所熟知的莽鸿,執(zhí)行完onResume之后昧旨,真正的繪制工作就才真正開始。
ActivityThread通過ViewManager對(duì)象調(diào)用其addView方法祥得,開始正式通知WmS要添加窗口了兔沃。實(shí)際上,獲取的這個(gè)ViewManager级及,是其子接口WindowManager的實(shí)現(xiàn)類WindowManagerImpl的方法乒疏。這個(gè)WindowManagerImpl的對(duì)象是通過
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)調(diào)用從系統(tǒng)服務(wù)獲取到的。

45. WindowManagerImpl之a(chǎn)ddView

路徑:frameworks/base/core/java/android/view/WindowManagerImpl.java
ViewManager只是一個(gè)接口饮焦,用于定義功能跛锌,本身并不與WmS打交道弓摘。它通過單例對(duì)象WindowManagerGlobal去訪問ViewRootImpl,再由ViewRootImpl去跟WmS通信。

46. WindowManagerGlobal之a(chǎn)ddView

路徑:frameworks/base/core/java/android/view/WindowManagerGlobal.java
WindowManagerGlobal也只是個(gè)二傳手损合,最終調(diào)用ViewRootImpl類的setView來(lái)真正與WmS交互。

47. ViewRootImpl之setView

路徑:frameworks/base/core/java/android/view/ViewRootImpl.java
ViewRootImpl被構(gòu)造出來(lái)后钧栖,會(huì)通過WindowManagerGlobal的getWindowSession方法去創(chuàng)建一個(gè)與WmS之間的連接谤牡。構(gòu)造中會(huì)調(diào)到這一句:

mWindowSession = WindowManagerGlobal.getWindowSession();

在正式添加到WmS之前,首先要保證這個(gè)View樹可以正常接收事件丙曙,于是先發(fā)起一次requestLayout爸业。

48. ViewRootImpl之requestLayout

這個(gè)方法本身是WmS最簡(jiǎn)單的方法之一,先檢查一下是不是UI線程亏镰,如果是扯旷,就scheduleTraversals,申請(qǐng)做一次遍歷索抓。
準(zhǔn)備好了之后钧忽,setView就會(huì)通過mWindowSession去IPC通知WmS去添加一個(gè)窗口毯炮。

49. Session之a(chǎn)ddToDisplay

路徑:frameworks/base/services/core/java/com/android/server/wm/Session.java
IPC調(diào)用WmS的addWindow方法。

50. WindowManagerService之a(chǎn)ddWindow

路徑:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
第一步先檢查權(quán)限耸黑,比如部分系統(tǒng)窗口就不是應(yīng)用可以添加的桃煎。
第二步去檢查是不是重復(fù)添加了。

if (mWindowMap.containsKey(client.asBinder())) {
    Slog.w(TAG, "Window " + client + " is already added");
    return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}

第三步大刊,如果是子窗口为迈,就尋找父窗口。
第四步缺菌,檢查窗口的有效性葫辐。
第五步,用WindowState對(duì)象來(lái)管理窗口的狀態(tài)伴郁。

win = new WindowState(this, session, client, token,attachedWindow, appOp0, seq, attrs, viewVisibility, displayContent);

第六步耿战,調(diào)整Window屬性
第七步,將token加入到mTokenMap中焊傅。
第八步昆箕,將client.asBinder()加到mWindowMap中。
第九步租冠,將Window們按順序排列鹏倘,調(diào)用addWindowToListInOrderLocked方法。
這些做完顽爹,addView就算完成了纤泵,剩下的事情就看遍歷的了。

51. ViewRootImpl之scheduleTraversals

準(zhǔn)備好了之后镜粤,放入隊(duì)列等待被遍歷捏题。

52. ViewRootImpl之doTraversal

遍歷操作,實(shí)際邏輯都在performTraversals中肉渴。

53. ViewRootImpl之performTraversals

遍歷的核心邏輯公荧,主要有三個(gè)步驟:measure, layout和draw。
如果是第一次調(diào)用同规,所有的子對(duì)象還沒有attach到窗口上循狰,需要首先dispatchAttachedToWindow。Attach到哪里呢券勺,PhoneWindow的DecorView绪钥。
這個(gè)方法沒有被DecorView重載,直接調(diào)用的是ViewGroup的dispatchAttachedToWindow关炼。

54. ViewGroup之dispatchAttachedToWindow

根元素被attach到Window上之后程腹,開始遞歸它的子節(jié)點(diǎn),使每個(gè)子節(jié)點(diǎn)都attach到父節(jié)點(diǎn)上儒拂。
執(zhí)行結(jié)束后寸潦,通過回調(diào)onAttachedToWindow來(lái)通知節(jié)點(diǎn)已經(jīng)被attach到Window上了色鸳。
在被attach到Window之前,View實(shí)際上是沒有大小的见转,因?yàn)檫€不知道被用到哪里呢命雀,無(wú)法去做測(cè)量。
然后池户,回到performTraversals中咏雌,在執(zhí)行三大操作之前凡怎,先去看看隊(duì)列里還有什么未執(zhí)行的任務(wù)沒有校焦,有的話就先執(zhí)行之。

getRunQueue().executeActions(mAttachInfo.mHandler);

由于是第一次畫统倒,所以mLayoutRequested為true寨典,我們還不知道窗口大小是多大,于是來(lái)一次測(cè)量房匆,調(diào)用measureHierarchy.

windowSizeMayChange |= measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);

測(cè)量完成之后耸成,就可以開始布局了,調(diào)用relayoutWindow.

55. ViewRootImpl之relayoutWindow

relayoutWindow當(dāng)然不是本地能搞得定的浴鸿,于是通過IPC調(diào)井氢,mWindowSession的relayout去通知WmS去干這事兒。

56. Session之relayout

IPC調(diào)用岳链,調(diào)用WmS的relayoutWindow花竞。

57. WindowManagerService之relayoutWindow

WmS準(zhǔn)備第一次畫之前,先來(lái)個(gè)進(jìn)場(chǎng)動(dòng)畫吧掸哑。

winAnimator.applyEnterAnimationLocked();

然后創(chuàng)建個(gè)新的Surface吧约急。

SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();

最后調(diào)用performLayoutAndPlaceSurfacesLocked方法

58. WindowManagerService之performLayoutAndPlaceSurfacesLocked

這里邊還要走一個(gè)最多6次的循環(huán),每次都調(diào)用performLayoutAndPlaceSurfacesLockedLoop苗分。

59. WindowManagerService之performLayoutAndPlaceSurfacesLockedLoop

調(diào)用performLayoutAndPlaceSurfacesLockedInner

60. WindowManagerService之performLayoutAndPlaceSurfacesLockedInner

真正執(zhí)行l(wèi)ayout的邏輯厌蔽。
Measure和layout完成了,最后終于可以畫了摔癣∨回到performTraversals中,調(diào)用performDraw择浊。

61. ViewRootImpl之performDraw

先調(diào)用draw去通知繪制線程開始畫拐云。
然后把所有的動(dòng)畫全停掉。

62. ViewRootImpl之draw

如果支持硬件加速近她,就調(diào)用HardwareRenderer抽象類的draw方法去畫叉瘩。

63. ThreadedRenderer之draw

路徑:frameworks/base/core/java/android/view/ThreadedRenderer.java

64. ThreadedRenderer之nSyncAndDrawFrame

這是個(gè)native方法,真正實(shí)現(xiàn)調(diào)用GPU去繪制粘捎。調(diào)用的是android_view_ThreadedRender_syncAndDrawFrame函數(shù)薇缅。

65. android_view_ThreadedRenderer_syncAndDrawFrame函數(shù)

路徑:frameworks/base/core/jni/android_view_ThreadedRenderer.cpp
再調(diào)用RenderProxy的syncAndDrawFrame危彩。

66. RenderProxy::syncAndDrawFrame

路徑:frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
調(diào)用DrawFrameTask的drawFrame函數(shù)。

67. DrawFrameTask::drawFrame

路徑:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
調(diào)用postAndWait泳桦。

68. DrawFrameTask::postAndWait

放到隊(duì)列里汤徽,等著VSYNC信號(hào)來(lái)了就調(diào)用吧。

void DrawFrameTask::postAndWait() {
AutoMutex \_lock(mLock);
mRenderThread->queue(this);
mSignal.wait(mLock);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灸撰,一起剝皮案震驚了整個(gè)濱河市谒府,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浮毯,老刑警劉巖完疫,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異债蓝,居然都是意外死亡壳鹤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門饰迹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)芳誓,“玉大人,你說(shuō)我怎么就攤上這事啊鸭∏绿剩” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵赠制,是天一觀的道長(zhǎng)赂摆。 經(jīng)常有香客問我,道長(zhǎng)憎妙,這世上最難降的妖魔是什么库正? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮厘唾,結(jié)果婚禮上褥符,老公的妹妹穿的比我還像新娘。我一直安慰自己抚垃,他們只是感情好喷楣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹤树,像睡著了一般铣焊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上罕伯,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天曲伊,我揣著相機(jī)與錄音,去河邊找鬼。 笑死坟募,一個(gè)胖子當(dāng)著我的面吹牛岛蚤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播懈糯,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼涤妒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了赚哗?” 一聲冷哼從身側(cè)響起她紫,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屿储,沒想到半個(gè)月后贿讹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扩所,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年围详,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朴乖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祖屏。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖买羞,靈堂內(nèi)的尸體忽然破棺而出袁勺,到底是詐尸還是另有隱情,我是刑警寧澤畜普,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布期丰,位于F島的核電站,受9級(jí)特大地震影響吃挑,放射性物質(zhì)發(fā)生泄漏钝荡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一舶衬、第九天 我趴在偏房一處隱蔽的房頂上張望埠通。 院中可真熱鬧,春花似錦逛犹、人聲如沸端辱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舞蔽。三九已至,卻和暖如春码撰,著一層夾襖步出監(jiān)牢的瞬間渗柿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工脖岛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留朵栖,地道東北人砾省。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像混槐,于是被迫代替她去往敵國(guó)和親编兄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,072評(píng)論 25 707
  • 相關(guān)文章Android深入理解四大組件系列 前言 Content Provider做為四大組件之一声登,通常情況下并沒...
    劉望舒閱讀 1,265評(píng)論 4 5
  • 1)https://github.com/LuaDist/luaxml下載壓縮包解壓到指定目錄 2)修改Makef...
    veraxs閱讀 3,962評(píng)論 0 0
  • 2017-02-20 凌晨02:11分 變天了狠鸳,白天伴有雷陣雨 寶貝出生18天了,無(wú)意間發(fā)現(xiàn)了這個(gè)APP悯嗓,寶貝...
    簡(jiǎn)心2017閱讀 261評(píng)論 0 3
  • 五個(gè)月前給大班娃報(bào)了Rise K階段件舵,此前娃在某私立雙語(yǔ)兩年,加上在家教的算是簡(jiǎn)單入門脯厨,簡(jiǎn)單單詞能輸出铅祸,簡(jiǎn)單句子能...
    Nerissaonly閱讀 133評(píng)論 0 0