Android app启动流程:Ams对activitystack和task的管理(12)

  • A+
所属分类:AMS

1、最原始堆栈的建立

在前面《关于FocusedStack的研究》中,不小心认识到了AMS最远先建立堆栈的过程,我们来回忆一下:

 void setWindowManager(WindowManagerService wm) {
        synchronized (mService) {
            mWindowManager = wm;
....
            mHomeStack = mFocusedStack = mLastFocusedStack =
                    getStack(HOME_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
....
        }
    }

 

在AMS启动的初期,会调用这个setWindowManager,建立Home堆栈。他的id 是0;整个建立的过程如下代码:

ActivityStack getStack(int stackId, boolean createStaticStackIfNeeded, boolean createOnTop) {
....
        return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
}

ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
        if (activityDisplay == null) {
            return null;
        }

        ActivityContainer activityContainer = new ActivityContainer(stackId);
        mActivityContainers.put(stackId, activityContainer);
        activityContainer.attachToDisplayLocked(activityDisplay, onTop);
        return activityContainer.mStack;
    }

ActivityContainer(int stackId) {
            synchronized (mService) {
                mStackId = stackId;
                mStack = new ActivityStack(this, mRecentTasks);
                mIdString = "ActivtyContainer{" + mStackId + "}";
                
            }
}

 

 

activity启动的时候堆栈和task的建立

Display #0 (activities from top to bottom):
  Stack #1:
  mFullscreen=true
  mBounds=null
    Task id #116
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{8e6ca6e #116 A=com.example.djh.demo2 U=0 StackId=1 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.demo2 cmp=com.example.djh.demo2/.MainActivity (has extras) }
        Hist #0: ActivityRecord{26859f8 u0 com.example.djh.demo2/.MainActivity t116}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.demo2 cmp=com.example.djh.demo2/.MainActivity (has extras) }
          ProcessRecord{8bfcfed 6749:com.example.djh.demo2/u0a116}
    Task id #115
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{7bd1b39 #115 A=com.example.djh.myapplication U=0 StackId=1 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.myapplication cmp=com.example.djh.myapplication/.MainActivity (has extras) }
        Hist #0: ActivityRecord{dd6042b u0 com.example.djh.myapplication/.MainActivity t115}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 pkg=com.example.djh.myapplication cmp=com.example.djh.myapplication/.MainActivity (has extras) }
          ProcessRecord{31572e8 6694:com.example.djh.myapplication/u0a115}



  Stack #0:
  mFullscreen=true
  mBounds=null
    Task id #114
    mFullscreen=true
    mBounds=null
    mMinWidth=-1
    mMinHeight=-1
    mLastNonFullscreenBounds=null
      TaskRecord{6ed3369 #114 A=com.bbk.studyos.launcher U=0 StackId=0 sz=1}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.bbk.studyos.launcher/.activity.Launcher }
        Hist #0: ActivityRecord{a2dd3e u0 com.bbk.studyos.launcher/.activity.Launcher t114}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.bbk.studyos.launcher/.activity.Launcher }
          ProcessRecord{cb4df75 1277:com.bbk.studyos.launcher/u0a70}

 

我们看下上面的层级结构:

display 0  
     --->stack 1
     ------>task 116
     ------>task 115
     --->stack  0
     ------>task 114

 

我们看下下面的过程:

  • 假设我们机器起来了,stack 0 里面只有task114 ---》launcher;
  • 然后点击一个应用建立stack 1 并建立task 115;
  • 然后再次点击一个应用 附加在stack 1 下面建立了 116;

我们通过代码来看下堆栈形成的过程:

通过前面的文章我们知道,activity的启动会到startActivityUnchecked

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    

        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);

        computeLaunchingTaskFlags();

        computeSourceStack();

 

在这个函数最前面对一些信息的整合:

mReusedActivity = getReusableIntentActivity();

        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;

        if (mReusedActivity != null) {
        }

 

通过getReusableIntentActivity 获取是否有可以复用的堆栈信息,这里我们机器刚起来,只有home堆栈,所以是没有的。

if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
              && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
          newTask = true;
          setTaskFromReuseOrCreateNewTask(taskToAffiliate);

      } else if (mSourceRecord != null) {

          final int result = setTaskFromSourceRecord();
          if (result != START_SUCCESS) {
              return result;
          }
      } else if (mInTask != null) {
          if (mSupervisor.isLockTaskModeViolation(mInTask)) {
              mSupervisor.showLockTaskToast();
              return START_RETURN_LOCK_TASK_MODE_VIOLATION;
          }

          final int result = setTaskFromInTask();
          if (result != START_SUCCESS) {
              return result;
          }
      } else {
          setTaskToCurrentTopOrCreateNewTask();
      }

 

上面的判断比较复杂, 最中我们假设会进入第一个分支。

setTaskFromReuseOrCreateNewTask

其实这个函数是我们今天要讲的比较关键的函数:

private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags,
                mOptions);

        if (mReuseTask == null) {
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent,
                    mVoiceSession, mVoiceInteractor, !mLaunchTaskBehind /* toTop */);
            mStartActivity.setTask(task, taskToAffiliate);
            if (mLaunchBounds != null) {
                final int stackId = mTargetStack.mStackId;
                if (StackId.resizeStackWithLaunchBounds(stackId)) {
                    mService.resizeStack(
                            stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
                } else {
                    mStartActivity.task.updateOverrideConfiguration(mLaunchBounds);
                }
            }
            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                    "Starting new activity " +
                            mStartActivity + " in new task " + mStartActivity.task);
        } else {
            mStartActivity.setTask(mReuseTask, taskToAffiliate);
        }
    }

 

