文章仅记录自己的一点分析过程,供日后参考。
1.dismissKeyguard()
先看下这个函数功能:
void dismissKeyguard() {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
if (mDismissKeyguardOnNextActivity) {
mDismissKeyguardOnNextActivity = false;
mWindowManager.dismissKeyguard();
}
}
函数很简单,判断mDismissKeyguardOnNextActivity为true,然后调用mWindowManager.dismissKeyguard()-->PhoneWindowManager.dismissKeyguardLw().
public void dismissKeyguardLw() {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
mHandler.post(new Runnable() {
public void run() {
if (mKeyguardDelegate.isDismissable()) {
// Can we just finish the keyguard straight away?
mKeyguardDelegate.keyguardDone(false, true);
} else {
// ask the keyguard to prompt the user to authenticate if necessary
mKeyguardDelegate.dismiss();
}
}
});
}
}
上面的代码逻辑是如果keyguard当前是显示状态,那么就进行解锁,否则直接返回。解锁时再判断当前keyguard是否设置了密码保护,如果设置了那么走mKeyguardDelegate.dismiss(),如果没设置,那就调用mKeyguardDelegate.keyguardDone(false, true)直接解锁keyguard。
dismissKeyguard()函数就是提供了一个给AMS侧使用的解锁keyguard接口。但是能不能调用真正解锁还得过mDismissKeyguardOnNextActivity变量这一关呀,这个变量在dismissKeyguardOnNextActivity()-->setDismissKeyguard(true)中赋值为true。dismissKeyguardOnNextActivity()是提供给launcher应用使用的。然而在AMS中的很多地方又调用setDismissKeyguard(false),一般情况是在startActivityLocked()一个activity,当出现权限等异常情况时调用。
2.resumeHomeActivity(ActivityRecord prev)
boolean resumeHomeActivity(ActivityRecord prev) {
moveHomeToTop();
if (prev != null) {
prev.task.mOnTopOfHome = false;
}
ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
if (r != null && r.isHomeActivity()) {
mService.setFocusedActivityLocked(r);
return resumeTopActivitiesLocked(mHomeStack, prev, null);
}
return mService.startHomeActivityLocked(mCurrentUser);
}
函数首先调用moveHomeToTop()来将HomeStack移到前台,然后再把launcher所在的Task移到顶端,这样下面调用resumeTopActivitiesLocked()时便能找到正确的ActivityStack和Task来启动。有个小细节需要注意的是:如果prev不为null,表示是从pre直接起launcher的,此时将prev.task.mOnTopOfHome设为FALSE。
3.TaskRecord.mOnTopOfHome
为什么要设为FALSE?要搞清这个问题需要完全理解mOnTopOfHome这个变量的设计思想。源码对mOnTopOfHome的解释如下:
/** Launch the home activity when leaving this task. */
只要是TaskRecord设置了mOnTopOfHome为true,待leaving这个Task时便回到桌面,这个解释是绝对正确的吗?还有什么叫leaving this task?这个得好好研究下。要研究清楚mOnTopOfHome,必然要研究使用mOnTopOfHome的各种场景,从场景中还原出最准确的理解。mOnTopOfHome作为判断条件的地方只有7处,分别在removeTask()、moveTaskToBackLocked()、removeActivityFromHistoryLocked()、adjustFocusedActivityLocked()、resumeTopActivityLocked()、isActivityOverHome()六个函数中。下面来一个个研究这几个函数(还好不多)。
㈠、isActivityOverHome()
/**
* Determine if home should be visible below the passed record.
* @param record activity we are querying for.
* @return true if home is visible below the passed activity, false otherwise.
*/
boolean isActivityOverHome(ActivityRecord record) {
// Start at record and go down, look for either home or a visible fullscreen activity.
final TaskRecord recordTask = record.task;
for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) {
TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList activities = task.mActivities;
final int startNdx =
task == recordTask ? activities.indexOf(record) : activities.size() - 1;
for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.isHomeActivity()) {
return true;
}
if (!r.finishing && r.fullscreen) {
// Passed activity is over a fullscreen activity.
return false;
}
}
if (task.mOnTopOfHome) {
// Got to the bottom of a task on top of home without finding a visible fullscreen
// activity. Home is visible.
return true;
}
}
// Got to the bottom of this stack and still don't know. If this is over the home stack
// then record is over home. May not work if we ever get more than two layers.
return mStackSupervisor.isFrontStack(this);
}
这个函数非常好理解,解释已经说得很清楚了,就是判断launcher是否会显示在参数给出的Activity之下。首先明白Activity是处在一个ActivityTask中的,所以逻辑就变成了判断launcher是否会显示在参数给出的Activity所在的ActivityTask中的所有Activity之下。这个说法还不太精确,准备的说是所处ActivityTask的参数Activity及以下的所有Activity。如果在这些Activity中找到一个全屏的,并且没有被finish的Activity,那么表示launcher就不会显示在参数Activity之下。如果在 这个Task中没有找到符合那两个条件的Activity,那么就看task.mOnTopOfHome是否为true, 如果为true,那么就返回true;如果整个Stack中都还没确认是否显示launcher,那么就依据mStackSupervisor.isFrontStack(this)来判断,其实这是由bug的,做多窗口时这个地方肯定要做修改,注释也说明了多于2个stack就会有问题。
从这个函数中已经隐约知道这个mOnTopOfHome变量的作用了,在Android4.4之前,只有一个Stack,所有的Task都放在mTaskHistoty中,现在有两个(多窗口有多个)ActivityStack,Task的管理变得相对来说复杂一些了,还好Google把其中一个ActivityStack定制为HomeStack,一般情况可认为就代表着launcher。那么问题来了?不是挖掘机哪家强的问题,是如何统一管理HomeStack跟另一个activityStack中的Task,Google借助了mOnTopOfHome这个属性,虽然有两个mTaskHistory,但你可以根据ActivityTask.mOnTopOfHome的值把这两个mTaskHistory合成一个mTaskHistory。反过来说就是Android 4.4 把Android 4.4之前的一个ActivityStack中的所有Task拆分到两个ActivityStack中,拆分规则就是把launcher和后台Activity拆分到一个ActivityStack(HomeStack)中,其他的所有Task放在另一个ActivityStack中,但是所有的Task还是要维持像4.4之前只有一个mTaskHistory那样后进后出的逻辑,比如从launcher启动微信,微信又启动相机,那么在非HomeStack中相机Task在栈顶,launcher最低,然而launcher Task又不在这个非HomeStack中管理,这个时候就需要mOnTopOfHome来标注一下微信所在Task之下就应该是launcher所在的Task。这样就达到了所有Task的统一管理。
所以mOnTopOfHome应该这么理解:mOnTopOfHome=true表示在整个Task栈管理中,当前这个Task紧着的下一个Task就是launcher所在的Task。嗯,这么理解,上面的isActivityOverHome()就变得更加容易理解了。相信后面那5个函数理解起来也非常容易理解了,都不用看了。哈哈,太开心了有没有。
㈡、ActivityStack.removeTask()
boolean removeTask(TaskRecord task) {
final int taskNdx = mTaskHistory.indexOf(task);
final int topTaskNdx = mTaskHistory.size() - 1;
if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
}
mTaskHistory.remove(task);
return mTaskHistory.isEmpty();
}
在整个Task管理中,如果移除的Task的mOnTopOfHome值为true,并且该Task不位于栈顶,那么肯定要把该Task的上一个Task.mOnTopOfHome设为true,不然逻辑就不对了。如果移除的Task位于栈顶或是mOnTopOfHome值不为true,那就直接remove掉即可。 /**
* Worker method for rearranging history stack. Implements the function of moving all
* activities for a specific task (gathering them if disjoint) into a single group at the
* bottom of the stack.
*
* If a watcher is installed, the action is preflighted and the watcher has an opportunity
* to premeptively cancel the move.
*
* @param taskId The taskId to collect and move to the bottom.
* @return Returns true if the move completed, false if not.
*/
final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
Slog.i(TAG, "moveTaskToBack: " + taskId);
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
if (mStackSupervisor.isFrontStack(this) && mService.mController != null) { //①一般mController 为null,所以这个逻辑不执行。
ActivityRecord next = topRunningActivityLocked(null, taskId);
if (next == null) {
next = topRunningActivityLocked(null, 0);
}
if (next != null) {
// ask watcher if this is allowed
boolean moveOK = true;
try {
moveOK = mService.mController.activityResuming(next.packageName);
} catch (RemoteException e) {
mService.mController = null;
Watchdog.getInstance().setActivityController(null);
}
if (!moveOK) {
return false;
}
}
}
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare to back transition: task=" + taskId);
final TaskRecord tr = taskForIdLocked(taskId);
if (tr == null) {
return false;
}
mTaskHistory.remove(tr); //②将指定的Task移到mTaskHistory的最低端。
mTaskHistory.add(0, tr);
// There is an assumption that moving a task to the back moves it behind the home activity.
// We make sure here that some activity in the stack will launch home.
ActivityRecord lastActivity = null;
int numTasks = mTaskHistory.size();
for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { //③Task移到最低端还不够,还需一个Task.mOnTopOfHome设为true;
final TaskRecord task = mTaskHistory.get(taskNdx);
if (task.mOnTopOfHome) {
break;
}
if (taskNdx == 1) {
// Set the last task before tr to go to home.
task.mOnTopOfHome = true;
}
}
if (reason != null &&
(reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
}
} else {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
}
mWindowManager.moveTaskToBottom(taskId); //③将Task所属的窗口移到最底端;
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
if (task == tr && task.mOnTopOfHome || numTasks <= 1) { //④如果移动的Task是当前resume的Task,并且mOnTopOfHome为true,那么当前这个Task移到低端后必然要起launcher,也就是会调用resumeHomeActivity(),mOnTopOfHome 重设为FALSE。
if (task != null) {
task.mOnTopOfHome = false;
}
return mStackSupervisor.resumeHomeActivity(null);
}
mStackSupervisor.resumeTopActivitiesLocked(); //⑤如果无须起launcher,那么就把该下一个Task中顶层Activity进行resume。
return true;
}
先搞清楚一件事:move Task To Back究竟是怎么个back法?Android如何定义一个Task是Back的?
我们知道源码里面还有一个Front Task,很容易知道Back和Front的划分是以Home来划分的,同时Back也有处在mTaskHistory底端的意思,所以moveTaskToBackLocked()函数理解起来就很容易了。唯一有点难理解的是第④点中为什么要把mOnTopOfHome设置为FALSE,这是个问题,但也不难理解,Android统一把move to back的task.mOnTopOfHome设为false,等到要 move to front的时候再判断下是哪个Task 做 move to front操作,如果是Home Task,那么有继续把task.mOnTopOfHome设为true,如果是非Home Task,那么task.mOnTopOfHome设为false,设计思想应该是这样的。来验证下这个猜测是不是对的,看moveTaskToFrontLocked()函数:
final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
// nothing to do!
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
ActivityOptions.abort(options);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
}
return;
}
mStackSupervisor.moveHomeStack(isHomeStack());
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr);
if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
}
mWindowManager.moveTaskToTop(tr.taskId);
mStackSupervisor.resumeTopActivitiesLocked();
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
}
moveTaskToFrontLocked()主要会做三件事:Task移动是否影响HomeStack为back或front;Task是谁主动移动的,这个主要用来决定mOnTopOfHome值,进而影响这个Task的管理;移动Task后,属于该Task的窗口也需要一到front,同时需要resume该Task中的顶端activity。moveHomeStack(isHomeStack())干了第一件事;insertTaskAtTop(tr)干了第二件事;mWindowManager.moveTaskToTop(tr.taskId)和mStackSupervisor.resumeTopActivitiesLocked()干了第三件事。insertTaskAtTop(tr)稍微不好理解一点,来分析下:
private void insertTaskAtTop(TaskRecord task) {
// If this is being moved to the top by another activity or being launched from the home
// activity, set mOnTopOfHome accordingly.
ActivityStack lastStack = mStackSupervisor.getLastStack(); //①找到是谁主动插入这个Task到顶端的,这个需要好好脑补为什么getLastStack()返回的就是谁是主动插入者
final boolean fromHome = lastStack == null ? true : lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) { //②如果是HomeStack主动插入这个Task,那么设为true,如果是非HomeStack,那么设为false。
task.mOnTopOfHome = fromHome;
}
mTaskHistory.remove(task);
// Now put task at top.
int stackNdx = mTaskHistory.size();
if (task.userId != mCurrentUser) {
// Put non-current user tasks below current user tasks.
while (--stackNdx >= 0) {
if (mTaskHistory.get(stackNdx).userId != mCurrentUser) {
break;
}
}
++stackNdx;
}
mTaskHistory.add(stackNdx, task);
}
㈣、removeActivityFromHistoryLocked()
什么时候调用removeActivityFromHistoryLocked()来将一个ActivityRecord从mTaskHistory中移除呢?这回不猜了,直接搜源码吧,在两个地方会进行这个操作,一个是在应用进程挂掉的时候,会调用这个函数将属于该进程的Activity进行移除,另一个地方自然是activity 被destroy的时候啦。现在来研究下activity 被destroy的场景,一个activity被destroy成功后,ActivityStack.activityDestroyedLocked()会被调用,这个函数做一些后续处理工作,其中最重要的工作便是从mTaskHistory中移除该ActivityRecord,如果移除的ActivityRecord所属的Task中只有该Activity一个,那么肯定要把Task也移除掉,为保险起见,移除掉栈顶Task后,还是要调用resumeTopActivitiesLocked()来resume一下,虽然一般正常情况下这个时候调用resumeTopActivitiesLocked()基本没啥用(因为在pause前一个activity后便把next activity进行resume了)。
final void activityDestroyedLocked(IBinder token) {
final long origId = Binder.clearCallingIdentity();
try {
ActivityRecord r = ActivityRecord.forToken(token);
if (r != null) {
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
}
if (isInStackLocked(token) != null) {
if (r.state == ActivityState.DESTROYING) {
cleanUpActivityLocked(r, true, false);
removeActivityFromHistoryLocked(r);
}
}
mStackSupervisor.resumeTopActivitiesLocked();
} finally {
Binder.restoreCallingIdentity(origId);
}
}
下面来重点分析removeActivityFromHistoryLocked()函数。首先记住只有在一个activity被destroy后才从mTaskHistory中移除。
final void removeActivityFromHistoryLocked(ActivityRecord r) {
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishing();
if (DEBUG_ADD_REMOVE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.i(TAG, "Removing activity " + r + " from stack");
}
final TaskRecord task = r.task;
if (task != null && task.removeActivity(r)) { //①如果activity所处的Task只有该activity一个,那么移除掉该activity后这个Task便是空的了,removeActivity(r)便返回true。此时便把Task也移除掉。
if (DEBUG_STACK) Slog.i(TAG,
"removeActivityFromHistoryLocked: last activity removed from " + this);
if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) { //②这个逻辑基本上不会走,因为在一个activity被destroy掉后,isFrontStack(this)和task.mOnTopOfHome不可能同时成立。
mStackSupervisor.moveHomeToTop();
}
mStackSupervisor.removeTask(task); //③把空的Task移除掉
}
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
r.state = ActivityState.DESTROYED;
if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
r.app = null;
mWindowManager.removeAppToken(r.appToken); //④移除掉属于该ActivityRecord的所有窗口。
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
}
这个函数主要做了三件事:(1).设置一ActivityRecord的一些状态;(2).从mTaskHistory中进行移除;(3).移除与该ActivityRecord对应的窗口;第(1)跟第(3)点很好理解,难点在第(2)点如何从mTaskHistory中进行移除。从mTaskHistory中移除一个Activity。
㈤、adjustFocusedActivityLocked()
这个函数在两个地方调用,一个是在stopActivityLocked()中,另一个在finishActivityLocked()中。但是你调试会发现stopActivityLocked()中调用adjustFocusedActivityLocked()时,adjustFocusedActivityLocked()都是不满足if()条件的,也就是直接退出了,只有在finishActivityLocked()中调用adjustFocusedActivityLocked()才会满足if条件,为什么会这样?为什么会这样,我也没搞清。
private void adjustFocusedActivityLocked(ActivityRecord r) {
if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
ActivityRecord next = topRunningActivityLocked(null);
if (next != r) {
final TaskRecord task = r.task;
if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
mStackSupervisor.moveHomeToTop();
}
}
mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
}
}
㈥、resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions)
这个函数特别不好理解,调用的地方特别多,但是调用的规律就是:在所有可能resume下一个activity的地方调用。这个函数就是跟名字一样,resume top activity。resumeTopActivitiesLocked()被调用并不能保证next activity能真正resume,可能next activity已经被resume,此时便直接返回即可;也可能resume next activity时还不满足resume条件,此时便需触发resume条件,等到条件满足了再调用resumeTopActivitiesLocked()便能正真resume next activity。调试发现,主要有一下这三种调用场景:
场景1.按返回键会桌面,应用放后台。
A.moveActivityTaskToBack()
B.completePauseLocked(),能真正resume activity。
场景2.apk进程死了,一般不会resumeactivity,除非正在运行的apk挂掉,会resume home activity。
场景3.启动一个next activity,ActivityStack.startActivityLocked().
A.startActivity().注意此时函数参数pre为null。
B.completePauseLocked(),能真正resume next activity。注意此时参数pre为前一个activity。
从上面三种场景中,可以总结出,resume一个activity时,会先调整好Stack的前台和后台,把Task加入到合适的位置,最后再调用ActivityStackSupervisor.resumeTopActivitiesLocked()来resume 顶层activity,在调用resumeTopActivitiesLocked()进行resume时不是一步到位的,必须先把前一个activity pause掉,然后才能真正resume nex activity。那么研究resumeTopActivitiesLocked()函数时必然首先要认识到所有的Stack、Task已经调整好了,只要找到一个合适的顶层activity,并且符合resume条件,然后把他resume就好了。
秉着这个思路下面来仔细研究resumeTopActivitiesLocked()函数。这个函数特别长,所有的解释都放在//注释后面:
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { //注意参数pre在start new activity时的参数值。第一次调用时pre为null;第二次pause后调用resumeTopActivityLocked()时pre为paused activity,不为null。
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null); //①找到一个处于栈顶Task中的顶端activity,且ActivityRecord.finishing==false的activity。前面已经说了,在调用resumeTopActivitiesLocked()之前已经做好了充分的准备,将要被resume的activity肯定已经处在最顶端了。
// 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;
if (next == null) { //②如果取出的activity为null,那这个ActivityStack肯定是非Home Stack,因为HomeStack不可能取不出activity的,这个时候只能启动Home Stack中的launcher了。
// There are no more activities! Let's just start up the
// Launcher...
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return mStackSupervisor.resumeHomeActivity(prev);
}
next.delayedResume = false;
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) { //③如果栈顶的Activity已经resume了,那么直接返回呀。
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
final TaskRecord nextTask = next.task;
final TaskRecord prevTask = prev != null ? prev.task : null;
if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) { //④这个地方逻辑挺复杂的。pre activity被finish掉了,并且pre activity是该Task中的最后一个Activity,并且该Task是要回到home的。
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) { //④这种情况就是next activity与pre activity属于同一Task,也就是说pre activity被finish掉了,但是又加入了新的成员,这个新的成员也就是这个Task中唯一一个Activity。此时便把next activity的frontOfTask设为true便好了。
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) { //④这种情况便是next activity与pre activity不属于同一个Task,pre activity被finish掉了,且是pre Task中的最后一个activity。既然pre Task的mOnTopOfHome属性为true,那么next Task必然要回到Home,所以需要把next Task的mOnTopOfHome 值置true。
// This task is going away but it was supposed to return to the home task.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).mOnTopOfHome = true;
} else {
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
return mStackSupervisor.resumeHomeActivity(prev);
}
}
// 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.isSleepingOrShuttingDown()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) { //⑤系统正在睡眠,无须resume Activity,此时直接返回FALSE。
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG, "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.mStartedUsers.get(next.userId) == null) { //⑥判断当前要resume的Activity所属的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); //⑥如果要resume一个Activity,那么必然要清掉mStoppingActivities、mGoingToSleepActivities、mWaitingVisibleActivities列表中该Activity
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
next.updateOptionsLocked(options); //⑥此处调用基本是无效的,因为在startActivity最开始就已经调用过该函数进行创建一个ActivityOptions了。
if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything
// until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) { //⑥如果pre Activity还没pause完成,那么也直接返回,因为必须pause掉pre Activity才可以resume next Activity。
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
// We need to start pausing the current activity so the top one
// can be resumed...
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving); //⑦前面说了,在调用resumeTopActivityLocked()已经做好了Stack、Task等准备,但是还没pause 前一个Stack中的resumed Activity,或者没有pause掉本Stack中resumed activity。此时便进行触发pause操作,然后返回,等待pause完成后调用completePauseLocked()-->resumeTopActivityLocked()再次尝试resume,此时便可继续往下执行。
if (mResumedActivity != null) {
pausing = true;
startPausingLocked(userLeaving, false);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
"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) {
// No reason to do full oom adj update here; we'll let that
// happen whenever it needs to later.
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// If the most recent activity was noHistory but was only stopped rather
// than stopped+finished because the device went to sleep, we need to make
// sure to finish it as we're making a new activity topmost.
if (mService.mSleeping && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
" on new resume");
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
null, "no-history", false);
mLastNoHistoryActivity = null;
}
if (prev != null && prev != next) { //⑦在pause pre Activity后,这个逻辑及下面的逻辑都会调用。
if (!prev.waitingVisible && next != null && !next.nowVisible) { //⑦刚pause完pre Activity,next Activity肯定还不可见嘛,这个逻辑自然会走。把pre Activity.waitingVisible=true.这个应该是为过渡动画做准备吧?
prev.waitingVisible = true;
mStackSupervisor.mWaitingVisibleActivities.add(prev);
if (DEBUG_SWITCH) Slog.v(
TAG, "Resuming top, waiting visible to hide: " + prev);
} else {
// The next activity is already visible, so hide the previous
// activity's windows right now so we can show the new one ASAP.
// We only do this if the previous is finishing, which should mean
// it is on top of the one being resumed so hiding it quickly
// is good. Otherwise, we want to do the normal route of allowing
// the resumed activity to be shown so we can decide if the
// previous should actually be hidden depending on whether the
// new one is found to be full-screen or not.
if (prev.finishing) {
mWindowManager.setAppVisibility(prev.appToken, false);
if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
+ prev + ", waitingVisible="
+ (prev != null ? prev.waitingVisible : null)
+ ", nowVisible=" + next.nowVisible);
} else {
if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
+ prev + ", waitingVisible="
+ (prev != null ? prev.waitingVisible : null)
+ ", nowVisible=" + next.nowVisible);
}
}
}
// Launching this app's activity, make sure the app is no longer
// considered stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState( //⑦设置PM中关于该应用的状态值,make sure the app is no longer considered stopped.
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.
boolean anim = true;
if (prev != null) {
if (prev.finishing) { //⑦如果pre Activity已经被finish了,那么直接隐藏pre Activity的窗口好了。如果没有被finish呢?那就先不管,反正next Activity的窗口肯定会覆盖pre Activity的窗口之上。从这个逻辑可以看出一个Activity只有在finish掉时窗口才设为不可见,pause状态窗口是可见的,同时也可以知道Activity切换动画是在resume next Activity时启动的。
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare close transition: prev=" + prev);
if (mNoAnimActivities.contains(prev)) {
anim = false;
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task //比如按back键从一个activity退到前一个activity时,pre.finishing为true,此时设置TRANSIT_ACTIVITY_CLOSE或者TRANSIT_TASK_CLOSE动画; 窗口的动画是在resume的过程中设置的; ?
? AppTransition.TRANSIT_ACTIVITY_CLOSE
: AppTransition.TRANSIT_TASK_CLOSE, false);
}
mWindowManager.setAppWillBeHidden(prev.appToken);
mWindowManager.setAppVisibility(prev.appToken, false);
} else {
if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(prev.task == next.task //从一个activity中拉起另一个activity,设置TRANSIT_ACTIVITY_OPEN和TRANSIT_TASK_OPEN动画;
? AppTransition.TRANSIT_ACTIVITY_OPEN
: AppTransition.TRANSIT_TASK_OPEN, false);
}
}
if (false) {
mWindowManager.setAppWillBeHidden(prev.appToken);
mWindowManager.setAppVisibility(prev.appToken, false);
}
} else {
if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
anim = false;
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
}
}
if (anim) {
next.applyOptionsLocked(); //启动动画
} else {
next.clearOptionsLocked();
}
ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) { //⑧ActivityRecord.app的赋值在realStartActivityLocked()完成;如果resume的Activity还未跟进程关联,那么就为null——说白点就是如果resume一个新的activity那么就为null,因此也会调用realStartActivityLocked();如果resume 一个已经start过的activity(比如按back键回到前一个activity),那么ActivityRecord.app就不为null;此时resume一个已经start过的activity;
if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
// This activity is now becoming visible.
mWindowManager.setAppVisibility(next.appToken, true); //⑧看到了没,next Activity是在resume时设置窗口可见的。
// schedule launch ticks to collect information about slow apps.
next.startLaunchTickingLocked();
ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
next.state = ActivityState.RESUMED; //⑧设置ActivityRecord.state=Resumed
mResumedActivity = next;
next.task.touchActiveTime();
mService.addRecentTaskLocked(next.task); //⑧既然已经resume了,自然要把当前Task加入到RecentTask中去,这个后续重点研究下
mService.updateLruProcessLocked(next.app, true, null); //⑧activity已经resume了,那该activity所属的进程重量值就要改变嘛,这样就不能轻易杀掉用户正在使用的apk吧
updateLRUListLocked(next);
mService.updateOomAdjLocked();
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
boolean notUpdated = true;
if (mStackSupervisor.isFrontStack(this)) { //⑧这个条件必然成立,从Activity所对应的窗口属性中提取出配置信息,比如屏幕转向等信息。为什么要这么做,因为当前要resume一个Activity,那么其他Activity必然需要跟随当前resume的Activity更新屏幕方向等。此时还必须冻结屏幕(FreezeScreen)。调用mService.updateConfigurationLocked()将屏幕方向信息更新到AMS中来。这个地方极有可能出横屏卡死的bug,后面再深入研究下
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
if (config != null) {
next.frozenBeforeDestroy = true;
}
notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
}
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(null);
if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
"Activity config changed during resume: " + next
+ ", new next: " + nextNext);
if (nextNext != next) {
// Do over!
mStackSupervisor.scheduleResumeTopActivities();
}
if (mStackSupervisor.reportResumedActivityLocked(next)) {
mNoAnimActivities.clear();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
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, "Delivering results to " + next
+ ": " + a);
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
next.userId, System.identityHashCode(next),
next.task.taskId, next.shortComponentName);
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward());
mStackSupervisor.checkReadyForSleepLocked();
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
} catch (Exception e) {
// Whoops, need to restart this activity!
if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
+ lastState + ": " + next);
next.state = lastState;
if (lastStack != null) {
lastStack.mResumedActivity = lastResumedActivity;
}
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
mStackSupervisor.isFrontStack(lastStack)) {
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);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
// From this point on, if something goes wrong there is no way
// to recover the activity.
try {
next.visible = true;
completeResumeLocked(next);
} catch (Exception e) {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception", true);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
next.stopped = false;
} else { //⑨resume一个新的activity(还未跟进程关联的Activity),进程可能还没起来。调用startSpecificActivityLocked(),在这个函数中会寻找目标进程,如果目标进程存在,那么就直接调用realStartActivityLocked(),如果目标进程不存在那么就先startProcess;
// 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, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
上面函数中有个重点就是 if (next.app != null && next.app.thread != null),这个不容易搞懂,当start new Activity时,此时这个activity还未跟目标进程关联(目标进程可能已经启动或未启动),activity跟目标进程关联是在realStartActivityLocked()中进行的;当back到前一个activity时,这个条件是满足的;所以这段逻辑的调用跟startSpecificActivityLocked()-->realStartActivityLocked()调用是互斥的!
4.moveTaskToFrontLocked()
final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
// nothing to do!
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
ActivityOptions.abort(options);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
}
return;
}
mStackSupervisor.moveHomeStack(isHomeStack()); //将Task移到顶端时,先将Task所在的ActivityStack设为前台Stack;
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
insertTaskAtTop(tr); //将Task插入到顶端;这个函数值得研究,在插入的时候会重置Task.mOnTopOfHome值。
if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
}
ActivityOptions.abort(options);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); //设置Task移到前台动画;
}
mWindowManager.moveTaskToTop(tr.taskId); //AMS这边准备设置好了Task位置,同时也要把WMS那边的窗口位置调整过来;
mStackSupervisor.resumeTopActivitiesLocked(); //Task跟窗口都放到正确的位置上后,便调用resumeTopActivitiesLocked()来启动顶层的Activity;
EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
}
6.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.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) { //①如果启动的Activity的目标进程已启动,那么直接调用realStartActivityLocked()启动Activity;
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, 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); //②如果Activity所在的进程未启动,那么先启动进程,在进程起来后会调用attachApplicationLocked(),函数中会接着调用realStartActivityLocked()函数继续启动这个Activity;
}