[Android]从Launcher开始启动App流程源码分析
从Launcher开始启动App流程源码分析
com.android.launcher.Launcher
就是我们的Launcher页面了,可以看到Launcher其实也是一个Activity
:
1 | public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener { |
既然是Activity
,那当然也会有onCreate
、onResume
等生命周期了,按照逻辑,应该会去加载所有App,以网格的布局显示在页面上,果然,在onResume
看到了这个方法:
1 |
|
看方法名就可以猜到这个方法就是用来加载所有App信息的,进入这个方法:
1 | private void startLoaders() { |
这里调用sModel
(LauncherModel
类型)的loadUserItems
方法去加载数据了,sModel
明显属于Model
层,进入loadUserItems
方法:
1 | void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged, |
然后使用DesktopItemsLoader
在mDesktopLoaderThread
线程中加载,:
1 | private class DesktopItemsLoader implements Runnable { |
然后我们回到Launcher
的onDesktopItemsLoaded
方法:1
2
3
4void onDesktopItemsLoaded(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) {
// ...
bindDesktopItems(shortcuts, appWidgets);
}
继续进入bindDesktopItems
方法:
1 | private void bindDesktopItems(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) { |
进入startBindingItems
方法:
1 | public void startBindingItems() { |
这里使用了Handler
发送消息,进入Handler
的handleMessage
方法:
1 |
|
接收到消息之后调用bindItems
方法:
1 | private void bindItems(Launcher.DesktopBinder binder, ArrayList<ItemInfo> shortcuts, int start, int count) { |
这里我们只考虑app或者app快捷方式的情况,文件夹和widgets暂时不考虑。app或者app快捷方式实质上都是进入了这个逻辑中,调用createShortcut
方法:
1 | // 重载方法,最终都会调用这个方法 |
这里首先inflater出item的布局,然后设置text
和OnClickListener
,还有tag,这个tag是ApplicationInfo
,里面包含了各种App信息,是从App的AndroidManifest.xml
的<application>
标签中解析出来的。既然设置了点击事件,显然,点击后应该会打开对应的App才对。所以继续看onClick
方法:
1 | public void onClick(View v) { |
点击App就会通过startActivitySafely
方法使用刚才设置的tag,也就是ApplicationInfo
中的intent进行跳转:
1 | void startActivitySafely(Intent intent) { |
然后我们来看看打开某个app的时候整个流程是怎么走的。接着上面的的startActivity()
方法走:
1 | public void startActivity(Intent intent, @Nullable Bundle options) { |
可以看到,不管你是调用了startActivity
还是startActivityForResult
方法,startActivityForResult
方法,并且如果是调用的startActivity
,则默认requestCode
就是-1,所以如果你想调用startActivityForResult
的时候,注意不能把requestCode
设置为-1,否则它的效果就跟startActivity
一样了,不会再回调onActivityResult
!,再看看startActivityForResult
的实现:
1 | public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { |
可以看到,Activity内部是使用mInstrumentation
(Instrumentation
类型)执行execStartActivity
方法来实现Activity
跳转的,执行完毕后会返回一个Instrumentation.ActivityResult
。
然后查看Instrumentation::execStartActivity
:
1 | public ActivityResult execStartActivity( |
首先通过ActivityManagerNative.getDefault()
获得一个IActivityManager
的实现类:
1 | static public IActivityManager getDefault() { |
先通过Binder IPC的方式从服务端获取一个Activity Manager
,然后通过ActivityManagernative
封装成一个代理ActivityManagerProxy
对象,然后调用startActivity
也是使用了Binder IPC进行与服务器端的通信,(整个Android系统的通信机制使用了大量的Binder IPC,这个以后再专门讨论这个吧),接着,我们进入到了com.android.server.am.ActivityManagerService
的startActivity
方法:
1 |
|
接下来的调用链:
-> startActivityAsUser
-> startActivityMayWait
-> startActivityLocked
-> startActivityUncheckedLocked
-> targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)
-> mStackSupervisor.resumeTopActivitiesLocked(this, r, options)
-> resumeTopActivityInnerLocked(prev, options);
-> mStackSupervisor.startSpecificActivityLocked(next, true, true)
startSpecificActivityLocked
方法如下:
1 | void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { |
首先从mService
找出对应需要启动Activity的进程(通过进程名字和uid,进程名字可以在AndroidManifest.xml
中配置)如果可以获取到,说明这个Activity所属的进程已经存在了,也就是说app已经在运行了,那就会调用realStartActivityLocked
,否则,如果该Activity所在的App是第一次启动,则会调用mService.startProcessLocked
方法:
1 | final ProcessRecord startProcessLocked(/*...*/){ |
这3个重载方法做的事情就是,先根据进程名字调用getProcessRecordLocked()
获取ProcessRecord
,如果ProcessRecord
不存在,则调用newProcessRecordLocked()
方法建立一个ProcessRecord
,并且新的ProcessRecord
绑定了ApplicationInfo
,uid
等信息,但后进入第三个重载方法,执行新建、启动进程。
再看Process::start
的实现:
1 | public static final ProcessStartResult start(/*...*/){ |
接下来就是通过Zygote
进程fork
一个新的进程作为app的进程。这里要需要讲的一个参数是processClass
,这个参数表示一个类,它用来作为新创建的进程的主入口,会调用这个类的静态main
方法,这个参数在startProcessLocked
方法中会被检查重置,如果是null的话,就默认是android.app.ActivityThread
。
现在App的进程也创建成功了,就会进入android.app.ActivityThread
的静态的main
中:
1 | public static void main(String[] args) { |
然后创建了一个ActivityThread
,说明每当一个新的app进程被创建,都会对应一个新的ActivityThread
实例,然后调用它的attach
方法:
1 | private void attach(boolean system) { |
然后再次通过Binder IPC调用ActivityManagerProxy
的attachApplication
,传入的ApplicationThread
(Binder)参数用于在服务端进行回调通信。最后进入ActivityManagerService::attachApplication
,再调用attachApplicationLocked(thread, callingPid)
1 | private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { |
首先,通过pid获取刚刚创建的进程,然后对app进行一些初始化工作,然后调用bindApplication
远程调用客户端ActivityThread::bindApplication
,再通过Handler
调用到ActivityThread::handleBindApplication
方法:
1 | private void handleBindApplication(AppBindData data) { |
首先,创建一个当前App的Context
,然后如果data.instrumentationName != null
,则初始化Instrumentation
相关的变量,并创建Instrumentation
的ApplicationInfo
等对象来创建Instrumentation
的Context
,然后创建Instrumentation
对象,并调用它的init
方法进行初始化。如果data.instrumentationName == null
,则new一个Instrumentation
(在一个进程中只会有一个Instrumentation
实例)然后创建Application
对象,并调用它的onCreate
方法,这样Application
就会被回调了。
然后我们回到ActivityManagerService::attachApplicationLocked
方法,远程执行完thread.bindApplication
方法之后,接下来会调用mStackSupervisor.attachApplicationLocked(app)
方法:
1 | boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { |
先通过topRunningActivityLocked
从堆栈顶端获取要启动的Activity,然后realStartActivityLocked(hr, app, true, true)
:
1 | final boolean realStartActivityLocked(ActivityRecord r, |
继续通过Binder IPC远程调用scheduleLaunchActivity
方法,然后进入ActivityThread
的scheduleLaunchActivity
方法中,然后通过Handler
进入handleLaunchActivity
方法:
1 | private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){ |
先调用performLaunchActivity
方法返回一个Activity
,然后调用handleResumeActivity
方法让该Activity
进入onResume
状态。所以很显然在performLaunchActivity
中肯定是生成了Activity
实例,并调用了onCreate
方法了,来看下代码:
1 | private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
首先,初始化LoadedApk
,然后通过Instrumentation
来创建一个Activity
实例,通过createBaseContextForActivity
方法创建一个Activity Context
,调用activity
的attach
方法,然后依次触发该Activity
的onCreate
、onRestoreInstanceState
、onPostCreate
等生命周期方法。
createBaseContextForActivity
方法如下:
1 | private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { |
通过ContextImpl::createActivityContext
创建的Context
对象,可以发现,不论是System Context/App Context/Activity Context
,这些Context
都是通过ContextImpl
生成的,具体这里再挖个坑先。
再继续进入Activity::attach
方法:
1 | final void attach(Context context, ActivityThread aThread, |
上面对Activity
与ActivityThread
、Instrumentation
等进行了绑定,所以说每个Activity
都含有一个ActivityThread
引用和一个Instrumentation
引用,而ActivityThread
实例和Instrumentation
实例在一个进程中都只有一个实例,因为ActivityThread
是在进程被创建成功后,进入ActivityThread
的static main()
时才会被创建,而Instrumentation
则是在ActivityThread
被创建后进行attach
的之后被创建。
启动应用流程所有方法链调用总结:
Activity::startActivity
Activity::startActivityForResult
Instrumentation::execStartActivity
:
携带参数:
1.who
:from的Context
2.contextThread
:from的ActivityThread
的ApplicationThread
,ApplicationThread
中可以通过Binder IPC提供给服务端回调Activity
生命周期等操作(from的主线程)。
3.mToken
:Binder
类型,用来标识from的Activity,可能为null。
4.target
:from的Activity(所以是用来接收跳转结果的),如果不是从Activity跳转则为null。
5.intent
:跳转Intent。
6.requestCode
:如果是startActivity
,则为-1。
7.options
:额外Bundle数据。ActivityManagerProxy::startActivity()
:
携带参数:
1.caller
:上面的contextThread
,from主线程。
2.callingPackage
:from的Context包名。
3.intent
:跳转Intent。
4.resolvedType
:跳转Intent的MIME类型。
5.resultTo
:上面的token
,Binder
类型,用来标识from的Activity。
6.resultWho
:from的Activity的mEmbeddedID(唯一标示字符串)
7.requestCode
:如果是startActivity
,则为-1。
8.startFlags
:默认传入为0。
9.profilerInfo
:默认传入为null。
10.options
:额外Bundle数据。ActivityManagerService::startActivity()
(通过Binder IPC调用):
携带参数跟上面一样。ActivityManagerService::startActivityAsUser
携带参数包括ActivityManagerService::startActivity()
所有的参数,最再加一个:
1.userId
:userId,根据给当前进程分配的Linux UID(这个UID可以用来让上层系统服务进行身份识别和权限检查)得到一个userId(如果不是多用户,则直接返回0)。ActivityStackSupervisor::startActivityMayWait()
参数:
1.caller
:上面的caller/contextThread
,from主线程。
2.callingUid
:调用用户uid。
3.callingPackage
:from的Context包名。
4.intent
:跳转Intent。
5.resolvedType
:跳转Intent的MIME类型。
6.voiceSession
:传null。
7.voiceInteractor
:传null。
8.resultTo
:上面的resultTo/token
,Binder
类型,用来标识from的Activity。
9.resultWho
:from的Activity的mEmbeddedID(唯一标示字符串)
10.requestCode
:如果是startActivity
,则为-1。
11.startFlags
:传null。
12.profilerInfo
:传null。
13.outResult
:传null。
14.config
:传null。
15.options
:额外数据。
16.ignoreTargetSecurity
:false。
17.userId
:上面的userId
,根据给当前进程分配的Linux UID(这个UID可以用来让上层系统服务进行身份识别和权限检查)得到一个userId(如果不是多用户,则直接返回0)。
18.iContainer
:传null。
19.inTask
:null。ActivityStackSupervisor::startActivityLocked()
:
参数:
1.caller
:上面的caller/contextThread
,from主线程。
2.intent
:跳转Intent。
3.resolvedType
:跳转Intent的MIME类型。
4.aInfo
:ActivityInfo
类型,解析from的Activity的Intent信息。
5.voiceSession
:传null。
6.voiceInteractor
:传null。
7.resultTo
:上面的resultTo/token
,Binder
类型,用来标识from的Activity。
8.resultWho
:from的Activity的mEmbeddedID(唯一标示字符串)
9.requestCode
:如果是startActivity
,则为-1。
10.callingPackage
:from的Context包名。
11.startFlags
:传null。
12.options
:额外数据。
13.ignoreTargetSecurity
:false。
14.componentSpecified
:是否显示指定了component
。
15.outActivity
:传null。
16.container
:上面的iContainer
,转型成了ActivityContainer
,还是null。
17.inTask
:null。
在这个方法中,通过ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
获取到之前创建的ProcessRecord
,然后从Activity
栈中根据resultTo/token
获取到对应from Activity的ActivityRecord
(sourceRecord),然后创建将要跳转的Activity的ActivityRecord对象(Token
也是在这个时候生成的)。ActivityStackSupervisor::startActivityUncheckedLocked()
:
参数:
1.r
:ActivityRecord
类型,就是ActivityStackSupervisor::startActivityLocked()
中创建的将要跳转的Activity的ActivityRecord对象。
2.sourceRecord
:就是ActivityStackSupervisor::startActivityLocked()
方法获取的from Activity的sourceRecord
。
3.voiceSession
:传null。
4.voiceInteractor
:传null。
5.startFlags
:传null。
6.doResume
:传true。
7.options
:额外数据。
8.inTask
:null。
这个方法中有大量的代码来处理task/stack
等方面的逻辑,以后再仔细深入这个方法。ActivityStrack::startActivityLocked()
:
方法调用者:ActivityStack
类型,targetStack
:在ActivityStackSupervisor::startActivityUncheckedLocked()
中确定的需要添加到的ActivityStack
。
参数:
1.r
:ActivityRecord
类型,就是ActivityStackSupervisor::startActivityLocked()
中创建的跳转的Activity的ActivityRecord对象。
2.newTask
:是否Intent
是否设置了Intent.FLAG_ACTIVITY_NEW_TASK
。
3.doResume
:传true。
4.keepCurTransition
:这个具体后面再研究,跟Intent
的flag有关。
5.options
:额外数据。
同样,这个方法中有大量的代码来处理task/stack
等方面的逻辑,以后再仔细深入这个方法(执行完这个方法后,ActivityRecord
就会被真正加入到ActivityStack
中)。ActivityStackSupervisor::resumeTopActivitiesLocked()
:
参数:
1.targetStack
:在ActivityStackSupervisor::startActivityUncheckedLocked()
中确定的需要添加到的ActivityStack
。
2.target
:ActivityRecord
类型,就是ActivityStackSupervisor::startActivityLocked()
中创建的跳转的Activity的ActivityRecord对象。
3.targetOptions
:额外数据。ActivityStack::resumeTopActivityLocked()
:
参数:
1.prev
:ActivityRecord
类型,就是ActivityStackSupervisor::startActivityLocked()
中创建的跳转的Activity的ActivityRecord对象。
2.options
:额外数据。ActivityStack::resumeTopActivityInnerLocked()
:
参数:
1.prev
:ActivityRecord
类型,就是ActivityStackSupervisor::startActivityLocked()
中创建的跳转的Activity的ActivityRecord对象。
2.options
:额外数据。ActivityStackSupervisor::startSpecificActivityLocked()
:
参数:
1.r
:最顶部没有处于finishing的Activity,就是刚刚在startActivityLocked
中加入的将要跳转的ActivityRecord
,通过topRunningActivityLocked(null)
查找
2.andResume
:传true
3.checkConfig
:传trueActivityManagerService::startProcessLocked()
:
参数:
1.processName
:创建进程的名称,就是ActivityStack::startSpecificActivityLocked()
中的r.processName
2.info
:ApplicationInfo
,也是r.info.applicaitonInfo
,具体可以查看ActivityStackSupervisor::startActivityLocked()
中创建ActivityRecord
的代码。
3.knownToBeDead
:传true。
4.intentFlags
:传0。
5.hostingType
:传字符串“activity”。
6.hostingName
:ComponentName
类型,intent
中的Componentname
7.allowWhileBooting
:传false。
8.isolated
:传false
9.keepIfLarge
传trueActivityManagerService::startProcessLocked()
(重载方法):
参数包含上面所有,多了以下几个:
1.isolatedUid
:传0
2.abiOverride
:传null
3.entryPoint
:传null
4.entryPointArgs
传null
5.crashHandler
传null
注意:在这个方法中,会创建新进程的ProcessRecord
对象,并绑定ApplicationInfo
等信息,这样,启动进程后进行bindApplicaiton
的时候就可以根据进程PID获取到所有的ApplicationInfo
信息了。ActivityManagerService::startProcessLocked()
(重载方法):
参数:
1.app
:ProcessRecord
类型,创建的进程。
2.hostingType
:传字符串“activity”。
3.hostingNameStr
:通过hostingName
生成的字符串(包名 + “/“ + 类的简单类名)
4.abiOverride
:传null
5.entryPoint
:传null
6.entryPointArgs
传nullProcess.start()
参数(省略部分参数):
1.processClass
:上面的entryPoint
,但是并不是null了,而是android.app.ActivityThread
,因为在ActivityManagerService::startProcessLocked()
中被设置默认值了,它表示一个类,用来作为新创建的进程的主入口,会调用这个类的静态main方法。所以启动完这个进程就会进入ActivityThread
的static main()
方法。
2.zygoteArgs
:fork zygote进程时的参数。ActivityThread::main()
ActivityThread::attach()
ActivityManagerProxy::attachApplication()
:
参数:
1.mAppThread
:ApplicationThread()
类型,Binder,用来提供给AMS调用。ActivityManagerService::attachApplication()
:
参数:
1.mAppThread
:ApplicationThread()
类型,Binder,用来提供给AMS调用。ActivityManagerService::attachApplicationLocked()
:
参数:
1.thread
:ApplicationThread()
类型,Binder,用来提供给AMS调用。上面的mAppThread
。
2.pid
:当前调用的进程PID。IApplicationThread::bindApplication()
:
方法调用调用者:上面的thread/mAppThread
,Binder,用来提供给AMS调用。
参数(省略部分参数):
1.packageName
:用的进程名字processName
2.info
:ApplicationInfo
类型,从ProcessRecord
中的instrumentationInfo或者info
,这个ApplicationInfo
是在建立ProcessRecord
时就保存了。ActivityThread::bindApplication()
:
参数:同上ActivityThread::handleBindApplication()
:
通过Handler调用。
参数:
1.data
:AppBindData
类型,里面包含的类型processName
,providers
,instrumentationName
,instrumentationArgs
,instrumentationWatcher
,instrumentationUiAutomationConnection
,config
等数据。ActivityManagerService
中的ActivityThread::bindApplication()
执行完毕之后ActivityStackSupervisor::attachApplicationLocked()
:
参数:
1.app
:新建的进程绑定的ProcessRecord
。ActivityStackSupervisor::realStartActivityLocked()
:
参数:
1.r
:ActivityRecord
类型,topRunningActivityLocked从堆栈顶端获取要启动的Activity。
2.app
:新建的进程绑定的ProcessRecord
。
3.andResume
:传入true
4.checkConfig
:传入trueIApplicationThread::scheduleLaunchActivity()
:
参数(部分):
1.intent
:将要启动的ActivityRecord
中的intent
。
2.token
:将要启动的ActivityRecord
中的token
。
3.info
:将要启动的ActivityRecord
中的ApplicationInfo
。ActivityThread::scheduleLaunchActivity()
:
Binder IPC调用,参数与IApplicationThread::scheduleLaunchActivity()
相同。ActivityThread::handleLaunchActivity()
:
该方法通过Handler调用,参数同上。
1.r
:ActivityClientRecord
类型,在ActivityThread::scheduleLaunchActivity()
中封装,包括的数据有token
,ident
,intent
,activityInfo
等等,但是LoadedApk
是这时根据包名从ActivityThread
中弱引用缓存中获取的的。
2.customIntent
:nullActivityThread::performLaunchActivity()
:
参数与ActivityThread::handleLaunchActivity()
相同。Activity::attach()
:
参数(部分):
1.context
:ActivityThread::performLaunchActivity()
中创建的Activity Context
。
2.aThread
:ActivityThread
类型,主线程,一个进程都共用一个。
3.token
:构建ActivityRecord
时生成的token
。
4.application
:Application
第一次的时候创建一遍。
5.intent
:将要启动的ActivityRecord中的intent。
6.info
:ActivityInfo
类型,将要启动的ActivityRecord中的ActivityInfo
。Instrumentation::callActivityOnCreate()
:
参数(部分):
1.activity
:ActivityThread::performLaunchActivity()
中创建的Activity
。Activity::performCreate()
Activity::onCreate()
本文链接:https://blog.wangjiegulu.com/2015/12/03/Android-从Launcher开始启动App流程源码分析/
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。