Activity启动流程分析:http://blog.csdn.net/luoshengyang/article/details/6689748
startActivityMayWait()函数
//根据Intent获取要启动ActivityInfo
ActivityInfo aInfo =resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
//重量级进程处理
if (aInfo != null &&(aInfo.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0)
startActivityLocked()函数
//从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了
callerApp = mService.getRecordForAppLocked(caller);
//参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中
sourceRecord = isInAnyStackLocked(resultTo);
//检查Activity启动权限
final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid, callingUid);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,callingPid, resolvedType, aInfo.applicationInfo);
//为要启动Activity创建ActivityRecord
ActivityRecord r = new ActivityRecord
//在执行HOME appSwitch的动作时,Pending当前StartActivity动作
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,realCallingPid, realCallingUid, "Activity start")) {
PendingActivityLaunch pal =new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
mPendingActivityLaunches.add(pal);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
startActivityUncheckedLocked()函数
//当intent和activity manifest存在冲突,则manifest优先
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&(launchSingleInstance || launchSingleTask))
//传进来的参数r.resultTo为null,表示Launcher不需要等这个即将要启动的MainActivity的执行结果
Slog.i(TAG, "startActivityUncheckedLocked r.resultTo: "+r.resultTo);
//表示并不是用户“主观意愿”启动的Activity,而是如来电、闹钟事件等触发的Activity启动
mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
//如果调用者指示先不要Resume(DoResume为空),那么我们将delayedResume设置true.
if (!doResume) {r.delayedResume = true;}
//addingToTask 如果为true表示正在添加至某个task, 后续需要将r添加至sourceRecord所在的task
boolean addingToTask = false;
//movedHome表示是否移动home task
boolean movedHome = false;
//reuseTask 如果不为null,则表示已存在task,会重用这个task,但是这个Task里的所有Activity会被清除掉, 需要将r加入这个task
TaskRecord reuseTask = null;
//查找目标Activity是否有存在的Task
ActivityRecord intentActivity = !launchSingleInstance ?findTaskLocked(r) : findActivityLocked(intent, r.info);
//isLockTaskModeViolation判断当时是否为Devices owner app,如果不是就直接return,startActivity就不会启动Activity
if (isLockTaskModeViolation(intentActivity.task,
(launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
//为Activity创建Task
if (r.resultTo == null && inTask == null && !addingToTask&& (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
checkTask = new TaskRecord(mService, getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
voiceSession, voiceInteractor);
startActivityLocked()函数5个参数
//将这个Activity放在stack的最顶层,这样才能与用户交互
task.addActivityToTop(r);
task.setFrontOfTask();
r.putInHistory();
//用于确定两个界面之间的切换使用什么样的动画效果
mWindowManager.prepareAppTransition
//在AMS中会有token记录起来了哪些Activity,就需要在对应的WMS中也做相应的添加以备案,再通过wms添加窗口时会做验证
mWindowManager.addAppToken
//设置一个APP的打开时的窗口,在APP显示第一个主界面时,需要显示一个过渡界面
mWindowManager.setAppStartingWindow
resumeTopActivityInnerLocked()函数
//top running之后的任意处于初始化状态且有显示StartingWindow, 则移除StartingWindow
cancelInitializingActivities();
//取出顶层ActivityRecord,即要启动Activity
final ActivityRecord next = topRunningActivityLocked(null);
//如果next为空,就启动Launcher。换句话说,无论何时Android系统都会有正在运行的Activity,默认就是Launcher
if (next == null) {isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);}
//如果要启动Activity与调用者是同一Activity,则什么都不做。mResumedActivity指是调用者(Launcher)
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&mStackSupervisor.allResumedActivitiesComplete()) {
//处于睡眠或者关机状态,再看看要启动的Activity是否就是当前处于堆栈顶端的Activity,如果是的话,也是什么都不用做
if (mService.isSleepingOrShuttingDown()&& mLastPausedActivity == next&& mStackSupervisor.allPausedActivitiesComplete()) {
//拥有该activity的用户没有启动则直接返回
if (mService.mStartedUsers.get(next.userId) == null)
//如果目标Activity正在stopping,那么就要终止它的这一操作。
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
//如果当前正在pausing一个Activity的话,那直接返回并等待它完成
if (!mStackSupervisor.allPausedActivitiesComplete())
//需要等待暂停当前activity完成,再resume top activity
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
//暂停其他Activity
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
startPausingLocked()函数
//暂停所有子栈的Activity
if (mActivityContainer.mParentActivity == null) {mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);}
//设置状态
mResumedActivity = null;
mPausingActivity = prev;
mLastPausedActivity = prev;
prev.state = ActivityState.PAUSING;
completePauseLocked()函数
prev.stopFreezingScreenLocked(true /*force*/);
mPausingActivity = null;
pause完成后resumeTopActivityInnerLocked()函数调用
/*
*当前在堆栈顶端的Activity为我们即将要启动的Activity,这里通过调用topRunningActivityLocked将它取回来,
*保存在next变量中。之前最后一个Resumed状态的Activity,即Launcher,到了这里已经处于Paused状态了,
*因此,mResumedActivity为null。最后一个处于Paused状态的Activity为Launcher,因此,这里的mLastPausedActivity就为Launcher。
*前面我们为MainActivity创建了ActivityRecord后,它的app域一直保持为null。
*有了这些信息后,上面这段代码就容易理解了,它最终调用startSpecificActivityLocked进行下一步操作。
*/
//把即将要隐藏的Activity添加到mWaitingVisibleActivities中
if (prev != null && prev != next) {
if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev)&& next != null && !next.nowVisible) {
mStackSupervisor.mWaitingVisibleActivities.add(prev);}
startSpecificActivityLocked()函数
//取出Activity的processRecord,应用进程第一次启动app为null
app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
startProcessLocked()函数
//为Activity创建进程
Process.start......
realStartActivityLocked()函数
//调度启动ticks用以收集应用启动慢的信息
r.startLaunchTickingLocked();
//更新Configuration
if (checkConfig) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r.appToken : null);
if (config != null) {
r.frozenBeforeDestroy = true;
}
mService.updateConfigurationLocked(config, r, false, false);
}
updateLruProcessLocked
Android所有应用进程(包括system_server)的ProcessRecord信息都保存在mPidsSelfLocked成员中,除此之外还有一个成员变量mLruProcesses也用于保存ProcessRecord。mLruProcesses的类型虽然是ArrayList,但其内部成员却是按照ProcessRecord的lruWeight大小排序的。在运行过程中,AMS会根据lruWeight的变化调整mLruProcesses成员的位置。updateLruProcessLocked的主要工作是根据app的lruWeight值调整它在数组中的位置。lruWeight越大,其在数组中的位置就越靠后。如果该app和某些Service或ContentProvider有交互关系,那就连同这些Service或ContentProvider所在进程调节lruWeight值。
updateOomAdjLocked
在updateOomAdjLocked函数中,AMS做了比较多事,都是为了最终调用computeOomAdjLocked函数计算某个进程的oom_adj和调度策略来完成对应用进程的管理,这之间4.0增加了一个接口类ComponentCallbacks2,定义了一个函数onTrimMemory,主要通知应用进程进行一定的内存释放。AMS的进程管理核心还是在computeOomAdjLocked里,computeOomAdjLocked就是一个算法,就是根据各种情况来设置几个值,这个调整的算法改进变动的可能性还是比较大的。
//如果当前启动Activity为固定屏幕,则设置它的task为固定屏幕任务
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
}
//将该进程设置为前台进程PROCESS_STATE_TOP
app.forceProcessStateUpTo(mService.mTopProcessState);
handleLaunchActivity()函数
//执行onCreate
Activity a = performLaunchActivity(r, customIntent);
//执行onResume
handleResumeActivity(r.token, false, r.isForward,r.reasonFlags,!r.activity.mFinished && !r.startsNotResumed);