文章仅记录自己的一点分析过程,供日后参考。
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<ActivityRecord> 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)稍微不好理解一点,来分析下:
<span style="font-size:18px;"> 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<ResultInfo> 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); <span style="font-size: 18.1818180084229px; font-family: Arial, Helvetica, sans-serif;">//②如果Activity所在的进程未启动,那么先启动进程,在进程起来后会调用attachApplicationLocked(),函数中会接着调用realStartActivityLocked()函数继续启动这个Activity;</span> }