在Activity启动流程(1)中,Activity的启动经过binder通信就会进入ActivityManagerService所在的进程中继续执行startActivity
方法,由于后续的方法涉及的逻辑比较多,在后面的分析中我可能会把某一个函数单独拿出来分析,最后我会做一个启动流程的总结。
ok,接下来看下startActivity
的实现:
ActivityManangerService类startActivity
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
null, null);
}
可以发现,这一步其实什么操作都没有做,只是将调用转发给了mMainStack
,然后执行了startActivityMayWait
方法。如果对参数的值记得不是很清晰的,可以看下Activity的启动流程(1)
接下来就要真的开始真正进入分析正题了。ActivityStack.java
位于的源码路径为frameworks/base/services/java/com/android/server/am/ActivityStack.java
,看下mStack.startActivityMayWait
:
ActivityStack类startActivityMayWait
final int startActivityMayWait(IApplicationThread caller, int callingUid,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug, String profileFile, ParcelFileDescriptor profileFd,
boolean autoStopProfiler, WaitResult outResult, Configuration config) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
/**intent.getComponent != null componentSpecified = true*/
boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
/**获得即将启动的activity的信息*/
ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
profileFile, profileFd, autoStopProfiler);
/**启动activity时对ActivityManagerService作同步*/
synchronized (mService) {
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;
}
//callingPid = callingUid = -1
mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Starting activity when config will change = " + mConfigWillChange);
//mConfigWillChange = false
//清除调用者的pid和uid,准备调用本进程内的函数
final long origId = Binder.clearCallingIdentity();
/**mMainStack在ActivityManangerService创建ActivityStack实例时被赋值为true*/
if (mMainStack && aInfo != null &&
(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
......
}
int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified, null);
......
}
这部分还是比较好理解的,我把和流程无关紧要的代码注释掉了。intent.getComponent() != null,故componentSpecified = true;接下来就是调用resolveActivity
方法获取即将启动的Activity信息aInfo,aInfo的信息主要是从AndroidManifest.xml中获取,resolveActivity
的具体实现,可以参考resolveActivity解析;接下来会设置callingUid和callingPid,从上一步可知,callingUid为-1且caller != null,故最后得到callingPid = callingUid = -1;config = null,故mConfigWillChange = false。接下来就会进入startActivityLocked
函数。
ActivityStack类startActivityLocked
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, boolean onlyIfNeeded,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = START_SUCCESS;
ProcessRecord callerApp = null;
/**根据传入的IApplicationThread构建应用的ProcessRecord*/
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
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 = START_PERMISSION_DENIED;
}
}
if (err == START_SUCCESS) {
Slog.i(TAG, "START {" + intent.toShortString(true, true, true) + "} from pid "
+ (callerApp != null ? callerApp.pid : callingPid));
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
int index = indexOfTokenLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG, "Will send result to " + resultTo + " (index " + index + ")");
if (index >= 0) {
/**requestCode >= 0表示需要启动的Actvity给父Activity返回结果,故sourceRecord和resultRecode相同*/
sourceRecord = mHistory.get(index);
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
/**resultRecord = null*/
int launchFlags = intent.getFlags();
if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
&& sourceRecord != null) {
......
}
//代码块1
/**未找到要启动的Activity组建信息*/
if (err == START_SUCCESS && intent.getComponent() == null) {
// We couldn't find a class that can handle the given Intent.
// That's the end of that!
err = START_INTENT_NOT_RESOLVED;
}
//代码块2
/**根据提供的条件,未解析成功Activty信息*/
if (err == START_SUCCESS && aInfo == null) {
// We couldn't find the specific class specified in the Intent.
// Also the end of the line.
err = START_CLASS_NOT_FOUND;
}
//代码块3
if (err != START_SUCCESS) {
if (resultRecord != null) {
sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
mDismissKeyguardOnNextActivity = false;
return err;
}
//代码块4
/**检查启动Activity进行的权限信息*/
final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,
callingUid, aInfo.applicationInfo.uid, aInfo.exported);
if (perm != PackageManager.PERMISSION_GRANTED) {
......
}
......
ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
......
err = startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
......
return err;
}
这部分代码理解起来不复杂,我在代码中也进行了注视。startActivityLocked
函数的主要作用就是构建ActivityRecord信息,准备为下一步Activity Task的创建和复用做准备。函数一开始根据启动目标Activity的进程(由于我们是在手机桌面启动了应用)构建ProcessRecord,这里的ProcessRecord指向就是Launcher所在的进程;接着使用构建的ProcessRecord callerApp获取callingUid和callingPid,如果记得清楚的话,在此步骤之前,callingUid和callingPid一直为-1,到了这一步才被真正赋值;尝试获取sourceRecord和resultRecord,mHistory
保存所有之前启动过的Activity,由于Launcher已经启动,故sourceRecord表示Launcher,由于requestCode = -1故resultRecord=null;代码块1会判断能否根据intent找到要启动的Activity的组建信息,如果未找到,则err = START_INTENT_NOT_RESOLVED;代码块2会判断能否解析要启动的Activity信息,如果不能解析,则err = START_CLASS_NOT_FOUND;代码块3判断经过前面的判断之后,如果err != START_SUCCESS,则返回错误码。
进过上面的处理后,系统会去判断启动此Activity的进程的权限,如果未能通过验证,则会返回权限异常,权限部分会在后续文章中进行分析。过程中还有其他无关流程的处理我就省略掉了,接下来就会根据之前的信息构造即将要启动的Activity的ActivityRecord,然后去调用startActivityUncheckedLocked
。
ActivityStack类startActivityUncheckedLocked
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, Uri[] grantedUriPermissions,
int grantedMode, boolean onlyIfNeeded, boolean doResume) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
int launchFlags = intent.getFlags();
// We'll invoke onUserLeaving before onPause only if the launching
// activity did not explicitly state that this is an automated launch.
//代码块1
mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
由于要启动的Activity未置位Intent.FLAG_ACTIVITY_NO_USER_ACTION
,故mUserLeaving = true。
if (!doResume) {
......
}
//r.delayResume = true
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
//notTop = null
// If the onlyIfNeeded flag is set, then we can do this if the activity
// being launched is the same as the one making the call... or, as
// a special case, if we do not know the caller then we count the
// current top activity as the caller.
if (onlyIfNeeded) {
......
}
if (sourceRecord == null) {
......
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
// own task.
//代码块1
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
// The activity being started is a single instance... it always
// gets launched into its own task.
//代码块2
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
......
//代码块3
}
boolean addingToTask = false;
TaskRecord reuseTask = null;
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//代码块4
if (r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
// unique task, so we do a special search.
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);
if (taskTop != null) {
......
//代码块5
}
}
从前面的分析可知,doResue = true,notTop = null;onlyIfNeeded = false;sourceRecord != null;代码块1会对sourecRecord的launchMode进行判断,由于sourceRecord代表的是Launcher,Launcher的launchMode为SINGLE_INSTANCE,故在代码块1会对launchFlags添加Intent.FLAG_ACTIVITY_NEW_TASK的标志。代码块2会对即将启动的Activity的launchMode进行判断,由于我们在新建Activity时并没有执行launchMode,launchMode为STAND,故不会进入代码块2执行;由之前的分析可知r.resultTo = null,故代码块3也不会执行;由于在代码块1中LAUNCH_SINGLE_TASK被置位,个程序会进入代码块4中执行;根据之前的分析r.resultTo = null,由于r.launchMode != LAUNCH_SINGLE_INSTANCE,故程序会执行findTaskLocked
函数,并将结果赋值给taskTop,由于即将要启动的Activity的launchMode被设置为LAUNCH_SINGLE_TASK,故在系统中中无法找到可以启动目标Activity的ActivityRecord,故taskTop = null,故代码块5不会被执行
boolean newTask = false;
boolean keepCurTransition = false;
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (reuseTask == null) {
//代码块1
// todo: should do better management of integers.
mService.mCurTask++;
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new task " + r.task);
} else {
r.setTask(reuseTask, reuseTask, true);
}
newTask = true;
.....
} else if (sourceRecord != null) {
//代码块2
......
} else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
//代码块3
......
} else {
//代码块4
......
}
......
startActivityLocked(r, newTask, doResume, keepCurTransition);
根据前面的分析可知,r.resultTo = null ,addingToTask = false且launchFlags的FLAG_ACTIVITY_NEW_TASK被置为,故代码块1会被执行,代码块2,3,4均不会被执行,接下来就好好分析下代码块1。
经过之前的分析可知,需要心的Activity Task来启动目标Activity,mService为ActivityManagerService实例,mCurTask表示当前task的数量,在新建task之前先修改mCurTask的值,使其加1,然后为目标Activity的ActivityRecord设置新的的TaskRecord,并设置newTask = true,接下来就会去执行startActivityLocked
函数了,这个startActivityLocked
函数是之前startActivity
函数的重载形式。
ActivityStack类startActivityLocked
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition) {
final int NH = mHistory.size();
int addPos = -1;
if (!newTask) {
//代码块1
.......
}
if (addPos < 0) {
addPos = NH;
}
if (addPos < NH) {
......
}
mHistory.add(addPos, r);
r.putInHistory();
r.frontOfTask = newTask;
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: starting " + r);
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_NONE, keepCurTransition);
mNoAnimActivities.add(r);
} else if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
mService.mWindowManager.prepareAppTransition(
WindowManagerPolicy.TRANSIT_TASK_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
} else {
mService.mWindowManager.prepareAppTransition(newTask
? WindowManagerPolicy.TRANSIT_TASK_OPEN
: WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
mService.mWindowManager.addAppToken(
addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
// to reset it to make sure we apply affinities to move any
// existing activities from other tasks in to it.
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags()
&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
}
if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
ActivityRecord prev = mResumedActivity;
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
if (prev.task != r.task) prev = null;
// (2) The current activity is already displayed.
else if (prev.nowVisible) prev = null;
}
mService.mWindowManager.setAppStartingWindow(
r, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
r.labelRes, r.icon, r.windowFlags, prev, showStartingIcon);
}
} else {
......
}
if (VALIDATE_TOKENS) {
......
}
if (doResume) {
resumeTopActivityLocked(null);
}
}