ActivityStackSupervisor分析

文章仅记录自己的一点分析过程,供日后参考。

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掉即可。
㈢、ActivityStack.moveTaskToBackLocked()

  /**
     * 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()

ActivityStackSupervisor分析_第1张图片

B.completePauseLocked(),能真正resume activity

ActivityStackSupervisor分析_第2张图片


场景2.apk进程死了,一般不会resumeactivity,除非正在运行的apk挂掉,会resume home activity

ActivityStackSupervisor分析_第3张图片


场景3.启动一个next activityActivityStack.startActivityLocked().

A.startActivity().注意此时函数参数pre为null。

ActivityStackSupervisor分析_第4张图片

B.completePauseLocked(),能真正resume next activity。注意此时参数pre为前一个activity。

ActivityStackSupervisor分析_第5张图片

从上面三种场景中,可以总结出,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;

    }


你可能感兴趣的:(android系统层)