DisplayContent、StackBox、TaskStack筆記,盜墓筆記
文章僅記錄自己的一點理解,僅供自己參考。
每個顯示裝置,都有一個Display對象,DisplayManagerService專門管理這些Display。
1、DisplayContent()
<span style="font-size:18px;"> DisplayContent(Display display, WindowManagerService service) { mDisplay = display; mDisplayId = display.getDisplayId(); display.getDisplayInfo(mDisplayInfo); isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; mService = service; StackBox newBox = new StackBox(service, this, null); mStackBoxes.add(newBox); TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this); newStack.mStackBox = newBox; newBox.mStack = newStack; mHomeStack = newStack; }</span>
對應在WMS中,每個Display對象都會給他new一個DisplayContent,儲存跟這個Display相關的視窗等資訊,這點從WMS的建構函式可以看出來。從DisplayContent()建構函式中還可以看出,每一個DisplayContent至少包含一個StackBox和TaskStack
createDisplayContentLocked()-->getDisplayContentLocked()-->WMS.newDisplayContentLocked()-->new DisplayContent();
<span style="font-size:18px;">WindowManagerService(){ ............ Display[] displays = mDisplayManager.getDisplays(); for (Display display : displays) { createDisplayContentLocked(display); } ........}</span>
2、mInitialDisplayWidth、mInitialDisplayHeight、mInitialDisplayDensity
儲存的是啟動顯示畫面寬度、高度、密度
3、mDisplayInfo
由第1條中的DisplayContent()建構函式中可以看出,mDisplayInfo就是從Display中擷取的,儲存著Display的相關資訊。
4、layoutNeeded
當有視窗需要Layout時,layoutNeeded就會被設為true。
5、mStackBoxes
正常來說mStackBoxes中會儲存兩個StackBox,一個StackBox(0)裡面只包含Launcher,另一個StackBox包含所有其他視窗。
①StackBox.mParent
<span style="font-size:18px;"> /** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this * is this entire size of mDisplayContent. */</span>
mParent表示由哪個StackBox分裂而來,但是對於StackBox 0和StackBox 1的mParent都為null。
②StackBox.mBounds
WMS.performLayoutLockedInner()-->DisplayContent.setStackBoxSize()-->StackBox.setStackBoxSizes()-->mBounds.set(bounds);
bounds尺寸來源於mPolicy.getContentRectLw(bounds);
<span style="font-size:18px;"> public void getContentRectLw(Rect r) { r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); }</span>對於720*1280尺寸的手機,(mContentLeft, mContentTop, mContentRight, mContentBottom)=(0,50,720,1280),踢出了狀態列高度,因此mBounds=(0,50,720,1280)
③StackBox.mVertical
這個變數表示mFirst 和mSecond分裂方向是否是垂直分裂還是左右分裂,具體見split()函數。
/** Relative orientation of mFirst and mSecond. */
④StackBox.layoutNeeded
⑤StackBox.
⑥StackBox.mStack
/** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */
6、StackBox.split()
StackBox分裂函數,分裂的兩個StackBox分別儲存在mFirst和mSecond中(二叉樹方式分裂)。
<span style="font-size:18px;"> TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) { if (mStackBoxId != relativeStackBoxId) { if (mStack != null) { return null; } TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight); if (stack != null) { return stack; } return mSecond.split(stackId, relativeStackBoxId, position, weight); } TaskStack stack = new TaskStack(mService, stackId, mDisplayContent); TaskStack firstStack; TaskStack secondStack; if (position == TASK_STACK_GOES_BEFORE) { position = TASK_STACK_TO_LEFT_OF; } else if (position == TASK_STACK_GOES_AFTER) { // TODO: Test Configuration here for LTR/RTL. position = TASK_STACK_TO_RIGHT_OF; } switch (position) { default: case TASK_STACK_TO_LEFT_OF: case TASK_STACK_TO_RIGHT_OF: mVertical = false; if (position == TASK_STACK_TO_LEFT_OF) { mWeight = weight; firstStack = stack; secondStack = mStack; } else { mWeight = 1.0f - weight; firstStack = mStack; secondStack = stack; } break; case TASK_STACK_GOES_ABOVE: case TASK_STACK_GOES_BELOW: mVertical = true; if (position == TASK_STACK_GOES_ABOVE) { mWeight = weight; firstStack = stack; secondStack = mStack; } else { mWeight = 1.0f - weight; firstStack = mStack; secondStack = stack; } break; } mFirst = new StackBox(mService, mDisplayContent, this); firstStack.mStackBox = mFirst; mFirst.mStack = firstStack; mSecond = new StackBox(mService, mDisplayContent, this); secondStack.mStackBox = mSecond; mSecond.mStack = secondStack; mStack = null; return stack; }</span>分裂的結果只有兩種情況:
①分裂節點的StackBox.mStack轉移到新的mFirst.mStack中,mSecond.mStack=new TaskStack(mService, stackId, mDisplayContent);
②分裂節點的StackBox.mStack轉移到新的mSecond.mStack中,mFirst.mStack=new TaskStack(mService, stackId, mDisplayContent);
上面兩種情況共同點是分裂節點StackBox.mStack會置null。
上述代碼還可以歸納出,分裂節點就是二叉樹的分葉節點,只有分葉節點才可以分裂,只有分葉節點mStack變數才不為null。也可以說一個StackBox分葉節點對應一個TaskStack。
從Android4.4源碼來看,目前預設顯示屏DEFAULT_DISPLAY的DisplayContent擁有兩棵StackBox二叉樹,這兩個StackBox二叉樹都還沒有進行分裂過,只包含一個根節點。
8、TaskStack類
StackBox二叉樹樹的一個分葉節點對應有一個TaskStack。
①TaskStack.mStackId,“stackId The id of the new TaskStack to create.”
②TaskStack.mTasks,儲存著這個Task棧(TaskStack)中的所有Task。一個TaskStack中可以包含很多Task任務。
③TaskStack.mDimLayer
④TaskStack.mDimWinAnimator
⑤TaskStack.mAnimationBackgroundSurface
⑥TaskStack.mAnimationBackgroundAnimator