[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::startActivityActivity::startActivityForResultInstrumentation::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协议 许可协议。转载请注明出处。