在上篇博客中说到有两种方式启动进程,其中一种就是点击Launcher界面,在点击Launcher最后也会调用Activity的startActivity方法,但是在Launcher中会调用如下代码:
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
这句代码代表启动这个Activity的时候要新建一个Task,主要在AMS中所有的Activity都是保存在Task中。
我们再来看一般的Activity的主Activity其AndroidManifest.xml文件
- <activity android:name=".MainActivity"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
因此,这里的intent包含的信息为:action = "Android.intent.action.Main",category="android.intent.category.LAUNCHER"。
然后我们继续分析,Activity的startActivity函数,最终会到AMS的startActivity函数,这中间的过程就不分析了,在之前的博客中分析过。我们来看AMS的startActivity函数,最终是在ActivityStackSupervisor的startActivityMayWait函数中。
- @Override
- public final int startActivity(IApplicationThread caller, String callingPackage,
- Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options) {
- return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
- resultWho, requestCode, startFlags, profilerInfo, options,
- UserHandle.getCallingUserId());
- }
- @Override
- public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
- Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
- int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
- enforceNotIsolatedCaller("startActivity");
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ALLOW_FULL_ONLY, "startActivity", null);
- // TODO: Switch to user app stacks here.
- return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
- resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
- profilerInfo, null, null, options, false, userId, null, null);
- }
我们来看下ActivityStackSupervisor的startActivityMayWait函数,先是主要调用了resolveActivity函数来解析intent的数据,也就是之前AndroidManifest.xml里的内容。
- ActivityInfo aInfo =
- resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
我们来看下resolveActivity函数主要还是通过PKMS来解析Intent,并且也设置了Intent的Component。
- ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
- ProfilerInfo profilerInfo, int userId) {
- // Collect information about the target of the Intent.
- ActivityInfo aInfo;
- try {
- ResolveInfo rInfo =
- AppGlobals.getPackageManager().resolveIntent(
- intent, resolvedType,
- PackageManager.MATCH_DEFAULT_ONLY
- | ActivityManagerService.STOCK_PM_FLAGS, userId);
- aInfo = rInfo != null ? rInfo.activityInfo : null;
- } catch (RemoteException e) {
- aInfo = null;
- }
- if (aInfo != null) {
- // Store the found target back into the intent, because now that
- // we have it we never want to do this again. For example, if the
- // user navigates back to this point in the history, we should
- // always restart the exact same activity.
- intent.setComponent(new ComponentName(
- aInfo.applicationInfo.packageName, aInfo.name));
- // Don't debug things in the system process
- if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
- if (!aInfo.processName.equals("system")) {
- mService.setDebugApp(aInfo.processName, true, false);
- }
- }
- if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
- if (!aInfo.processName.equals("system")) {
- mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
- }
- }
- if (profilerInfo != null) {
- if (!aInfo.processName.equals("system")) {
- mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
- }
- }
- }
- return aInfo;
- }
后面又调用了ActivityStackSupervisor的startActivityLocked函数,在这个函数中主要创建了ActivityRecord对象
下面我们继续startActivityUncheckedLocked方法,我们先看下面这段代码,由于这个intent的标志值的位Intent.FLAG_ACTIVITY_NEW_TASK被置位,而且Intent.FLAG_ACTIVITY_MULTIPLE_TASK没有置位,因此,下面的if语句会被执行。
- if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
- (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
- || launchSingleInstance || launchSingleTask) {
- // If bring to front is requested, and no result is requested and we have not
- // been given an explicit task to launch in to, and
- // we can find a task that was started with this same
- // component, then instead of launching bring that one to the front.
- if (inTask == null && 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 intentActivity = !launchSingleInstance ?
- findTaskLocked(r) : findActivityLocked(intent, r.info);
- if (intentActivity != null) {
这段代码的逻辑是查看一下,当前有没有Task可以用来执行这个Activity。由于r.launchMode的值不为ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task,这里返回的结果是null,即taskTop为null,因此,需要创建一个新的Task来启动这个Activity。
接着往下看:
- if (r.packageName != null) {
- // 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.
- ActivityStack topStack = mFocusedStack;
- ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
- if (top != null && r.resultTo == null) {
- if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
- if (top.app != null && top.app.thread != null) {
- if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
- || launchSingleTop || launchSingleTask) {
- ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
- top.task);
- // For paranoia, make sure we have correctly
- // resumed the top activity.
- topStack.mLastPausedActivity = null;
- if (doResume) {
- resumeTopActivitiesLocked();
- }
- ActivityOptions.abort(options);
- if ((startFlags&ActivityManager.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 ActivityManager.START_RETURN_INTENT_TO_CALLER;
- }
- top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
- return ActivityManager.START_DELIVERED_TO_TOP;
- }
- }
- }
- }
这段代码的逻辑是看一下,当前在堆栈顶端的Activity是否就是即将要启动的Activity,有些情况下,如果即将要启动的Activity就在堆栈的顶端,那么,就不会重新启动这个Activity的别一个实例了。现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity,因此,这里不用进一步处理上述介绍的情况。
执行到这里,我们知道,要在一个新的Task里面来启动这个Activity了,于是新创建一个Task,并且将这个Task设置为ActivityRecord的task成员变量
- if (r.resultTo == null && inTask == null && !addingToTask
- && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
- newTask = true;//新建一个task
- targetStack = computeStackFocus(r, newTask);
- targetStack.moveToFront("startingNewTask");
- if (reuseTask == null) {
- r.setTask(targetStack.createTaskRecord(getNextTaskId(),
- newTaskInfo != null ? newTaskInfo : r.info,
- newTaskIntent != null ? newTaskIntent : intent,
- voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
- taskToAffiliate);
- if (DEBUG_TASKS) Slog.v(TAG_TASKS,
- "Starting new activity " + r + " in new task " + r.task);
- }
- TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop) {
- TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
- voiceInteractor);
- addTask(task, toTop, false);
- return task;
- }
addTask函数也将这个task放入mTaskHistory一个合适的位置。
- void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
- task.stack = this;
- if (toTop) {
- insertTaskAtTop(task, null);
- } else {
- mTaskHistory.add(0, task);
- updateTaskMovement(task, false);
- }
- if (!moving && task.voiceSession != null) {
- try {
- task.voiceSession.taskStarted(task.intent, task.taskId);
- } catch (RemoteException e) {
- }
- }
- }
下面继续调用了ActivityStack的startActivityLocked函数,在这个函数最后有如下代码,当然这个doResume为true。
- if (doResume) {
- mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
- }
- final ActivityRecord next = topRunningActivityLocked(null);
先获取了下个ActivityRecord,这里也就是我们要启动的Activity。
然后会调用startPausingLocked,把当前的Activity pause。注意这里调用了startPausingLocked之前就return了。
- if (mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG_STATES,
- "resumeTopActivityLocked: Pausing " + mResumedActivity);
- pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
- }
- if (pausing) {
- 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);
- }
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return true;
- }
我们再来看startPausingLocked函数,在startPausingLocked函数中调用了ActivityThread的schedulePauseActivity函数:
- final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
- boolean dontWait) {
- ......
- prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
- userLeaving, prev.configChangeFlags, dontWait);
- ......
在ActivityThread中最后调用handlePauseActivity函数来处理,在handlePauseActivity函数中调用performPauseActivity函数最后会调用Activity的onPause方法,在这个函数最后调用了AMS的activityPaused方法。
- private void handlePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges, boolean dontReport) {
- ActivityClientRecord r = mActivities.get(token);
- if (r != null) {
- Slog.d(TAG, "userLeaving=" + userLeaving + " handling pause of " + r + ",isPreHoney" + r.isPreHoneycomb() +
- "dontReport :"+ dontReport);
- if (userLeaving) {
- performUserLeavingActivity(r);
- }
- r.activity.mConfigChangeFlags |= configChanges;
- performPauseActivity(token, finished, r.isPreHoneycomb());
- EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName() + ",performPauseActivity ok done.");
- Slog.d(TAG, "performPauseActivity after");
- // Make sure any pending writes are now committed.
- if (r.isPreHoneycomb()) {
- QueuedWork.waitToFinish();
- }
- // Tell the activity manager we have paused.
- if (!dontReport) {
- try {
- ActivityManagerNative.getDefault().activityPaused(token);
- } catch (RemoteException ex) {
- Slog.e(TAG,"handlePauseActivity RemoteException: " + ex);
- }
- }
- EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
- r.activity.getComponentName().getClassName() + ",ActivityManager activityPaused ok done.");
- mSomeActivitiesChanged = true;
- }
- }
- ActivityStack lastStack = mStackSupervisor.getLastStack();
- if (next.app != null && next.app.thread != null) {
- ......
- } else {
- EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, "ActivityStack resumeTopActivityInnerLock startSpecificActivityLocked fork process");
- // Whoops, need to restart this activity!
- if (!next.hasBeenLaunched) {
- next.hasBeenLaunched = true;
- } else {
- if (SHOW_APP_STARTING_PREVIEW) {
- mWindowManager.setAppStartingWindow(
- next.appToken, next.packageName, next.theme,
- mService.compatibilityInfoForPackageLocked(
- next.info.applicationInfo),
- next.nonLocalizedLabel,
- next.labelRes, next.icon, next.logo, next.windowFlags,
- null, true);
- }
- if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
- }
- if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
- mStackSupervisor.startSpecificActivityLocked(next, true, true);
- }
- 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.task.stack.setLaunchTime(r);
- if (app != null && app.thread != null) {
- try {
- if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
- || !"android".equals(r.info.packageName)) {
- // Don't add this if it is a platform component that is marked
- // to run in multiple processes, because this is actually
- // part of the framework so doesn't make sense to track as a
- // separate apk in the process.
- app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
- mService.mProcessStats);
- }
- realStartActivityLocked(r, app, andResume, checkConfig);
- return;
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception when starting activity "
- + r.intent.getComponent().flattenToShortString(), e);
- }
- // If a dead object exception was thrown -- fall through to
- // restart the application.
- }
- mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
- "activity", r.intent.getComponent(), false, false, true);
- }