天天看点

startActivity启动过程分析(转)

基于Android 6.0的源码剖析, 分析android Activity启动流程,相关源码:

​<code>​startActivity​</code>​的整体流程与​​startService启动过程分析​​非常相近,但比Service启动更为复杂,多了stack/task以及UI的相关内容以及Activity的生命周期更为丰富。

Activity启动发起后,通过Binder最终交由system进程中的AMS来完成,则启动流程如下图:

startActivity启动过程分析(转)

接下来,从源码来说说每个过程。

[-&gt; Activity.java]

execStartActivity()方法的参数:

​<code>​mAppThread​</code>​: 数据类型为ApplicationThread,通过mMainThread.getApplicationThread()方法获取。

​<code>​mToken​</code>​: 数据类型为IBinder.

[-&gt; Instrumentation.java]

关于 ActivityManagerNative.getDefault()返回的是ActivityManagerProxy对象. 此处startActivity()的共有10个参数, 下面说说每个参数传递AMP.startActivity()每一项的对应值:

caller: 当前应用的ApplicationThread对象mAppThread;

callingPackage: 调用当前ContextImpl.getBasePackageName(),获取当前Activity所在包名;

intent: 这便是启动Activity时,传递过来的参数;

resolvedType: 调用intent.resolveTypeIfNeeded而获取;

resultTo: 来自于当前Activity.mToken

resultWho: 来自于当前Activity.mEmbeddedID

requestCode = -1;

startFlags = 0;

profilerInfo = null;

options = null;

[-&gt; ActivityManagerNative.java :: ActivityManagerProxy]

AMP经过binder IPC,进入ActivityManagerNative(简称AMN)。接下来程序进入了system_servr进程,开始继续执行。

[-&gt; ActivityManagerNative.java]

[-&gt; ActivityManagerService.java]

此处mStackSupervisor的数据类型为​<code>​ActivityStackSupervisor​</code>​

当程序运行到这里时, ASS.startActivityMayWait的各个参数取值如下:

caller = ApplicationThreadProxy, 用于跟调用者进程ApplicationThread进行通信的binder代理类.

callingUid = -1;

callingPackage = ContextImpl.getBasePackageName(),获取调用者Activity所在包名

intent: 这是启动Activity时传递过来的参数;

resolvedType = intent.resolveTypeIfNeeded

voiceSession = null;

voiceInteractor = null;

resultTo = Activity.mToken, 其中Activity是指调用者所在Activity, mToken对象保存自己所处的ActivityRecord信息

resultWho = Activity.mEmbeddedID, 其中Activity是指调用者所在Activity

outResult = null;

config = null;

ignoreTargetSecurity = false;

userId = AMS.handleIncomingUser, 当调用者userId跟当前处于同一个userId,则直接返回该userId;当不相等时则根据调用者userId来决定是否需要将callingUserId转换为mCurrentUserId.

iContainer = null;

inTask = null;

再来看看这个方法的源码:

[-&gt; ActivityStackSupervisor.java]

该过程主要功能:通过resolveActivity来获取ActivityInfo信息, 然后再进入ASS.startActivityLocked().先来看看

ActivityManager类有如下4个flags用于调试:

START_FLAG_DEBUG:用于调试debug app

START_FLAG_OPENGL_TRACES:用于调试OpenGL tracing

START_FLAG_NATIVE_DEBUGGING:用于调试native

START_FLAG_TRACK_ALLOCATION: 用于调试allocation tracking

AppGlobals.getPackageManager()经过函数层层调用,获取的是ApplicationPackageManager对象。经过binder IPC调用,最终会调用PackageManagerService对象。故此时调用方法为PMS.resolveIntent().

[-&gt; PackageManagerService.java]

ASS.resolveActivity()方法的核心功能是找到相应的Activity组件,并保存到intent对象。

其中有两个返回值代表启动Activity失败:

START_INTENT_NOT_RESOLVED: 从Intent中无法找到相应的Component或者ActivityInfo

START_NOT_CURRENT_USER_ACTIVITY:该Activity对当前用户不可见

当mAppSwitchesAllowedTime时间小于当前时长,或者具有STOP_APP_SWITCHES的权限,则允许app发生切换操作.

其中mAppSwitchesAllowedTime, 在​<code>​AMS.stopAppSwitches()​</code>​的过程中会设置为:​<code>​mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME​</code>​. 禁止app切换的timeout时长为5s(APP_SWITCH_DELAY_TIME = 5s).

当发送5秒超时或者执行​<code>​AMS.resumeAppSwitches()​</code>​过程会将mAppSwitchesAllowedTime设置0, 都会开启允许app执行切换的操作.另外,禁止App切换的操作,对于同一个app是不受影响的,有兴趣可以进一步查看​<code>​checkComponentPermission​</code>​过程.

​<code>​mPendingActivityLaunches​</code>​记录着所有将要启动的Activity, 是由于在​<code>​startActivityLocked​</code>​的过程时App切换功能被禁止, 也就是不运行切换Activity, 那么此时便会把相应的Activity加入到​<code>​mPendingActivityLaunches​</code>​队列. 该队列的成员在执行完​<code>​doPendingActivityLaunchesLocked​</code>​便会清空.

启动mPendingActivityLaunches中所有的Activity, 由于doResume = false, 那么这些activtity并不会进入resume状态,而是设置delayedResume = true, 会延迟resume.