Android M應用啟動流程分析
更新:
2016-10-29:更新handleBindApplication部分。
我這個版本的原則是,有話則長,無話則短.
以下分析基于6.0.1_r10版本。
先看一張大圖:
1. 桌面的onClick事件(進程:桌面應用的進程)
我們暫時忽略Input處理的過程,以桌面的onClick事件被觸發為起點。
這部分根據Launcher的不同而大同小異。
2. ActivityManagerService之startActivity(進程AmS)
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
桌面調用framework,最后會調到AmS的startActivity方法.
現在是多用戶時代了,startActivity現在唯一做的事兒,就是通過UserHandle.getCallingUserId()去獲取當前的user id,然后調用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
這個方法如其名,還真是只處理跟user相關的工作,調用handleIncomingUser。
之后,調用ActivityStackSupervisor來去處理跟Activity狀態相關真正邏輯。
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(進程AmS)
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
先解釋一下為什么叫MayWait,因為調用startActivity是可能要等待結果的startActivityForResult,那就要掛起調用者。
首先,startActivityMayWait要讀取一些信息。從4.4開始,這部分邏輯寫到resolveActivity方法中,它會調用PackageManagerService的resolveIntent方法。這個方法會先調用queryIntentActivities方法出查詢相關的列表,然后再調用chooseBestActivity方法去選擇。為了不影響主線,這些支線內容后面再講。
主線往下走,進入startActivityLocked。Locked意思是調用者需要保證加鎖保護,不能重復調用,在startActivityMayWait中,是采用mService對象,也就是構造ActivityStackSupervisor時傳進來的ActivityManagerService的對象。
調用成功了之后,如果需要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
前面先做一系列檢查的工作,比如權限,比如Intent防火墻檢查。
準備做好之后,就new一個ActivityRecord,用于存儲Activity的各種狀態和歷史信息。
然后,通過getFocusedStack方法獲取當前獲取焦點的ActivityStack。ActivityStackSupervisor中的mFocusedStack中保存了當前的前臺ActivityStack。
下面就準備切換新進程了,先判斷一下是否可以切換,如果處于通話中界面等無法馬上切換的情況。通過ActivityManagerService的checkAppSwitchAllowedLocked方法來做檢查,如果當前不允許做進程切換,就先存到PendingActivityLaunch的列表中,等待以后有機會再調用。
如果允許做切換,那么先檢查一下當前是否有以前的等待任務,如果有就先執行它們,調用doPendingActivityLaunchesLocked方法去執行這個循環。
如果以上都完成了,就調用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
通過一系列分析,找到了該執行的目標ActivityStack,然后調用該ActivityStack的startActivityLocked方法針對該任務做具體的操作。
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
如果需要的話,這一步中會調用到WmS的setAppStartingWindow,開始準備新應用的啟動窗口。
這其中,有重要一步是調用WindowManagerService的addAppToken方法去將信息共步給WmS,為下一步的顯示做準備。
最后,調用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
先獲取當前焦點顯示的ActivityStack,調其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
調用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
這是第一次進入這個方法,這次我們是走pause桌面這一支,下一次我們就走到最后的startSpecificActivityLocked那一支。
調用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開始發起pause桌面的操作
如果不是從桌面啟動的話,就要去為上一個應用抓個用于顯示在近期任務里的圖。
prev.updateThumbnailLocked(screenshotActivities(prev), null);
處理完成之后,通知桌面應用去執行onPause。
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags, dontWait);
這個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來發送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 (桌面進程)
路徑:frameworks/base/core/java/android/app/ActivityThread.java
通過IPC,運行桌面應用的ActivityThread的schedulePauseActivity。此處ActivityThread會將這個請求放入隊列中,等待運行。
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時做的addWindow之類的操作一直在干活。
14. ActivityThread之handlePauseActivity (桌面進程)
終于從隊列中輪到出場了,開始執行桌面的onPause吧。
不過先別急,執行onPause之前,先執行performUserLeavingActivity,最后會調到Activity的performUserLeaving。
這個方法做兩步:
final void performUserLeaving() {
onUserInteraction();
onUserLeaveHint();
}
這些都做完了,調用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
首先判斷一下狀態,如果已經pause了,那就需要先resume之。當然,如果pause了之后正在finishing中,就算了,不是的話,拋個RuntimeException,問問調用者不先resume是為哪般。
沒有異常的話,先調用callCallActivityOnSaveInstanceState,這個會通過Instrumentation的callActivityOnSaveInstanceState去調用Activity的performSaveInstanceState, 然后會調到Activity的onSaveInstanceState。還會將對話框的信息做保存操作。
保存完狀態之后,再調用Instrumentation的callActivityOnPause。然后調用Activity的performPause。
Activity在onPause之前,先通知各個Fragment去onPause,再調用Activity的onPause.
performPauseActivity結束后,回到launchPauseActivity,下面通知AMS,調IPC來做activityPaused。
16. ActivityManagerNative 之activityPaused
路徑:frameworks/base/core/java/android/app/ActivityManagerNative.java
桌面的onPause執行完了,通過IPC通知AmS,可以啟動新應用了。
17. ActivityManagerService之activityPaused
路徑:services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到activityPaused的消息,然后找到對應的ActivityStack的activityPausedLocked。
18. ActivityStack之activityPausedLocked
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
然后調用completePausedLocked。
19. ActivityStack之completePauseLocked
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
到此,桌面的onPause正式告一段落。
結束之后,再次調用前面我們已經遇到過的ActivityStackSupervisor的resumeTopActivitiesLocked,前一次我們走了一半就調pause過程去了,這次我們將走到最后。
20. ActivityStackSupervisor之resumeTopActivitiesLocked
還跟上次一樣,調相應的ActivityStack的resumeTopActivityLocked。
21. ActivityStack之resumeTopActivityLocked
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
這個方法只是一個十幾行的wrapper,除了設了個flag和處理鎖屏之外,直接調用resumeTopActivityInnerLocked方法。
22. ActivityStack之resumeTopActivityInnerLocked
這個大方法走到最后,執行ActivityStackSupervisor的startSpecificActivityLocked。
(注:這個方法是5.0之后分出來的,4.4上還在resumeTopActivityLocked里面)
23. ActivityStackSupervisor之startSpecificActivityLocked (AmS進程)
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
從這里,又從ActivityStackSupervisor調回ActivityManagerService,調用startProcessLocked。
24. ActivityManagerService 之startProcessLocked
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
通過調用android.os.Process的start去啟動新進程。
25. Process.start
路徑:frameworks/base/ core/java/android/os/Process.java
其實就是startViaZygote的一個簡單封裝。
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
主要是處理參數,然后調用zygoteSendArgsAndGetResult去通過socket通信去通知zygote。
27. Process.zygoteSendArgsAndGetResult
路徑:frameworks/base/core/java/android/os/Process.java
通過socket通知Zygote進程去fork新進程。接收方是ZygoteConnection。
28. ZygoteConnection.runOnce
路徑:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
從socket中讀取命令并執行。
這個可以往下再分為4步:
- readArgumentList
- apply security policies
- apply security policies
- preForkAndSpecialize
29. Zygote之forkAndSpecialize
路徑:/frameworks/base/core/java/com/android/internal/os/Zygote.java
這步分為三個子步驟:
- preFork
- nativeForkAndSpecialize
- postForkCommon
29-1. ZygoteHooks.PreFork
路徑:/libcore/dalvik/src/main/java/dalvik/system/ ZygoteHooks.java
這步離開了frameworks/base,進入了libcore。這里面要注意,不能調用Android的API,打個log什么的都要注意。
- Daemons.stop()
停掉GC,停掉finalizer等,fork進程時不需要這些 - waitUntilAllThreadsStopped()
確保fork之前只有一個線程在運行 - nativePreFork()
給虛擬機一個機會去在fork之前做點處理
29-2. com_android_internal_os_Zygote_nativeForkAndSpecialize
路徑:/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
這是我們第一次進入C++層。真正做事的函數是ForkAndSpecializeCommon。
真正開始fork新進程
- SetSigChldHandler
- Fork and detach(新進程從這一步開始誕生)
- child process setup
這一步是值得大書特書的一步,因為從這一步開始,更具體地說是從Fork and detach開始,新應用的進程終于fork出來了。從此zygote老進程的事情我們不再關心,我們來看新進程號就好了。
Child process setup之后,有一個重要的函數會被執行到,這就是ZygoteHooks_nativePostForkChild。
在這個函數中,ART版本號會被打印出來。說明Android Runtime已經正式開始工作了。
29-3. postForkCommon
路徑:/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
只干一件事,把preFork里面stop的monitor們重新打開。這一步要注意,原來的Zygote里面的不要去管了,只看新進程的就好。
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
初始化完成,通過反射來調用ActivityThread的main方法
32. ActivityThread main
路徑:frameworks/base/ core/java/android/app/ActivityThread.java
執行ActivityThread的main方法,新的應用正式上路
33. Proxy:attachApplication
路徑:frameworks/base/
新的Activity建好了,要通知AmS,走IPC。
34. ActivityManagerService之attachApplication
路徑: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
AmS收到attach的通知,一切準備就緒。
35. AMS:attachApplicationLocked
路徑:frameworks/base/ services/core/java/com/android/server/am/ActivityManagerService.java
其它部分都是線性的,這部分我們不得不分成兩個部分各表一支了。這兩部分分別走IPC,最后在ActivityThread的隊列中匯合。
首先是bindApplication。
36. ApplicationThreadProxy之bindApplication
IPC調用
路徑:frameworks/base/core/java/android/app/ApplicationThreadNative.java
37. ActivityThread之bindApplication
路徑:frameworks/base/core/java/android/app/ActivityThread.java
主要包括兩部分的操作,雖然這個方法不叫做scheduleXXX,但是實際上兩步的操作都是放到隊列中。
到這一步的時候,其實我們只是啟動了一個空進程而己,跟實際的apk還一點關系也沒有。
首先,如果services不為空的話,先初始化一下services cache。
ServiceManager.initServiceCache(services);
然后,schedule第一個任務,setCoreSettings(coreSettings);
這個最終會走到handleSetCoreSettings。
下面,PM才出場去讀真正的package的信息。讀好之后,再去將BIND_APPLICATION消息放到隊列里去,這時候可能正在執行setCoreSettings。
38. ActivityThread之handleBindApplication
真正啟動Activity之前,還得做一些準備工作。比如install provider就是在這時候做的。
38-1 LoadedApk之makeApplication
我們都知道,在Activity之外,對于每個應用,還對應一個Application類。這個Application就是在LoadApk的makeApplication方法時構造的。
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 }
下面調用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方法去真正創建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
通過反射構造對象,然后調用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之attach
attach再調用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之attachBaseContext
```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構造好之后,將調用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方法,它將會調用到realStartActivityLocked。
39. ActivityStackSupervisor之realStartActivityLocked(AmS進程)
路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
這時算是真正啟動,通過Activity,可以執行onCreate了。
40. ApplicationThreadNative之scheduleLaunchActivity
路徑:frameworks/base/core/java/android/app/ApplicationThreadNative.java
IPC通道,通知本地進程
41. ActivityThread之scheduleLaunchActivity
路徑:frameworks/base/ core/java/android/app/ActivityThread.java
ActivityThread收到,將命令放入隊列。
42. ActivityThread之handleLaunchActivity
路徑:frameworks/base/ core/java/android/app/ActivityThread.java
正式開始Activity的啟動流程。
43. ActivityThread之performLaunchActivity
路徑:frameworks/base/ core/java/android/app/ActivityThread.java
負責new出Activity的實例,makeApplication,然后調用Activity.attach向系統注冊。
最后,通過callActivityOnCreate來調用應用的onCreate方法。
44. ActivityThread之handleResumeActivity
路徑:frameworks/base/ core/java/android/app/ActivityThread.java
首先,通過performResumeActivity方法調用應用的onResume方法。
如大家所熟知的,執行完onResume之后,真正的繪制工作就才真正開始。
ActivityThread通過ViewManager對象調用其addView方法,開始正式通知WmS要添加窗口了。實際上,獲取的這個ViewManager,是其子接口WindowManager的實現類WindowManagerImpl的方法。這個WindowManagerImpl的對象是通過
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)調用從系統服務獲取到的。
45. WindowManagerImpl之addView
路徑:frameworks/base/core/java/android/view/WindowManagerImpl.java
ViewManager只是一個接口,用于定義功能,本身并不與WmS打交道。它通過單例對象WindowManagerGlobal去訪問ViewRootImpl,再由ViewRootImpl去跟WmS通信。
46. WindowManagerGlobal之addView
路徑:frameworks/base/core/java/android/view/WindowManagerGlobal.java
WindowManagerGlobal也只是個二傳手,最終調用ViewRootImpl類的setView來真正與WmS交互。
47. ViewRootImpl之setView
路徑:frameworks/base/core/java/android/view/ViewRootImpl.java
ViewRootImpl被構造出來后,會通過WindowManagerGlobal的getWindowSession方法去創建一個與WmS之間的連接。構造中會調到這一句:
mWindowSession = WindowManagerGlobal.getWindowSession();
在正式添加到WmS之前,首先要保證這個View樹可以正常接收事件,于是先發起一次requestLayout。
48. ViewRootImpl之requestLayout
這個方法本身是WmS最簡單的方法之一,先檢查一下是不是UI線程,如果是,就scheduleTraversals,申請做一次遍歷。
準備好了之后,setView就會通過mWindowSession去IPC通知WmS去添加一個窗口。
49. Session之addToDisplay
路徑:frameworks/base/services/core/java/com/android/server/wm/Session.java
IPC調用WmS的addWindow方法。
50. WindowManagerService之addWindow
路徑:frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
第一步先檢查權限,比如部分系統窗口就不是應用可以添加的。
第二步去檢查是不是重復添加了。
if (mWindowMap.containsKey(client.asBinder())) {
Slog.w(TAG, "Window " + client + " is already added");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
第三步,如果是子窗口,就尋找父窗口。
第四步,檢查窗口的有效性。
第五步,用WindowState對象來管理窗口的狀態。
win = new WindowState(this, session, client, token,attachedWindow, appOp0, seq, attrs, viewVisibility, displayContent);
第六步,調整Window屬性
第七步,將token加入到mTokenMap中。
第八步,將client.asBinder()加到mWindowMap中。
第九步,將Window們按順序排列,調用addWindowToListInOrderLocked方法。
這些做完,addView就算完成了,剩下的事情就看遍歷的了。
51. ViewRootImpl之scheduleTraversals
準備好了之后,放入隊列等待被遍歷。
52. ViewRootImpl之doTraversal
遍歷操作,實際邏輯都在performTraversals中。
53. ViewRootImpl之performTraversals
遍歷的核心邏輯,主要有三個步驟:measure, layout和draw。
如果是第一次調用,所有的子對象還沒有attach到窗口上,需要首先dispatchAttachedToWindow。Attach到哪里呢,PhoneWindow的DecorView。
這個方法沒有被DecorView重載,直接調用的是ViewGroup的dispatchAttachedToWindow。
54. ViewGroup之dispatchAttachedToWindow
根元素被attach到Window上之后,開始遞歸它的子節點,使每個子節點都attach到父節點上。
執行結束后,通過回調onAttachedToWindow來通知節點已經被attach到Window上了。
在被attach到Window之前,View實際上是沒有大小的,因為還不知道被用到哪里呢,無法去做測量。
然后,回到performTraversals中,在執行三大操作之前,先去看看隊列里還有什么未執行的任務沒有,有的話就先執行之。
getRunQueue().executeActions(mAttachInfo.mHandler);
由于是第一次畫,所以mLayoutRequested為true,我們還不知道窗口大小是多大,于是來一次測量,調用measureHierarchy.
windowSizeMayChange |= measureHierarchy(host, lp, res,desiredWindowWidth, desiredWindowHeight);
測量完成之后,就可以開始布局了,調用relayoutWindow.
55. ViewRootImpl之relayoutWindow
relayoutWindow當然不是本地能搞得定的,于是通過IPC調,mWindowSession的relayout去通知WmS去干這事兒。
56. Session之relayout
IPC調用,調用WmS的relayoutWindow。
57. WindowManagerService之relayoutWindow
WmS準備第一次畫之前,先來個進場動畫吧。
winAnimator.applyEnterAnimationLocked();
然后創建個新的Surface吧。
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
最后調用performLayoutAndPlaceSurfacesLocked方法
58. WindowManagerService之performLayoutAndPlaceSurfacesLocked
這里邊還要走一個最多6次的循環,每次都調用performLayoutAndPlaceSurfacesLockedLoop。
59. WindowManagerService之performLayoutAndPlaceSurfacesLockedLoop
調用performLayoutAndPlaceSurfacesLockedInner
60. WindowManagerService之performLayoutAndPlaceSurfacesLockedInner
真正執行layout的邏輯。
Measure和layout完成了,最后終于可以畫了。回到performTraversals中,調用performDraw。
61. ViewRootImpl之performDraw
先調用draw去通知繪制線程開始畫。
然后把所有的動畫全停掉。
62. ViewRootImpl之draw
如果支持硬件加速,就調用HardwareRenderer抽象類的draw方法去畫。
63. ThreadedRenderer之draw
路徑:frameworks/base/core/java/android/view/ThreadedRenderer.java
64. ThreadedRenderer之nSyncAndDrawFrame
這是個native方法,真正實現調用GPU去繪制。調用的是android_view_ThreadedRender_syncAndDrawFrame函數。
65. android_view_ThreadedRenderer_syncAndDrawFrame函數
路徑:frameworks/base/core/jni/android_view_ThreadedRenderer.cpp
再調用RenderProxy的syncAndDrawFrame。
66. RenderProxy::syncAndDrawFrame
路徑:frameworks/base/libs/hwui/renderthread/RenderProxy.cpp
調用DrawFrameTask的drawFrame函數。
67. DrawFrameTask::drawFrame
路徑:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
調用postAndWait。
68. DrawFrameTask::postAndWait
放到隊列里,等著VSYNC信號來了就調用吧。
void DrawFrameTask::postAndWait() {
AutoMutex \_lock(mLock);
mRenderThread->queue(this);
mSignal.wait(mLock);
}