Activity是Android中最重要的概念,没有之一。我之前写过 Android Tasks、ActivityStack和Activity,主要解释了一下Android Task和Activity这两个概念之间的关系,另外Android Task中包含了一个ActivityStack来管理Activity的关系,今天重新复习一下Activity的启动过程,是在理解Activity的路上往前更进一步。
图片转载自 http://www.cnblogs.com/Jackwen/p/5117313.html
图片和内容不是一一对应的,但是经过拼起来以后呈现出来的是一个更大的图。
以下分析基于6.0.1_r10版本。(转载自刘子瑛)
我们暂时忽略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方法。
|
3. ActivityManagerService之startActivityAsUser
这个方法如其名,还真是只处理跟user相关的工作,调用handleIncomingUser。
之后,调用ActivityStackSupervisor来去处理跟Activity状态相关真正逻辑。
|
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还在征途上。
|
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。
|
6. ActivityStackSupervisor之startActivityUncheckedLocked
路径:frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
通过一系列分析,找到了该执行的目标ActivityStack,然后调用该ActivityStack的startActivityLocked方法针对该任务做具体的操作。
|
7. ActivityStack之startActivityLocked
路径:frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
如果需要的话,这一步中会调用到WmS的setAppStartingWindow,开始准备新应用的启动窗口。
这其中,有重要一步是调用WindowManagerService的addAppToken方法去将信息共步给WmS,为下一步的显示做准备。
最后,调用ActivityStackSupervisor的resumeTopActivitiesLocked方法,将显示的Activities都resume一下。
|
8. ActivityStackSupervisor之resumeTopActivitiesLocked
先获取当前焦点显示的ActivityStack,调其resumeTopActivityLocked。完成后,遍历所有能显示的Activity的stack。
|
9. ActivityStack之resumeTopActivityLocked
调用resumeTopActivityInnerLocked
|
10. ActivityStack之resumeTopActivityInnerLocked
这是第一次进入这个方法,这次我们是走pause桌面这一支,下一次我们就走到最后的startSpecificActivityLocked那一支。
调用startPausingLocked去pause。
|
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对象。
|
12. ApplicationThreadNative的schedulePauseActivity
路径:frameworks/base/core/java/android/app/ApplicationThreadNative.java
AmS要通过IPC来通知给桌面,于是通过Proxy来发送IPC操作.
13. ActivityThread之schedulePauseActivity (桌面进程)
路径:frameworks/base/core/java/android/app/ActivityThread.java
通过IPC,运行桌面应用的ActivityThread的schedulePauseActivity。此处ActivityThread会将这个请求放入队列中,等待运行。
在这段期间,WmS也没闲着,类似于之前我们在startActivityLocked时做的addWindow之类的操作一直在干活。
14. ActivityThread之handlePauseActivity (桌面进程)
终于从队列中轮到出场了,开始执行桌面的onPause吧。
不过先别急,执行onPause之前,先执行performUserLeavingActivity,最后会调到Activity的performUserLeaving。
这个方法做两步:
|
这些都做完了,调用performPauseActivity。
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去启动新进程。
路径:frameworks/base/ core/java/android/os/Process.java
其实就是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。
路径:frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
从socket中读取命令并执行。
这个可以往下再分为4步:
- readArgumentList
- apply security policies
- apply security policies
- preForkAndSpecialize
路径:/frameworks/base/core/java/com/android/internal/os/Zygote.java
这步分为三个子步骤:
- preFork
- nativeForkAndSpecialize
- postForkCommon
路径:/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。
在这个函数中,我们熟悉的AOC版本号的log会输出出来。
这个函数的AOC版本路径在:/aliyunos/aoc/vm/native/dalvik_system_ZygoteHooks.cc中。
|
对应的ART版本在:/art/runtime/native/dalvik_system_ZygoteHooks.cc中。
路径:/libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
只干一件事,把preFork里面stop的monitor们重新打开。这一步要注意,原来的Zygote里面的不要去管了,只看新进程的就好。
路径: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方法
路径:frameworks/base/ core/java/android/app/ActivityThread.java
执行ActivityThread的main方法,新的应用正式上路
路径: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就是在这时候做的。
下面花开两朵说另一枝,回到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)调用从系统服务获取到的。
路径: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交互。
路径:frameworks/base/core/java/android/view/ViewRootImpl.java
ViewRootImpl被构造出来后,会通过WindowManagerGlobal的getWindowSession方法去创建一个与WmS之间的连接。构造中会调到这一句:
|
在正式添加到WmS之前,首先要保证这个View树可以正常接收事件,于是先发起一次requestLayout。
48. ViewRootImpl之requestLayout
这个方法本身是WmS最简单的方法之一,先检查一下是不是UI线程,如果是,就scheduleTraversals,申请做一次遍历。
准备好了之后,setView就会通过mWindowSession去IPC通知WmS去添加一个窗口。
路径: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
第一步先检查权限,比如部分系统窗口就不是应用可以添加的。
第二步去检查是不是重复添加了。
|
第三步,如果是子窗口,就寻找父窗口。
第四步,检查窗口的有效性。
第五步,用WindowState对象来管理窗口的状态。
|
第六步,调整Window属性
第七步,将token加入到mTokenMap中。
第八步,将client.asBinder()加到mWindowMap中。
第九步,将Window们按顺序排列,调用addWindowToListInOrderLocked方法。
这些做完,addView就算完成了,剩下的事情就看遍历的了。
51. ViewRootImpl之scheduleTraversals
准备好了之后,放入队列等待被遍历。
遍历操作,实际逻辑都在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中,在执行三大操作之前,先去看看队列里还有什么未执行的任务没有,有的话就先执行之。
|
由于是第一次画,所以mLayoutRequested为true,我们还不知道窗口大小是多大,于是来一次测量,调用measureHierarchy.
|
测量完成之后,就可以开始布局了,调用relayoutWindow.
55. ViewRootImpl之relayoutWindow
relayoutWindow当然不是本地能搞得定的,于是通过IPC调,mWindowSession的relayout去通知WmS去干这事儿。
IPC调用,调用WmS的relayoutWindow。
57. WindowManagerService之relayoutWindow
WmS准备第一次画之前,先来个进场动画吧。
|
然后创建个新的Surface吧。
|
最后调用performLayoutAndPlaceSurfacesLocked方法
58. WindowManagerService之performLayoutAndPlaceSurfacesLocked
这里边还要走一个最多6次的循环,每次都调用performLayoutAndPlaceSurfacesLockedLoop。
59. WindowManagerService之performLayoutAndPlaceSurfacesLockedLoop
调用performLayoutAndPlaceSurfacesLockedInner
60. WindowManagerService之performLayoutAndPlaceSurfacesLockedInner
真正执行layout的逻辑。
Measure和layout完成了,最后终于可以画了。回到performTraversals中,调用performDraw。
先调用draw去通知绘制线程开始画。
然后把所有的动画全停掉。
如果支持硬件加速,就调用HardwareRenderer抽象类的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函数。
路径:frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp
调用postAndWait。
68. DrawFrameTask::postAndWait
放到队列里,等着VSYNC信号来了就调用吧。
|