先看下computeStackFocus这个函数:

private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds,
            int launchFlags, ActivityOptions aOptions) {

        final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
        final boolean canUseFocusedStack = focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID
                || (focusedStackId == DOCKED_STACK_ID && r.canGoInDockedStack())
                || (focusedStackId == FREEFORM_WORKSPACE_STACK_ID && r.isResizeableOrForced());
        if (canUseFocusedStack && (!newTask
                || mSupervisor.mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
                    "computeStackFocus: Have a focused stack=" + mSupervisor.mFocusedStack);
            return mSupervisor.mFocusedStack;
        }

        final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks;
        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            stack = homeDisplayStacks.get(stackNdx);
            if (!ActivityManager.StackId.isStaticStack(stack.mStackId)) {

                return stack;
            }
        }

        final int stackId = task != null ? task.getLaunchStackId() :
                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
                        FULLSCREEN_WORKSPACE_STACK_ID;
        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
 
        return stack;
    }

 

前面有好多的判断都是不会执行。

why

这边好多变量,自己去研究。

最终会到最后面两句话:

final int stackId = task != null ? task.getLaunchStackId() :
                bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
                        FULLSCREEN_WORKSPACE_STACK_ID;
        stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);

 

这个task 我们说我们刚建立所以task是空的,buonds也是空的,所以拿的是**FULLSCREEN_WORKSPACE_STACK_ID ** 是1。

ActivityStack getStack(int stackId, boolean createStaticStackIfNeeded, boolean createOnTop) {
        ActivityContainer activityContainer = mActivityContainers.get(stackId);
        if (activityContainer != null) {
            return activityContainer.mStack;
        }
        if (!createStaticStackIfNeeded || !StackId.isStaticStack(stackId)) {
            return null;
        }
        return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
    }
    
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
        if (activityDisplay == null) {
            return null;
        }

        ActivityContainer activityContainer = new ActivityContainer(stackId);
        mActivityContainers.put(stackId, activityContainer);
        activityContainer.attachToDisplayLocked(activityDisplay, onTop);
        return activityContainer.mStack;
    }

 

后面这个函数我们熟悉了,所以会建立一个新的stack 1 在display0下面。

那么如果再次点击一个应用呢?

还是会拿FULLSCREEN_WORKSPACE_STACK_ID 这个id,但是这个时候 activityContainer 这个已经是有了的,不会空的所以会直接返回。

Android app启动流程:调用startProcessLocked的几种情况(1)

Android app启动流程:startProcessLocked函数分析(2)

Android app启动流程:Process.start(3)

Android app启动流程:startservice(4)

Android app启动流程:broadcast广播的注册(5)

Android app启动流程:广播的发送broadcastIntentLocked(6)

Android app启动流程:广播的发送scheduleBroadcastsLocked(7)

Android app启动流程:广播的发送processNextBroadcast(8)

Android app启动流程:关于FocusedStack的研究(9)

Android app启动流程:startActivityMayWait分析(10)

Android app启动流程:startActivityLocked分析(11)

Android app启动流程:Ams对activitystack和task的管理(12)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:1   其中:访客  1   博主  0

    • 匿名 匿名 2

      代码贴太多,注释讲解太少,看不懂