这篇博客我们分析WMS的一些常用变量,我们依然从主线addWindow开始分析,碰到一些常用的变量再进行分析。
DisplayContent
我们再来看如下DisplayContent 类
final DisplayContent displayContent = getDisplayContentLocked(displayId);
我们再来看getDisplayContentLocked函数,当mDisplayContents没有对应displayId对应的DisplayContent,会调用newDisplayContentLocked函数创建一个DisplayContent 然后放入mDisplayContents。
-
public DisplayContent getDisplayContentLocked(final int displayId) {
-
DisplayContent displayContent = mDisplayContents.get(displayId);
-
if (displayContent == null) {
-
final Display display = mDisplayManager.getDisplay(displayId);
-
if (display != null) {
-
displayContent = newDisplayContentLocked(display);
-
}
-
}
-
return displayContent;
-
}
DisplayContent 的mWindows放了该显示设备所有的window。
WindowManager.LayoutParams token
我们看addWindow这个函数的一个参数WindowManager.LayoutParams attrs,这个参数有很多地方修改,最基本的是在Activity应用中调用setContentView的时候会初始化。
现在我们来看其中一个重要的成员变量token。
先看下面代码,当该窗口是一个子窗口时,会调用windowForClientLocked来查找主窗口的WindowState。这个WindowState也就是子窗口的attachedWindow。
-
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
-
attachedWindow = windowForClientLocked(null, attrs.token,
false);
-
if (attachedWindow == null) {
-
Slog.w(TAG,
"Attempted to add window with token that is not a window: "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
-
}
-
if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
-
&& attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
-
Slog.w(TAG,
"Attempted to add window with token that is a sub-window: "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
-
}
-
}
我们来看下windowForClientLocked函数,就是从mWindowMap中获取其attrs.token的WindowState,说明子窗口的attrs.token放的是其父窗口的token。
-
final WindowState windowForClientLocked(Session session, IBinder client,
-
boolean throwOnError) {
-
WindowState win = mWindowMap.get(client);
-
......
-
-
return win;
-
}
那我们先来看看这个token是从何而来,
我们知道WMS的addWindow,是用ActivityThread的handleResumeActivity函数调用如下代码发起的,我们先来看看WindowManagerImpl的addView函数
-
if (r.window == null && !a.mFinished && willBeVisible) {
-
r.window = r.activity.getWindow();
-
View decor = r.window.getDecorView();
-
decor.setVisibility(View.INVISIBLE);
-
ViewManager wm = a.getWindowManager();
-
WindowManager.LayoutParams l = r.window.getAttributes();
-
a.mDecor = decor;
-
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
l.softInputMode |= forwardBit;
-
if (a.mVisibleFromClient) {
-
a.mWindowAdded =
true;
-
wm.addView(decor, l);
-
}
WindowManagerImpl的addView函数,直接调用了WindowMangerGlobal的addView函数
-
@
Override
-
public
void
addView
(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
-
applyDefaultToken(params);
-
mGlobal.addView(view, params, mDisplay, mParentWindow);
-
}
WindowMangerGlobal的addView函数先调用了其parentWindow的adjustLayoutParamsForSubWindow函数,然后就是创建ViewRooImpl对象,再调用其setView函数,就是在这个函数中通过Binder调用了WMS的addWindow函数。
-
public void addView(View view, ViewGroup.LayoutParams params,
-
Display display, Window parentWindow) {
-
if (view == null) {
-
throw
new IllegalArgumentException(
"view must not be null");
-
}
-
if (display == null) {
-
throw
new IllegalArgumentException(
"display must not be null");
-
}
-
if (!(params instanceof WindowManager.LayoutParams)) {
-
throw
new IllegalArgumentException(
"Params must be WindowManager.LayoutParams");
-
}
-
-
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
-
if (parentWindow != null) {
-
parentWindow.adjustLayoutParamsForSubWindow(wparams);
-
}
-
......
-
-
root =
new ViewRootImpl(view.getContext(), display);
-
-
view.setLayoutParams(wparams);
-
-
mViews.add(view);
-
mRoots.add(root);
-
mParams.add(wparams);
-
}
-
-
// do this last because it fires off messages to start doing things
-
try {
-
root.setView(view, wparams, panelParentView);
-
}
-
......
-
}
那我们先要看这个parentWindow是谁,这个parentWindow是在创建WindowManagerImpl 时传进来的。
-
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
-
return
new WindowManagerImpl(mDisplay, parentWindow);
-
}
这个函数是在Activity的attach中调用的,代码如下:
-
mWindow.setWindowManager(
-
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
-
mToken, mComponent.flattenToString(),
-
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) !=
0);
最后我们看传参是this,就是代表Activity中创建的PhoneWindow对象。
-
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
-
boolean hardwareAccelerated) {
-
mAppToken = appToken;
-
mAppName = appName;
-
mHardwareAccelerated = hardwareAccelerated
-
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI,
false);
-
if (wm == null) {
-
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-
}
-
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(
this);
-
}
Window的adjustLayoutParamsForSubWindow函数如下,会把wp的token改成mAppToken。
-
void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
-
CharSequence curTitle = wp.getTitle();
-
if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
-
......
-
}
else
if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW &&
-
.......
-
}
else {
-
if (wp.token == null) {
-
wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
-
}
-
if ((curTitle == null || curTitle.length() ==
0)
-
&& mAppName != null) {
-
wp.setTitle(mAppName);
-
}
-
}
-
if (wp.packageName == null) {
-
wp.packageName = mContext.getPackageName();
-
}
-
if (mHardwareAccelerated) {
-
wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-
}
-
}
而这个mAppToken就是在setWindowManager时赋值的,因此这个token就是Activity的mToken。就是每一个Activity的全局唯一性。
-
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
-
boolean hardwareAccelerated) {
-
mAppToken = appToken;
-
mAppName = appName;
-
mHardwareAccelerated = hardwareAccelerated
-
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI,
false);
-
if (wm == null) {
-
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-
}
-
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(
this);
-
}
mTokenMap
我们再回想之前分析的博客,每个Activity启动的时候会在ActivityStack中调用mWindowManager.addAppToken函数,WMS的addAppToken函数如下,就是放入mTokenMap中,key就是appToken,Value就是APPWindowToken。
-
@
Override
-
public
void
addAppToken
(int addPos, IApplicationToken token, int taskId, int stackId,
-
int requestedOrientation, boolean fullscreen, boolean showForAllUsers,
int userId,
-
int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
-
......
-
-
synchronized(mWindowMap) {
-
AppWindowToken atoken = findAppWindowToken(token.asBinder());
-
if (atoken != null) {
-
Slog.w(TAG,
"Attempted to add existing app token: " + token);
-
return;
-
}
-
atoken =
new AppWindowToken(
this, token, voiceInteraction);
-
......
-
-
mTokenMap.put(token.asBinder(), atoken);
-
-
// Application tokens start out hidden.
-
atoken.hidden =
true;
-
atoken.hiddenRequested =
true;
-
-
}
-
}
继续回到addWindow函数,下面是一些出错处理。首先就是传来的appToken一定要在mTokenMap有对应的WindowToken。
-
WindowToken token = mTokenMap.get(attrs.token);
-
if (token == null) {
-
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
-
Slog.w(TAG,
"Attempted to add application window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
if (type == TYPE_INPUT_METHOD) {
-
Slog.w(TAG,
"Attempted to add input method window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
if (type == TYPE_VOICE_INTERACTION) {
-
Slog.w(TAG,
"Attempted to add voice interaction window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
if (type == TYPE_WALLPAPER) {
-
Slog.w(TAG,
"Attempted to add wallpaper window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
if (type == TYPE_DREAM) {
-
Slog.w(TAG,
"Attempted to add Dream window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
if (type == TYPE_ACCESSIBILITY_OVERLAY) {
-
Slog.w(TAG,
"Attempted to add Accessibility overlay window with unknown token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
token =
new WindowToken(
this, attrs.token,
-1,
false);
-
addToken =
true;
-
}
else
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
-
AppWindowToken atoken = token.appWindowToken;
-
if (atoken == null) {
-
Slog.w(TAG,
"Attempted to add window with non-application token "
-
+ token +
". Aborting.");
-
return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
-
}
else
if (atoken.removed) {
-
Slog.w(TAG,
"Attempted to add window with exiting application token "
-
+ token +
". Aborting.");
-
return WindowManagerGlobal.ADD_APP_EXITING;
-
}
-
if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
-
// No need for this guy!
-
if (localLOGV) Slog.v(
-
TAG,
"**** NO NEED TO START: " + attrs.getTitle());
-
return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
-
}
-
}
else
if (type == TYPE_INPUT_METHOD) {
-
if (token.windowType != TYPE_INPUT_METHOD) {
-
Slog.w(TAG,
"Attempted to add input method window with bad token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
}
else
if (type == TYPE_VOICE_INTERACTION) {
-
if (token.windowType != TYPE_VOICE_INTERACTION) {
-
Slog.w(TAG,
"Attempted to add voice interaction window with bad token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
}
else
if (type == TYPE_WALLPAPER) {
-
if (token.windowType != TYPE_WALLPAPER) {
-
Slog.w(TAG,
"Attempted to add wallpaper window with bad token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
}
else
if (type == TYPE_DREAM) {
-
if (token.windowType != TYPE_DREAM) {
-
Slog.w(TAG,
"Attempted to add Dream window with bad token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
}
else
if (type == TYPE_ACCESSIBILITY_OVERLAY) {
-
if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
-
Slog.w(TAG,
"Attempted to add Accessibility overlay window with bad token "
-
+ attrs.token +
". Aborting.");
-
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
-
}
-
}
else
if (token.appWindowToken != null) {
-
Slog.w(TAG,
"Non-null appWindowToken for system window of type=" + type);
-
// It is not valid to use an app token with other system types; we will
-
// instead make a new token for it (as if null had been passed in for the token).
-
attrs.token = null;
-
token =
new WindowToken(
this, null,
-1,
false);
-
addToken =
true;
-
}
mWindowMap
然后就新建一个WindowState对象,加入到mWindowMap中,注意这里的key是client.asBinder
-
WindowState win =
new WindowState(
this, session, client, token,
-
attachedWindow, appOp[
0], seq, attrs, viewVisibility, displayContent);
-
......
-
win.attach();
-
mWindowMap.put(client.asBinder(), win);
这里的client,是ViewRootImpl的mWindow 对象用来和WMS通信的,一个ViewRootImpl一个mWindow对象。
mWindow = new W(this);
token.windows
再回到addWindow函数,下面是关于新窗口确定插入的位置的相关代码:
-
if (type == TYPE_INPUT_METHOD) {
-
win.mGivenInsetsPending =
true;
-
mInputMethodWindow = win;
-
addInputMethodWindowToListLocked(win);
-
imMayMove =
false;
-
}
else
if (type == TYPE_INPUT_METHOD_DIALOG) {
-
mInputMethodDialogs.add(win);
-
addWindowToListInOrderLocked(win,
true);
-
moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(
true));
-
imMayMove =
false;
-
}
else {
-
addWindowToListInOrderLocked(win,
true);
-
if (type == TYPE_WALLPAPER) {
-
mLastWallpaperTimeoutTime =
0;
-
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-
}
else
if ((attrs.flags&FLAG_SHOW_WALLPAPER) !=
0) {
-
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-
}
else
if (mWallpaperTarget != null
-
&& mWallpaperTarget.mLayer >= win.mBaseLayer) {
-
// If there is currently a wallpaper being shown, and
-
// the base layer of the new window is below the current
-
// layer of the target window, then adjust the wallpaper.
-
// This is to avoid a new window being placed between the
-
// wallpaper and its target.
-
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
-
}
-
}
我们主要看下addWindowToListInOrderLocked函数,这个函数分有附属窗口和没有附属窗口,我们先看下有附属窗口的处理。
-
private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
-
if (DEBUG_FOCUS_LIGHT) Slog.d(TAG,
"addWindowToListInOrderLocked: win=" + win +
-
" Callers=" + Debug.getCallers(
4));
-
if (win.mAttachedWindow == null) {
-
final WindowToken token = win.mToken;
-
int tokenWindowsPos =
0;
-
if (token.appWindowToken != null) {
-
tokenWindowsPos = addAppWindowToListLocked(win);
-
}
else {
-
addFreeWindowToListLocked(win);
-
}
-
if (addToToken) {
-
if (DEBUG_ADD_REMOVE) Slog.v(TAG,
"Adding " + win +
" to " + token);
-
token.windows.add(tokenWindowsPos, win);
-
}
-
}
else {
-
addAttachedWindowToListLocked(win, addToToken);
-
}
-
-
if (win.mAppToken != null && addToToken) {
-
win.mAppToken.allAppWindows.add(win);
-
}
-
}
addAttachedWindowToListLocked函数,先调用getTokenWindowsOnDisplay函数,来得到所有这个WindowToken的WindowState,然后根据这个WindowState插入合适位置。并且把要插入的windowState,也放入token.windows。
-
private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
-
final WindowToken token = win.mToken;
-
final DisplayContent displayContent = win.getDisplayContent();
-
if (displayContent == null) {
-
return;
-
}
-
final WindowState attached = win.mAttachedWindow;
-
-
WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
-
-
// Figure out this window's ordering relative to the window
-
// it is attached to.
-
final
int NA = tokenWindowList.size();
-
final
int sublayer = win.mSubLayer;
-
int largestSublayer = Integer.MIN_VALUE;
-
WindowState windowWithLargestSublayer = null;
-
int i;
-
for (i =
0; i < NA; i++) {
-
WindowState w = tokenWindowList.get(i);
-
final
int wSublayer = w.mSubLayer;
-
if (wSublayer >= largestSublayer) {
-
largestSublayer = wSublayer;
-
windowWithLargestSublayer = w;
-
}
-
if (sublayer <
0) {
-
// For negative sublayers, we go below all windows
-
// in the same sublayer.
-
if (wSublayer >= sublayer) {
-
if (addToToken) {
-
if (DEBUG_ADD_REMOVE) Slog.v(TAG,
"Adding " + win +
" to " + token);
-
token.windows.add(i, win);
//放入WindowToken的windows
-
}
-
placeWindowBefore(wSublayer >=
0 ? attached : w, win);
//插入合适位置
-
break;
-
}
-
}
else {
-
// For positive sublayers, we go above all windows
-
// in the same sublayer.
-
if (wSublayer > sublayer) {
-
if (addToToken) {
-
if (DEBUG_ADD_REMOVE) Slog.v(TAG,
"Adding " + win +
" to " + token);
-
token.windows.add(i, win);
-
}
-
placeWindowBefore(w, win);
-
break;
-
}
-
}
-
}
-
if (i >= NA) {
-
if (addToToken) {
-
if (DEBUG_ADD_REMOVE) Slog.v(TAG,
"Adding " + win +
" to " + token);
-
token.windows.add(win);
-
}
-
if (sublayer <
0) {
-
placeWindowBefore(attached, win);
-
}
else {
-
placeWindowAfter(largestSublayer >=
0
-
? windowWithLargestSublayer
-
: attached,
-
win);
-
}
-
}
-
}
我们先看下getTokenWindowsOnDisplay函数,就是遍历WindowToken的windows,是得同一个DisplayContent对象。
-
WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
-
final WindowList windowList =
new WindowList();
-
final
int count = token.windows.size();
-
for (
int i =
0; i < count; i++) {
-
final WindowState win = token.windows.get(i);
-
if (win.getDisplayContent() == displayContent) {
-
windowList.add(win);
-
}
-
}
-
return windowList;
-
}
DisplayContent的mWindows
再来看placeWindowBefore函数,插入到windows的pos位置
-
private void placeWindowBefore(WindowState pos, WindowState window) {
-
final WindowList windows = pos.getWindowList();
-
int i = windows.indexOf(pos);
-
if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
-
TAG,
"Adding window " + window +
" at "
-
+ i +
" of " + windows.size() +
" (before " + pos +
")");
-
if (i <
0) {
-
Slog.w(TAG,
"placeWindowBefore: Unable to find " + pos +
" in " + windows);
-
i =
0;
-
}
-
windows.add(i, window);
-
mWindowsChanged =
true;
-
}
getWindowList就是返回DisplayContent 得到mWindows,所以在placeWindowBefore插入window,最终也都是插入DisplayContent的mWindows
-
WindowList getWindowList() {
-
final DisplayContent displayContent = getDisplayContent();
-
return displayContent == null ? null : displayContent.getWindowList();
-
}
继续看addWindowToListInOrderLocked函数,对没有附属窗口的调用addAppWindowToListLocked,就是调用WindowState的getWindowList来获取displayContent.getWindowList,然后调用placeWindowBefore插入合适的位置。
-
private int addAppWindowToListLocked(final WindowState win) {
-
final IWindow client = win.mClient;
-
final WindowToken token = win.mToken;
-
final DisplayContent displayContent = win.getDisplayContent();
-
if (displayContent == null) {
-
// It doesn't matter this display is going away.
-
return
0;
-
}
-
-
final WindowList windows = win.getWindowList();
-
final
int N = windows.size();
-
WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
-
int tokenWindowsPos =
0;
-
int windowListPos = tokenWindowList.size();
-
if (!tokenWindowList.isEmpty()) {
-
// If this application has existing windows, we
-
// simply place the new window on top of them... but
-
// keep the starting window on top.
-
if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
-
// Base windows go behind everything else.
-
WindowState lowestWindow = tokenWindowList.get(
0);
-
placeWindowBefore(lowestWindow, win);
-
......
-
}
-
}
-
}
Task TaskStack
我们再来看看WMS的addAppToken函数,这个函数中新建了APPWindowToken之后,会看mTaskIdToTask是否有这个taskId,没有会调用createTaskLocked根据AMS传进来的taskId和stackId创建Task和TaskStack。
- <code class=“language-cpp”> AppWindowToken atoken = findAppWindowToken(token.asBinder());
- if (atoken != null) {
- Slog.w(TAG, ”Attempted to add existing app token: ” + token);
- return;
- }
- atoken = new AppWindowToken(this, token, voiceInteraction);
- ……
- Task task = mTaskIdToTask.get(taskId);
- if (task == null) {
- task = createTaskLocked(taskId, stackId, userId, atoken);
- }
- task.addAppToken(addPos, atoken);
- mTokenMap.put(token.asBinder(), atoken);</code>
-
AppWindowToken atoken = findAppWindowToken(token.asBinder());
-
if (atoken != null) {
-
Slog.w(TAG,
"Attempted to add existing app token: " + token);
-
return;
-
}
-
atoken =
new AppWindowToken(
this, token, voiceInteraction);
-
......
-
-
Task task = mTaskIdToTask.get(taskId);
-
if (task == null) {
-
task = createTaskLocked(taskId, stackId, userId, atoken);
-
}
-
task.addAppToken(addPos, atoken);
-
-
mTokenMap.put(token.asBinder(), atoken);
createTaskLocked函数如下,TaskStack会在ActivityStackSupervisor中调用WMS的attachStack函数创建,这里然后创建Task,再把task放入mTaskIdToTask中。再把task加入到TaskStack中。
-
private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken) {
-
if (DEBUG_STACK) Slog.i(TAG,
"createTaskLocked: taskId=" + taskId +
" stackId=" + stackId
-
+
" atoken=" + atoken);
-
final TaskStack
stack = mStackIdToStack.get(stackId);
-
if (
stack == null) {
-
throw
new IllegalArgumentException(
"addAppToken: invalid stackId=" + stackId);
-
}
-
EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
-
Task task =
new Task(taskId,
stack, userId,
this);
-
mTaskIdToTask.put(taskId, task);
-
stack.addTask(task, !atoken.mLaunchTaskBehind
/* toTop */, atoken.showForAllUsers);
-
return task;
-
}
WMS的attachStack函数如下,当mStackIdToStack没有这个stackId,这个时候新建TaskStack,然后加入到mStackIdToStack。
-
public void attachStack(int stackId, int displayId) {
-
final
long origId = Binder.clearCallingIdentity();
-
try {
-
synchronized (mWindowMap) {
-
final DisplayContent displayContent = mDisplayContents.get(displayId);
-
if (displayContent != null) {
-
TaskStack
stack = mStackIdToStack.get(stackId);
-
if (
stack == null) {
-
if (DEBUG_STACK) Slog.d(TAG,
"attachStack: stackId=" + stackId);
-
stack =
new TaskStack(
this, stackId);
//新建TaskStack
-
mStackIdToStack.put(stackId,
stack);
//加入到mStackIdToStack
-
}
-
stack.attachDisplayContent(displayContent);
-
displayContent.attachStack(
stack);
-
moveStackWindowsLocked(displayContent);
-
final WindowList windows = displayContent.getWindowList();
-
for (
int winNdx = windows.size() -
1; winNdx >=
0; --winNdx) {
-
windows.get(winNdx).reportResized();
-
}
-
}
-
}
AppWindowToken 的mTask
我们再回到WMS的addAppToken函数,创建完task,之后调用了Task的addAppToken函数
-
Task task = mTaskIdToTask.get(taskId);
-
if (task == null) {
-
task = createTaskLocked(taskId, stackId, userId, atoken);
-
}
-
task.addAppToken(addPos, atoken);
Task的addAppToken把AppWindowToken 放入到Task的mAppTokens中,并且赋值AppWindowToken 的mTask
-
void addAppToken(int addPos, AppWindowToken wtoken) {
-
final
int lastPos = mAppTokens.size();
-
if (addPos >= lastPos) {
-
addPos = lastPos;
-
}
else {
-
for (
int pos =
0; pos < lastPos && pos < addPos; ++pos) {
-
if (mAppTokens.get(pos).removed) {
-
// addPos assumes removed tokens are actually gone.
-
++addPos;
-
}
-
}
-
}
-
mAppTokens.add(addPos, wtoken);
-
wtoken.mTask =
this;
-
mDeferRemoval =
false;
-
}