Android M應(yīng)用啟動(dòng)流程分析
更新:
2016-10-29:更新handleBindApplication部分。
我這個(gè)版本的原則是,有話則長(zhǎng)鞋拟,無(wú)話則短.
以下分析基于6.0.1_r10版本。
先看一張大圖:
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);
}