ActivityStackSupervisor分析

来源:互联网 发布:linux安装包命令 编辑:程序博客网 时间:2024/05/22 13:15

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

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掉即可。
㈢、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)稍微不好理解一点,来分析下:

<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 activityActivityStack.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>    }


1 0
原创粉丝点击