前言
其实在之前就研究过Activity的启动流程,查看过很多资料,说实话这不是一时半会就能弄明白了解透彻的,这里面牵扯到的东西和知识也是非常多,那么我呢将对其做一个比较详细的总结和分析,至于一些细节以后有机会再单独分析,我相信只要阅读此文你将会对Activity的启动模式有一个大概的了解,如果您想要深入了解还得自己多结合源码分析翻阅相关资料,此篇文章基于Android 8.0源码进行分析,有不对的地方还请多指教。
1. Activity是什么?
一个界面
2.如何启动一个Activity?
调用startActivity()
3.Activity启动流程源码分析
好了让我们直接步入正题吧
>>> 步骤1
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
>>> 步骤2
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
//此时options为null将调用else
startActivityForResult(intent, -1);
}
}
>>> 步骤3
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
//如果是第一次启动mParent肯定为null
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
//委托mInstrumentation调用execStartActivity
//activity的生命周期方法都是它来调用
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
//为什么要判断requestCode对于0呢?
//因为不大于0的话onActivityResult不起作用
//所以在调用startActivityForResult设置requestCode必须等于等于0才起作用!
if (requestCode >= 0) {
mStartedActivity = true;
}
} else {
...
}
}
这里简单的介绍一下
Instrumentation
因为是第一次在分析过程中出现所以我简单的先介绍一下
- 调用activity的生命周期相关方法,一个Activity对象的生命周期开始于被一个Intent启动的时候
- 这时候该Activity对象的onCreate()方法就会被调用,紧跟着就是onResume()
- Android的API框架并没有为你的代码提供一种方法去直接调用这些回调函数,但是通过instrumentation就可以做到这一点。
下面我们来看一下委托Instrumentation调用的 execStartActivity()
方法
/**
* @param who The Context from which the activity is being started.
* @param contextThread The main thread of the Context from which the activity
* is being started.
* @param token Internal token identifying to the system who is starting
* the activity; may be null.
* @param target Which element is performing the start (and thus receiving
* any result).
* @param intent The actual Intent to start.
* @param requestCode Identifier for this request's result; less than zero
* if the caller is not expecting a result.
*
* @return To force the return of a particular result, return an
* ActivityResult object containing the desired data; otherwise
* return null. The default implementation always returns null.
*/
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
>>> 重点关注这个方法
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
//checkStartActivityResult作用
// 比如如果启动的activity没有在xml里面进行注册那么在这个check里就会报错
checkStartActivityResult(result, intent);
}
return null;
}
ActivityManager.getService()
实际上返回的结果就是ActivityManagerService
简称AMS,详细细节可查阅相关资料,在一开始的启动流程中主要的还是一些参数传递过程,到了后面就比较复杂了,下面就是AMS的startActivity函数
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
>>> 步骤1
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
>>> 步骤2
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
>>> 步骤3
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
在上面的步骤3中调用了startActivityMayWait()
函数这个函数在ActivityStarter
类里,我们重点分析,如下:
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask, String reason) {
//检测intent的合法性
//...
//方法分析1:
//a.此方法实际上的调用PackageManagerService的resolveIntent
//b.根据intent的信息查找匹配的activity
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...
// 方法分析2:
// a.收集Intent所指向的Activity信息,
// b.当存在多个可供选择的Activity,则直接向用户弹出选择框供用户选择
// c.设置Intent的Component
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
ActivityOptions options = ActivityOptions.fromBundle(bOptions);
ActivityStackSupervisor.ActivityContainer container =
(ActivityStackSupervisor.ActivityContainer)iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null &&
container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
// 设置uuid
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}
...
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Check to see if we already
// have another, different heavy-weight process running.
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final ProcessRecord heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
|| !heavy.processName.equals(aInfo.processName))) {
//这里面比较长我就不贴出来了说一下内容
//a.如果当前系统中已经存在重量级进程,但不是将要启动的这个
//b.实例化这个重量级的Intent,并且赋值给当前的Intent,关于重量级下面我会讲到
}
}
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
// 重点关注1
>>> 启动activity并将启动结果返回。
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask, reason);
// 如果configuration发生变化,则调用AMS的updateConfigurationLocked进行处理
if (stack.mConfigWillChange) {
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"在启动活动后更新到新的配置。");
mService.updateConfigurationLocked(globalConfig, null, false);
}
// 分析:
// a. outResult是作为参数传递进来
// b. 在上个方法中可以发现传递过来的为null,所以这个if语句将不会被执行
if (outResult != null) {
//关注如果不为null的情况
outResult.result = res;
//res是调用startActivityLocked返回的结果
//在startActivityLocked之后给启动结果赋值
if (res == ActivityManager.START_SUCCESS) {
mSupervisor.mWaitingActivityLaunched.add(outResult);
//将成功的结果保存
do {
try {
mService.wait();
//AMS执行线程等待
} catch (InterruptedException e) {
}
} while (outResult.result != START_TASK_TO_FRONT
&& !outResult.timeout && outResult.who == null);
//while循环里面的判断条件要看activity被唤醒的方式了
if (outResult.result == START_TASK_TO_FRONT) {
// START_TASK_TO_FRONT解释为 : 一个activity被带到前台,但是还没有完全启动
res = START_TASK_TO_FRONT;
}
}
if (res == START_TASK_TO_FRONT) {
// 当这个activity被带到前台的时候
final ActivityRecord r = outRecord[0];
if (r.nowVisible && r.state == RESUMED) {
//如果ActivityRecord 是可见的并且是RESUME状态的话
outResult.timeout = false;
outResult.who = r.realActivity;
outResult.totalTime = 0;
outResult.thisTime = 0;
//对outResult进行赋值
} else {
...
}
}
}
// 作用
// a.通知监听者,activity正在启动。
// b.更新状态
mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
return res;
}
}
结合代码以及注释可以得出这样的结论startActivityMayWait这个函数有以下几点
1.让PKMS来解析Intent并得到ResolveInfo
2.匹配最相符的Intent
3.判断是否是启动重量级的任务
ResolveInfo : 这个任务在manifast中的信息,IntentFilter之类的
重量级:所谓重量级在这里的意思就是有多个任务被匹配到
注释里的重点关注就是启动流程调用的方法,下面我们接着看startActivityLocked这个函数
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
// 为变量赋值
>>> 启动activity,并将结果返回。上段代码用到的res就是它返的
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
container, inTask);
return mLastStartActivityResult;
}
在这个方法里面传递了一些参数给startActivity这个函数IApplicationThread caller
,Intent
,callingPid
调用者的进程pid,realCallingPid
当前进程pid,startFlags=0
等。startActivity这个函数也是比较重要的那我们来看一下
startActivity
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
//err 表示错误的启动结果,在下面会对其赋值默认是启动成功
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
= options != null ? options.popAppVerificationBundle() : null;
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
// 检测caller是否有权限启动目标Activity
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = ActivityManager.START_PERMISSION_DENIED;
//调用者没有权限
}
}
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
if (err == ActivityManager.START_SUCCESS) {
Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
+ "} from uid " + callingUid);
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Will send result to " + resultTo + " " + sourceRecord);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
final int launchFlags = intent.getFlags();
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
//对IntentFlags为FLAG_ACTIVITY_FORWARD_RESULT这种特殊情况进行特殊处理
// 1.Activity A 启动了Activity B,Activity B又启动了C,A-->B-->C, 这种情况下
// 2.A启动B要求B返回result给A,但是如果B在启动C时,Intent设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志
// 3.那么此时将会交由C向A setResult。
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
if (resultRecord != null && !resultRecord.isInStackLocked()) {
resultRecord = null;
}
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
sourceRecord.resultTo = null;
if (resultRecord != null) {
resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
}
if (sourceRecord.launchedFromUid == callingUid) {
callingPackage = sourceRecord.launchedFromPackage;
}
}
//...省略了检测参数部分
// (包括检查intent,ActivityInfo),检测结果赋值给了err
if (err != START_SUCCESS) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(
-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
}
ActivityOptions.abort(options);
//如果检查不SUCCESS那么startActivity到此结束直接
return err;
}
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
resultRecord, resultStack, options);
// 检查启动activity它自己的相关权限,其中里面有一个判断(!aInfo.exported)的时候会报错
// 这个exported属性是什么意思呢?
// 1.意思就是说Activity的属性exported的值为false时
// 2.然后别的app就打不开这个Activity了,
// 3.如果要打开的话,就必须和这个Activity在同一Application下或者uid相同才
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort |= !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
}
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
options);
// mInterceptor 属于一个拦截类,将这些信息拦截下来,给自己的变量保存
// 然后再重新赋值给这些信息,其实这个值还是和以前一样没有变
// 但是这样做的好处就是在之后可以拦截器里进行修改
intent = mInterceptor.mIntent;
rInfo = mInterceptor.mRInfo;
aInfo = mInterceptor.mAInfo;
resolvedType = mInterceptor.mResolvedType;
inTask = mInterceptor.mInTask;
callingPid = mInterceptor.mCallingPid;
callingUid = mInterceptor.mCallingUid;
options = mInterceptor.mActivityOptions;
if (abort) {
//1如果要终止
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
//2我们向打电话的人假装它真的开始了,但是他们会得到取消的结果。
ActivityOptions.abort(options);
return START_SUCCESS;
}
...
// If we have an ephemeral app, abort the process of launching the resolved intent.
// Instead, launch the ephemeral installer. Once the installer is finished, it
// starts either the intent we resolved here [on install error] or the ephemeral
// app [on install success].
//如果我们有一个短暂的应用程序,中止启动解决意图的过程。
//相反,启动临时安装程序。安装程序完成之后。
//开始我们在这里解决的意图[安装错误]或短暂的
// app[安装成功]。
if (rInfo != null && rInfo.auxiliaryInfo != null) {
intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
callingPackage, verificationBundle, resolvedType, userId);
resolvedType = null;
callingUid = realCallingUid;
callingPid = realCallingPid;
aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
}
//ActivityRecord,用于存储Activity的各种状态和历史信息。
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
...
>>> 一个正常的启动最终会return这里
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
这个方法我们看完了,总结一下
1.检测callerApp是否有权限启动目标activity否则报错误信息ActivityManager.START_PERMISSION_DENIED
2.判断intent带进来的flag
3.在上述代码里面我把对处理VOICE Session的代码减掉了,可以理解为语音会话
4.调用Supervisor.checkStartAnyActivityPermission 检查这个activity自己的相关权限
5.设置mInterceptor 保存一些变量信息放到拦截器里面,比如这个intent,uid,pid,ResolveInfo,ActivityInfo等
6.创建一个ActivityRecord它可以理解为,任务载里面的一个任务,所有的信息都会放到这个里面,具体是什么信息呢?我再贴一份代码你们就知道了如下:
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, container, options, sourceRecord);
还没完别急!接着往下看,它return了一个重载方法
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
>>> 步骤1
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
...
}
postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);
return result;
}
这个重载方法里面执行了startActivityUnchecked这个函数代码也是巨多,不打紧下面接着分析,在这之前我先说一些笼统的东西这个函数主要做了那些事情,比如判断即将启动的Activity是否需要在task中进行创建和是否创建新的Task启动,如何去复用这个activity的逻辑,然后又把这个Task带到前台并设置对应的Task。OK让我们带着这些线索继续看代码。
//这个方法只在步骤一调用了
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
// 方法分析:
// 作用: a.设置一些初始化状态
// b.校验intent的flag是否是特定的flag
// c.将传过去的参数重新赋值给本类的成员变量
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
// 进过一些条件判断之后设置activity的启动模式
// 以后有时间做详细分析
computeSourceStack();
// 这个方法其实就是针对启动模式为FLAG_ACTIVITY_NEW_TASK的时候判断要不要为其重新NEW一个task
mIntent.setFlags(mLaunchFlags);
ActivityRecord reusedActivity = getReusableIntentActivity();
//决定是否将新的Activity插入到现有的Task中
//返回null表示否,否则新启动的Activity将插入到该Task的Top位置。
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
//preferredLaunchStackId : 要加入的StackID
final int preferredLaunchDisplayId =
(mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
if (reusedActivity != null) {
//1.reusedActivity不为null的时候
//2.将新的Activity插入到现有的Task
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (mStartActivity.getTask() == null) {
mStartActivity.setTask(reusedActivity.getTask());
}
if (reusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTask().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
// as the first operation, in case the activity will be resumed as a result of later
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
// 判断当前activity启动模式是否为SinleTask,
// 并且当前要启动的activity在现有的Task中的话
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
// state.
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
//清空在它在上的任务
// The above code can remove {@code reusedActivity} from the task, leading to the
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
if (reusedActivity.getTask() == null) {
reusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);
}
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
//top就是要启动的activty,deliverNewIntentLocked将会回调它的onNewIntent方法
}
}
//将其他任务栈隐藏如果你需要的话
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
//将这个activity的任务栈移动到前台
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
//最后修改这个任务栈的信息
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
}
}
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
? mStartActivity.resultTo.getStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
null /* data */);
}
ActivityOptions.abort(mOptions);
return START_CLASS_NOT_FOUND;
}
// If the activity being launched is the same as the one currently at the top, then
// we need to check if it should only be launched once.
// 从上面这段注释我们得知当启动的Task和位于顶部的Tas相同的时候,我们检查一下是否应该只启动一次
// 这也是下面这部分代码的核心工作
final ActivityStack topStack = mSupervisor.mFocusedStack;
final ActivityRecord topFocused = topStack.topActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
// 从dontstart的赋值过程不难看出它代表要启动的activity和前台activity是否一致
// 以及是否需要重新创建一个实例
if (dontStart) {
//以下代码就是重新使用这个activity
ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
//将回调onNewIntent
top.deliverNewIntentLocked(
mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
boolean newTask = false;
//newTask:是否创建一个新的任务栈
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
// Should this be considered a new task?
// 上面这个英文的解释就是:是否应该被视为一项新任务?
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack)
// 重新创建一个任务栈
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
if (mDoResume) {
...
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
// 如果目标堆栈以前没有可用的焦点(该堆栈上以前的顶部运行活动是不可见的)
// 那么任何先前的调用都会将堆栈移动到不会更新集中的堆栈。如果现在开始新的活动
// 可以使任务堆栈成为焦点,然后确保我们现在相应地更新聚焦堆栈。对应上面的英文翻译
mTargetStack.moveToFront("startActivityUnchecked");
}
>>> 最终会来到这里
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
//更新最后一个堆载的id
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
}
在这个函数里面进行了很多的校验逻辑,细节很多我总结几个重要的点, 通过computeLaunchingTaskFlags()
这个函数在经过一些判断之后设置了activity的启动模式,再决定是否要加入现有的Task中去,如果不加入就创建一个新的task。还有如果他的启动模式是SingleTask的话,在启动它之前会清空压在它上面的activity,然后把这个Task带到前台,之后就可以启动activity了, 将会调用ActivityStackSupervisor类resumeFocusedStackTopActivityLocked()这个函数
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
>>> 步骤1
//
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...
return false;
}
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
boolean result = false;
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
>>> 步骤2
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
...
return result;
}
在上面的代码中的步骤2会调用ActivityStack类中的resumeTopActivityInnerLocked()函数。还是一样先和大家简单的说明一下这个函数的作用,在启动这个activity之前先暂停正在运行的activity,之后就会进行一个转场动画并且更新一些进程数据,新旧交替但是还是没有真正启动,请看代码(我做了一些删减)
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}
// Find the next top-most activity to resume in this stack that is not finishing and is
// focusable. If it is not focusable, we will fall into the case below to resume the
// top activity in the next focusable task.
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
//拿到这个将要运行的activity信息
final boolean hasRunningActivity = next != null;
final ActivityRecord parent = mActivityContainer.mParentActivity;
final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
if (hasRunningActivity
&& (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
// 看上面的注释就能明白了
return false;
}
mStackSupervisor.cancelInitializingActivities();
// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;
// 将mUserLeaving放置在userLeaving中,并且重置mUserLeaving为false,因此就可以通过userLeaving
// 判断是否需要向源Activity组件发送一个用户离开的时间通知了
if (!hasRunningActivity) {
// There are no activities left in the stack, let's look somewhere else.
return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
//方法作用:将焦点转移到下一个activity
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
// 如果启动的activity是进入重新恢复状态执行onResume的话,直接return false
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
// 重新恢复这个activity会有一个过渡公话
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
final TaskRecord nextTask = next.getTask();
final TaskRecord prevTask = prev != null ? prev.getTask() : null;
if (prevTask != null && prevTask.getStack() == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
// This task is going away but it was supposed to return to the home stack.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else if (!isOnHomeDisplay()) {
return false;
} else if (!isHomeStack()){
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Launching home next");
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
// 启动到Home Task
}
}
// If we are sleeping, and there is no resumed activity, and the top
// activity is paused, well that is the state we want.
if (mService.isSleepingOrShuttingDownLocked()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
// 在回到Home的时候回执行一个过度动画
// 按一下home键就能看到这个动画的效果了trying!
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
if (!mService.mUserController.hasStartedUserState(next.userId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.userId + " is stopped");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// The activity may be waiting for stop, but that is no longer
// appropriate for it.
mStackSupervisor.mStoppingActivities.remove(next);
//在会stop掉了activity里面移除掉将会启动的activity,因为它会被重新运行起来
mStackSupervisor.mGoingToSleepActivities.remove(next);
//和上面的意思一样
next.sleeping = false;
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
boolean lastResumedCanPip = false;
final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
if (lastFocusedStack != null && lastFocusedStack != this) {
// So, why aren't we using prev here??? See the param comment on the method. prev doesn't
// represent the last resumed activity. However, the last focus stack does if it isn't null.
final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
"resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
}
// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
// to be paused, while at the same time resuming the new resume activity only if the
// previous activity can't go into Pip since we want to give Pip activities a chance to
// enter Pip before resuming the next activity.
final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
&& !lastResumedCanPip;
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
// 暂停任务栈中的其他activity
if (mResumedActivity != null) {
// 我们从一个Activity启动另一个Activity的时候,源Activity不是空,mResumedActivity指向源Activity,
// 因此mResumedActivity不为空
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
//暂停当前正在运行的activity
}
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
// 把即将启动的activity放到这个Lru列表的最上面,关于什么是Lru大家可以去查阅相关资料
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
} else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
// It is possible for the activity to be resumed when we paused back stacks above if the
// next activity doesn't have to wait for pause to complete.
// So, nothing else to-do except:
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
// 如果启动的这个任务不需要等其他的任务先暂停,那么当在我们上面的任务已经暂停的时候
// 就可以直接启动了
executeAppTransition(options);
// 运行重新恢复任务的过度动画
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
...
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
next.packageName, false, next.userId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ next.packageName + ": " + e);
}
// We are starting up the next activity, so tell the window manager
// that the previous one will be hidden soon. This way it can know
// to ignore it when computing the desired screen orientation.
// 下面这个if else 会通知WindowManager 告诉它前面那个activity很快就要隐藏了
boolean anim = true;
if (prev != null) {
if (prev.finishing) {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
prev.setVisibility(false);
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind
? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN, false);
}
}
} else {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
}
}
Bundle resumeAnimOptions = null;
if (anim) {
ActivityOptions opts = next.getOptionsForTargetActivityLocked();
if (opts != null) {
resumeAnimOptions = opts.toBundle();
}
next.applyOptionsLocked();
} else {
next.clearOptionsLocked();
}
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
+ " stopped=" + next.stopped + " visible=" + next.visible);
// If the previous activity is translucent, force a visibility update of
// the next activity, so that it's added to WM's opening app list, and
// transition animation can be set up properly.
// For example, pressing Home button with a translucent activity in focus.
// Launcher is already visible in this case. If we don't add it to opening
// apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
// TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
// 如果之前的活动是半透明的,则强制进行可见性更新
// 下一个活动,将它添加到WM的开放应用列表中
// 过渡动画可以正确设置。
// 例如,按下Home键,焦点是半透明的活动。
// 在这种情况下,启动程序已经可见。如果我们不把它加进去。
// 将无法运行一些动画。
final boolean lastActivityTranslucent = lastStack != null
&& (!lastStack.mFullscreen
|| (lastStack.mLastPausedActivity != null
&& !lastStack.mLastPausedActivity.fullscreen));
// This activity is now becoming visible.
if (!next.visible || next.stopped || lastActivityTranslucent) {
next.setVisibility(true);
// 将这个活动变为可见
}
...
//省略了一部分更新任务载的代码
...
if (notUpdated) {
// The configuration update wasn't able to keep the existing
// instance of the activity, and instead started a new one.
// We should be all done, but let's just make sure our activity
// is still at the top and schedule another run if something
// weird happened.
ActivityRecord nextNext = topRunningActivityLocked();
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
"Activity config changed during resume: " + next
+ ", new next: " + nextNext);
if (nextNext != next) {
// Do over!
mStackSupervisor.scheduleResumeTopActivities();
}
if (!next.visible || next.stopped) {
next.setVisibility(true);
}
next.completeResumeLocked();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
try {
// Deliver all pending results.
ArrayList a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
"Delivering results to " + next + ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
// 这一步将调用onActivityResult
}
}
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
....
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
// scheduleResumeActivity会触发activity的onResume
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
} catch (Exception e) {
...
}
...
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
>>> 如果新启动一个activity调用这个函数
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
总结一下resumeTopActivityInnerLocked函数,在这里面调用topRunningActivityLocked()
把要启动的activity信息取出来,在启动之前先暂停其他activity,并把当前这个activity在要暂停的任务列表里面移除,之后又判断这个要启动Activity是否已经存在,是否为home应用,接着又判断是否要执行它的onNewIntent方法和onResume,以及之前是半透明的状态现在恢复可见,这些情况都在这个方法里面体现到。如果是创建一个新的就会调用 ASS.startSpecificActivityLocked 方法创建 Activity 并启动。接下来我们继续分析startSpecificActivityLocked方法
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
// 判断这个活动是否已经准备好了,前面代码就是做准备的,所以会进入到这里面
try {
...
>>> 启动流程会到这一步,在下面分析
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
...
}
// 如果抛出异常或者进程为空, 需要AMS重新fork一个进程来起来
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
如你所见startSpecificActivityLocked()
方法里面就一个主要功能调用了realStartActivityLocked()
函数,并在抛出异常和判断这个进程为空的时候执行startProcessLocked()
重新fork一个进程出来,让我们直接来看主要功能。代码如下
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
if (!allPausedActivitiesComplete()) {
// 当有活动暂停的时候,我们会跳过开始任何新的活动,直到停止为止。
// 注意:对于以暂停状态开始的活动,我们也这样做,因为它们将首先被恢复,然后在客户端暂停。
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"realStartActivityLocked: Skipping start of r=" + r
+ " some activities pausing...");
return false;
}
r.startFreezingScreenLocked(app, 0);
if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) {
r.setVisibility(true);
}
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
//让窗口管理器根据新的活动顺序重新评估屏幕的方向。注意,由于这个原因,
//方向调用activity manager。我们不关心这个,因为activity目前没有运行,所以我们只是重新启动它。
if (checkConfig) {
//这个checkConfig是作为参数传递进来的,传递进来的是true所以会执行if里面的代码
final int displayId = r.getDisplayId();
final Configuration config = mWindowManager.updateOrientationFromAppTokens(
getDisplayOverrideConfiguration(displayId),
r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
// Deferring resume here because we're going to launch new activity shortly.
// We don't want to perform a redundant launch of the same record while ensuring
// configurations and trying to resume top activity of focused stack.
mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
displayId);
//作用:更新这个activity的覆盖配置。如果没有提供配置,将根据当前显示信息在WM中计算新的配置。
}
if (mKeyguardController.isKeyguardLocked()) {
r.notifyUnknownVisibilityLaunched();
//启动的时候显示软键盘
}
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.appInfo.uid
+ " info.ai.uid=" + applicationInfoUid
+ " old=" + r.app + " new=" + app);
}
r.app = app;
//设置这个任务的进程
app.waitingToKill = null;
r.launchCount++;
// 增加启动次数
r.lastLaunchTime = SystemClock.uptimeMillis();
// 设置启动时间
if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);
//更新AMS最近启动的进程列表
mService.updateOomAdjLocked();
final TaskRecord task = r.getTask();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
// 固定屏幕不允许其他activity启动
}
...
// 一波赋值操作
r.sleeping = false;
r.forceNewConfig = false;
mService.showUnsupportedZoomDialogIfNeededLocked(r);
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
ProfilerInfo profilerInfo = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
// 条件是成立的 在之前这个函数resolveActivity 对它进行过赋值
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
final String profileFile = mService.mProfileFile;
if (profileFile != null) {
ParcelFileDescriptor profileFd = mService.mProfileFd;
if (profileFd != null) {
try {
profileFd = profileFd.dup();
} catch (IOException e) {
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException o) {
}
profileFd = null;
}
}
}
// 重点就是在这里new一个 ProfilerInfo出来,传递给ActivityTherad类的
// scheduleLaunchActivity函数
profilerInfo = new ProfilerInfo(profileFile, profileFd,
mService.mSamplingInterval, mService.mAutoStopProfiler,
mService.mStreamingOutput);
}
}
}
app.hasShownUi = true;
app.pendingUiClean = true;
app.forceProcessStateUpTo(mService.mTopProcessState);
// Because we could be starting an Activity in the system process this may not go across
// a Binder interface which would create a new Configuration. Consequently we have to
// always create a new Configuration here.
//因为我们可能在系统进程中启动一个活动,所以这可能不会通过绑定器接口来创建一个新的配置。
// 因此,我们必须始终在这里创建一个新的配置。
final MergedConfiguration mergedConfiguration = new MergedConfiguration(
mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
r.setLastReportedConfiguration(mergedConfiguration);
>>> 最后启动流程来到了这里
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
} catch (RemoteException e) {
...
}
...
// Update any services we are bound to that might care about whether
// their client may have activities.
if (r.app != null) {
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
// 更新绑定的服务
}
return true;
}
看到这里那么恭喜你Activity的启动流程第一部分分析到这里就结束了,到了realStartActivityLocked()
这个方法activity的启动也就真正的到了路口了,我大概的梳理一下realStartActivityLocked()
这个方法的作用,先是mWindowManager.updateOrientationFromAppTokens()
让窗口管理器根据新的活动顺序重新评估屏幕的方向,紧接着更新这个activity的覆盖配置mService.updateDisplayOverrideConfigurationLocked()
,然后判断是否在启动的时候显示软键盘,然后固定屏幕,这个时候不允许其他的activity启动,最后来到scheduleLaunchActivity()
这个函数,到了这个函数后面就是启动Activity的生命周期,View的绘制,之类的等等。后续接着为大家分析。
5. 总结
以上就是Activity启动流程第一部分的总结已经分析完了,有什么不对的地方还望指出,后续我将会推出第二部分。在这个分析过程中我也学到了了解到了收获了很多,我相信您再仔细阅读过之后也会有所收获。感谢您的阅读,。