- A+
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)
2019年6月24日 下午1:52 沙发
代码贴太多,注释讲解太少,看不懂