日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DisplayContent、StackBox、TaskStack笔记

發布時間:2025/3/13 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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.mAnimationBackgroundSurface

DimLayer對象,用來實現陰影效果的Surface包裝類對象,彈出不論什么dialog,理應將dialog之下的窗體上面加一個陰影,也就是將dialog設置一個WindowManager.LayoutParams.FLAG_DIM_BEHIND屬性mAnimationBackgroundSurface跟背景動畫相關。

TaskStack(WindowManagerService service, int stackId, DisplayContent displayContent) {mService = service;mStackId = stackId;mDisplayContent = displayContent;mDimLayer = new DimLayer(service, this);mAnimationBackgroundSurface = new DimLayer(service, this);}

④TaskStack.mDimWinAnimator

保存著陰影效果Surface的窗體動畫,在startDimmingIfNeeded()函數中更新WindowStateAnimator。

void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {// Only set dim params on the highest dimmed layer.final WindowStateAnimator existingDimWinAnimator = mDimWinAnimator;// Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.if (newWinAnimator.mSurfaceShown && (existingDimWinAnimator == null|| !existingDimWinAnimator.mSurfaceShown|| existingDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {mDimWinAnimator = newWinAnimator;}} mDimWinAnimator中保存的動畫與其它窗體的動畫是同一個對象,并不獨立擁有WindowStateAnimator

⑤TaskStack.mAnimationBackgroundSurface

⑥TaskStack.mAnimationBackgroundAnimator

上面兩個跟背景動畫相關?

9、mTaskHistory

保存著全部TaskStack中的Task合集。

10、mExitingTokens、mExitingAppTokens

mExitingTokens:* Window tokens that are in the process of exiting, but still?on screen for animations.*

mExitingAppTokens:?* Application tokens that are in the process of exiting, but still?on screen for animations.*

相應延遲remove的WindowToken、AppWindowToken分別保存在mExitingTokens和mExitingAppTokens中。在下一次調用performLayoutAndPlaceSurfacesLockedInner()時便從這兩個list中移除滿足一定條件的Token。

11、mWindows

保存著屬于該DisplayContent的按Z軸高度排列的全部WindowState。

12、createStack()

函數用來創建一個TaskStack。

TaskStack createStack(int stackId, int relativeStackBoxId, int position, float weight) {TaskStack newStack = null;if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackBoxId="+ relativeStackBoxId + " position=" + position + " weight=" + weight);if (stackId == HOME_STACK_ID) {if (mStackBoxes.size() != 1) {throw new IllegalArgumentException("createStack: HOME_STACK_ID (0) not first.");}newStack = mHomeStack;} else {int stackBoxNdx;for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {final StackBox box = mStackBoxes.get(stackBoxNdx);if (position == StackBox.TASK_STACK_GOES_OVER|| position == StackBox.TASK_STACK_GOES_UNDER) {// Position indicates a new box is added at top level only.if (box.contains(relativeStackBoxId)) {StackBox newBox = new StackBox(mService, this, null);newStack = new TaskStack(mService, stackId, this);newStack.mStackBox = newBox;newBox.mStack = newStack;final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +(stackBoxNdx + offset));mStackBoxes.add(stackBoxNdx + offset, newBox);break;}} else {// Remaining position values indicate a box must be split.newStack = box.split(stackId, relativeStackBoxId, position, weight);if (newStack != null) {break;}}}if (stackBoxNdx < 0) {throw new IllegalArgumentException("createStack: stackBoxId " + relativeStackBoxId+ " not found.");}}if (newStack != null) {layoutNeeded = true;}EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position,(int)(weight * 100 + 0.5));return newStack;}

position大體上分為兩大類型,導致有兩種創建TaskStack方式:①直接new一棵僅僅有根節點的StackBox樹,再new一個TaskStack;②從StackBox.mStackBoxId==relativeStackBoxId的葉節點上分裂出兩個StackBox,再new一個TaskStack保存在兩個中的一個StackBox中。眼下看來android4.4的第二個TaskStack是通過第一種方式創建的。

ActivityStackSupervisor.startActivityUncheckedLocked()-->ActivityStackSupervisor.adjustStackFocus()-->ActivityManagerService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);研究下這串代碼調用會發現AMS那邊相應會new ActivityStack,也就是說AMS中的一個ActivityStack相應WMS中的一個TaskStack,且是一一相應關系。這樣的相應關系體如今TaskStack.mStackId==ActivityStack.mStackId。

13、moveHomeStackBox()

從名字就能夠看出是干嘛的,移動Home相應的StackBox函數。mStackBoxes中有序的保存著StackBox二叉樹根節點,因此肯定會有調換順序函數,這個函數就是。從moveHomeStackBox()函數中還能夠知道眼下僅僅支持兩顆StackBox樹。

boolean moveHomeStackBox(boolean toTop) {if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" +Debug.getCallers(4));EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0);switch (mStackBoxes.size()) {case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");case 1: return false; // Only the home StackBox exists.case 2:if (homeOnTop() ^ toTop) {mStackBoxes.add(mStackBoxes.remove(0));return true;}return false;default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");}}

14、setTouchExcludeRegion()

這個函數主要作用是設置目標TaskStack的觸摸區域mTouchExcludeRegion值,為多窗體設計的。

WMS.performLayoutAndPlaceSurfacesLockedInner()-->WMS.setFocusedStackFrame()-->setTouchExcludeRegion()

16、switchUserStacks()

這個函數在多用戶切換時調用。

void switchUserStacks(int oldUserId, int newUserId) {final WindowList windows = getWindowList();for (int i = 0; i < windows.size(); i++) {final WindowState win = windows.get(i);if (win.isHiddenFromUserLocked()) {if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "+ win + ", attrs=" + win.mAttrs.type + ", belonging to "+ win.mOwnerUid);win.hideLw(false);}}for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {mStackBoxes.get(stackBoxNdx).switchUserStacks(newUserId);}} 函數調用isHiddenFromUserLocked()推斷窗體是否可以在新用戶中顯示,返回true就調用WindowState.hideLw()隱藏窗體。
同一時候會調用StackBox.switchUserStacks()-->TaskStack.switchUser(),可是這個switchUser()邏輯有問題吧??

void switchUser(int userId) {int top = mTasks.size();for (int taskNdx = 0; taskNdx < top; ++taskNdx) {Task task = mTasks.get(taskNdx);if (task.mUserId == userId) {mTasks.remove(taskNdx);mTasks.add(task);--top;}}}

完。

轉載于:https://www.cnblogs.com/mengfanrong/p/4022780.html

總結

以上是生活随笔為你收集整理的DisplayContent、StackBox、TaskStack笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。