Android M應(yīng)用啟動(dòng)流程分析
更新:
2016-10-29:更新handleBindApplication部分。
我這個(gè)版本的原則是,有話則長,無話則短.
以下分析基于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來去處理跟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對象,也就是構(gòu)造ActivityStackSupervisor時(shí)傳進(jìn)來的ActivityManagerService的對象。
調(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,用于存儲Activity的各種狀態(tài)和歷史信息。
然后,通過getFocusedStack方法獲取當(dāng)前獲取焦點(diǎn)的ActivityStack。ActivityStackSupervisor中的mFocusedStack中保存了當(dāng)前的前臺ActivityStack。
下面就準(zhǔn)備切換新進(jìn)程了,先判斷一下是否可以切換,如果處于通話中界面等無法馬上切換的情況。通過ActivityManagerService的checkAppSwitchAllowedLocked方法來做檢查,如果當(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方法針對該任務(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對象。
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來通知給桌面,于是通過Proxy來發(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è)請求放入隊(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也沒閑著,類似于之前我們在startActivityLocked時(shí)做的addWindow之類的操作一直在干活。
14. ActivityThread之handlePauseActivity (桌面進(jìn)程)
終于從隊(duì)列中輪到出場了,開始執(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ì)顟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來做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的消息,然后找到對應(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之后分出來的,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è)簡單封裝。
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)閺倪@一步開始,更具體地說是從Fork and detach開始,新應(yīng)用的進(jìn)程終于fork出來了。從此zygote老進(jìn)程的事情我們不再關(guān)心,我們來看新進(jìn)程號就好了。
Child process setup之后,有一個(gè)重要的函數(shù)會(huì)被執(zhí)行到,這就是ZygoteHooks_nativePostForkChild。
在這個(gè)函數(shù)中,ART版本號會(huì)被打印出來。說明Android Runtime已經(jīng)正式開始工作了。
29-3. postForkCommon
路徑:/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
只干一件事,把preFork里面stop的monitor們重新打開。這一步要注意,原來的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
初始化完成,通過反射來調(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才出場去讀真正的package的信息。讀好之后,再去將BIND_APPLICATION消息放到隊(duì)列里去,這時(shí)候可能正在執(zhí)行setCoreSettings。
38. ActivityThread之handleBindApplication
真正啟動(dòng)Activity之前,還得做一些準(zhǔn)備工作。比如install provider就是在這時(shí)候做的。
38-1 LoadedApk之makeApplication
我們都知道,在Activity之外,對于每個(gè)應(yīng)用,還對應(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)造對象,然后調(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 }
下面花開兩朵說另一枝,回到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)注冊。
最后,通過callActivityOnCreate來調(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對象調(diào)用其addView方法,開始正式通知WmS要添加窗口了。實(shí)際上,獲取的這個(gè)ViewManager,是其子接口WindowManager的實(shí)現(xiàn)類WindowManagerImpl的方法。這個(gè)WindowManagerImpl的對象是通過
(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打交道。它通過單例對象WindowManagerGlobal去訪問ViewRootImpl,再由ViewRootImpl去跟WmS通信。
46. WindowManagerGlobal之a(chǎn)ddView
路徑:frameworks/base/core/java/android/view/WindowManagerGlobal.java
WindowManagerGlobal也只是個(gè)二傳手,最終調(diào)用ViewRootImpl類的setView來真正與WmS交互。
47. ViewRootImpl之setView
路徑:frameworks/base/core/java/android/view/ViewRootImpl.java
ViewRootImpl被構(gòu)造出來后,會(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最簡單的方法之一,先檢查一下是不是UI線程,如果是,就scheduleTraversals,申請做一次遍歷。
準(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對象來管理窗口的狀態(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)用,所有的子對象還沒有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來通知節(jié)點(diǎn)已經(jīng)被attach到Window上了。
在被attach到Window之前,View實(shí)際上是沒有大小的,因?yàn)檫€不知道被用到哪里呢,無法去做測量。
然后,回到performTraversals中,在執(zhí)行三大操作之前,先去看看隊(duì)列里還有什么未執(zhí)行的任務(wù)沒有,有的話就先執(zhí)行之。
getRunQueue().executeActions(mAttachInfo.mHandler);
由于是第一次畫,所以mLayoutRequested為true,我們還不知道窗口大小是多大,于是來一次測量,調(diào)用measureHierarchy.
windowSizeMayChange |= measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);
測量完成之后,就可以開始布局了,調(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)備第一次畫之前,先來個(gè)進(jìn)場動(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信號來了就調(diào)用吧。
void DrawFrameTask::postAndWait() {
AutoMutex \_lock(mLock);
mRenderThread->queue(this);
mSignal.wait(mLock);
}