Android6.0 WMS(四) WMS中常用變量分析

這篇博客我們分析WMS的一些常用變量,我們依然從主線addWindow開始分析,碰到一些常用的變量再進行分析。


DisplayContent

我們再來看如下DisplayContent 類

            final DisplayContent displayContent = getDisplayContentLocked(displayId);

我們再來看getDisplayContentLocked函數,當mDisplayContents沒有對應displayId對應的DisplayContent,會調用newDisplayContentLocked函數創建一個DisplayContent 然後放入mDisplayContents。

  1. public DisplayContent getDisplayContentLocked(final int displayId) {
  2. DisplayContent displayContent = mDisplayContents.get(displayId);
  3. if (displayContent == null) {
  4. final Display display = mDisplayManager.getDisplay(displayId);
  5. if (display != null) {
  6. displayContent = newDisplayContentLocked(display);
  7. }
  8. }
  9. return displayContent;
  10. }
DisplayContent 的mWindows放了該顯示設備所有的window。


WindowManager.LayoutParams  token

我們看addWindow這個函數的一個參數WindowManager.LayoutParams attrs,這個參數有很多地方修改,最基本的是在Activity應用中調用setContentView的時候會初始化。

現在我們來看其中一個重要的成員變量token。

先看下面代碼,當該窗口是一個子窗口時,會調用windowForClientLocked來查找主窗口的WindowState。這個WindowState也就是子窗口的attachedWindow。

  1. if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
  2. attachedWindow = windowForClientLocked(null, attrs.token, false);
  3. if (attachedWindow == null) {
  4. Slog.w(TAG, "Attempted to add window with token that is not a window: "
  5. + attrs.token + ". Aborting.");
  6. return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
  7. }
  8. if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
  9. && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
  10. Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
  11. + attrs.token + ". Aborting.");
  12. return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
  13. }
  14. }

我們來看下windowForClientLocked函數,就是從mWindowMap中獲取其attrs.token的WindowState,說明子窗口的attrs.token放的是其父窗口的token。

  1. final WindowState windowForClientLocked(Session session, IBinder client,
  2. boolean throwOnError) {
  3. WindowState win = mWindowMap.get(client);
  4. ......
  5. return win;
  6. }

那我們先來看看這個token是從何而來,

我們知道WMS的addWindow,是用ActivityThread的handleResumeActivity函數調用如下代碼發起的,我們先來看看WindowManagerImpl的addView函數

  1. if (r.window == null && !a.mFinished && willBeVisible) {
  2. r.window = r.activity.getWindow();
  3. View decor = r.window.getDecorView();
  4. decor.setVisibility(View.INVISIBLE);
  5. ViewManager wm = a.getWindowManager();
  6. WindowManager.LayoutParams l = r.window.getAttributes();
  7. a.mDecor = decor;
  8. l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
  9. l.softInputMode |= forwardBit;
  10. if (a.mVisibleFromClient) {
  11. a.mWindowAdded = true;
  12. wm.addView(decor, l);
  13. }

WindowManagerImpl的addView函數,直接調用了WindowMangerGlobal的addView函數

  1. @Override
  2. public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
  3. applyDefaultToken(params);
  4. mGlobal.addView(view, params, mDisplay, mParentWindow);
  5. }

WindowMangerGlobal的addView函數先調用了其parentWindow的adjustLayoutParamsForSubWindow函數,然後就是創建ViewRooImpl對象,再調用其setView函數,就是在這個函數中通過Binder調用了WMS的addWindow函數。

  1. public void addView(View view, ViewGroup.LayoutParams params,
  2. Display display, Window parentWindow) {
  3. if (view == null) {
  4. throw new IllegalArgumentException("view must not be null");
  5. }
  6. if (display == null) {
  7. throw new IllegalArgumentException("display must not be null");
  8. }
  9. if (!(params instanceof WindowManager.LayoutParams)) {
  10. throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
  11. }
  12. final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
  13. if (parentWindow != null) {
  14. parentWindow.adjustLayoutParamsForSubWindow(wparams);
  15. }
  16. ......
  17. root = new ViewRootImpl(view.getContext(), display);
  18. view.setLayoutParams(wparams);
  19. mViews.add(view);
  20. mRoots.add(root);
  21. mParams.add(wparams);
  22. }
  23. // do this last because it fires off messages to start doing things
  24. try {
  25. root.setView(view, wparams, panelParentView);
  26. }
  27. ......
  28. }

那我們先要看這個parentWindow是誰,這個parentWindow是在創建WindowManagerImpl 時傳進來的。

  1. public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
  2. return new WindowManagerImpl(mDisplay, parentWindow);
  3. }

這個函數是在Activity的attach中調用的,代碼如下:

  1. mWindow.setWindowManager(
  2. (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
  3. mToken, mComponent.flattenToString(),
  4. (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

最後我們看傳參是this,就是代表Activity中創建的PhoneWindow對象。

  1. public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
  2. boolean hardwareAccelerated) {
  3. mAppToken = appToken;
  4. mAppName = appName;
  5. mHardwareAccelerated = hardwareAccelerated
  6. || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
  7. if (wm == null) {
  8. wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  9. }
  10. mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
  11. }

Window的adjustLayoutParamsForSubWindow函數如下,會把wp的token改成mAppToken。

  1. void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) {
  2. CharSequence curTitle = wp.getTitle();
  3. if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
  4. ......
  5. } else if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW &&
  6. .......
  7. } else {
  8. if (wp.token == null) {
  9. wp.token = mContainer == null ? mAppToken : mContainer.mAppToken;
  10. }
  11. if ((curTitle == null || curTitle.length() == 0)
  12. && mAppName != null) {
  13. wp.setTitle(mAppName);
  14. }
  15. }
  16. if (wp.packageName == null) {
  17. wp.packageName = mContext.getPackageName();
  18. }
  19. if (mHardwareAccelerated) {
  20. wp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
  21. }
  22. }

而這個mAppToken就是在setWindowManager時賦值的,因此這個token就是Activity的mToken。就是每一個Activity的全局唯一性。

  1. public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
  2. boolean hardwareAccelerated) {
  3. mAppToken = appToken;
  4. mAppName = appName;
  5. mHardwareAccelerated = hardwareAccelerated
  6. || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
  7. if (wm == null) {
  8. wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  9. }
  10. mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
  11. }


mTokenMap

我們再回想之前分析的博客,每個Activity啓動的時候會在ActivityStack中調用mWindowManager.addAppToken函數,WMS的addAppToken函數如下,就是放入mTokenMap中,key就是appToken,Value就是APPWindowToken。

  1. @Override
  2. public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
  3. int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int userId,
  4. int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
  5. ......
  6. synchronized(mWindowMap) {
  7. AppWindowToken atoken = findAppWindowToken(token.asBinder());
  8. if (atoken != null) {
  9. Slog.w(TAG, "Attempted to add existing app token: " + token);
  10. return;
  11. }
  12. atoken = new AppWindowToken(this, token, voiceInteraction);
  13. ......
  14. mTokenMap.put(token.asBinder(), atoken);
  15. // Application tokens start out hidden.
  16. atoken.hidden = true;
  17. atoken.hiddenRequested = true;
  18. }
  19. }


繼續回到addWindow函數,下面是一些出錯處理。首先就是傳來的appToken一定要在mTokenMap有對應的WindowToken。

  1. WindowToken token = mTokenMap.get(attrs.token);
  2. if (token == null) {
  3. if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
  4. Slog.w(TAG, "Attempted to add application window with unknown token "
  5. + attrs.token + ". Aborting.");
  6. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  7. }
  8. if (type == TYPE_INPUT_METHOD) {
  9. Slog.w(TAG, "Attempted to add input method window with unknown token "
  10. + attrs.token + ". Aborting.");
  11. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  12. }
  13. if (type == TYPE_VOICE_INTERACTION) {
  14. Slog.w(TAG, "Attempted to add voice interaction window with unknown token "
  15. + attrs.token + ". Aborting.");
  16. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  17. }
  18. if (type == TYPE_WALLPAPER) {
  19. Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
  20. + attrs.token + ". Aborting.");
  21. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  22. }
  23. if (type == TYPE_DREAM) {
  24. Slog.w(TAG, "Attempted to add Dream window with unknown token "
  25. + attrs.token + ". Aborting.");
  26. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  27. }
  28. if (type == TYPE_ACCESSIBILITY_OVERLAY) {
  29. Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token "
  30. + attrs.token + ". Aborting.");
  31. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  32. }
  33. token = new WindowToken(this, attrs.token, -1, false);
  34. addToken = true;
  35. } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
  36. AppWindowToken atoken = token.appWindowToken;
  37. if (atoken == null) {
  38. Slog.w(TAG, "Attempted to add window with non-application token "
  39. + token + ". Aborting.");
  40. return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
  41. } else if (atoken.removed) {
  42. Slog.w(TAG, "Attempted to add window with exiting application token "
  43. + token + ". Aborting.");
  44. return WindowManagerGlobal.ADD_APP_EXITING;
  45. }
  46. if (type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
  47. // No need for this guy!
  48. if (localLOGV) Slog.v(
  49. TAG, "**** NO NEED TO START: " + attrs.getTitle());
  50. return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED;
  51. }
  52. } else if (type == TYPE_INPUT_METHOD) {
  53. if (token.windowType != TYPE_INPUT_METHOD) {
  54. Slog.w(TAG, "Attempted to add input method window with bad token "
  55. + attrs.token + ". Aborting.");
  56. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  57. }
  58. } else if (type == TYPE_VOICE_INTERACTION) {
  59. if (token.windowType != TYPE_VOICE_INTERACTION) {
  60. Slog.w(TAG, "Attempted to add voice interaction window with bad token "
  61. + attrs.token + ". Aborting.");
  62. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  63. }
  64. } else if (type == TYPE_WALLPAPER) {
  65. if (token.windowType != TYPE_WALLPAPER) {
  66. Slog.w(TAG, "Attempted to add wallpaper window with bad token "
  67. + attrs.token + ". Aborting.");
  68. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  69. }
  70. } else if (type == TYPE_DREAM) {
  71. if (token.windowType != TYPE_DREAM) {
  72. Slog.w(TAG, "Attempted to add Dream window with bad token "
  73. + attrs.token + ". Aborting.");
  74. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  75. }
  76. } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
  77. if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
  78. Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token "
  79. + attrs.token + ". Aborting.");
  80. return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
  81. }
  82. } else if (token.appWindowToken != null) {
  83. Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
  84. // It is not valid to use an app token with other system types; we will
  85. // instead make a new token for it (as if null had been passed in for the token).
  86. attrs.token = null;
  87. token = new WindowToken(this, null, -1, false);
  88. addToken = true;
  89. }


mWindowMap

然後就新建一個WindowState對象,加入到mWindowMap中,注意這裏的key是client.asBinder

  1. WindowState win = new WindowState(this, session, client, token,
  2. attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
  3. ......
  4. win.attach();
  5. mWindowMap.put(client.asBinder(), win);

這裏的client,是ViewRootImpl的mWindow 對象用來和WMS通信的,一個ViewRootImpl一個mWindow對象。

        mWindow = new W(this);


token.windows

再回到addWindow函數,下面是關於新窗口確定插入的位置的相關代碼:

  1. if (type == TYPE_INPUT_METHOD) {
  2. win.mGivenInsetsPending = true;
  3. mInputMethodWindow = win;
  4. addInputMethodWindowToListLocked(win);
  5. imMayMove = false;
  6. } else if (type == TYPE_INPUT_METHOD_DIALOG) {
  7. mInputMethodDialogs.add(win);
  8. addWindowToListInOrderLocked(win, true);
  9. moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
  10. imMayMove = false;
  11. } else {
  12. addWindowToListInOrderLocked(win, true);
  13. if (type == TYPE_WALLPAPER) {
  14. mLastWallpaperTimeoutTime = 0;
  15. displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
  16. } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
  17. displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
  18. } else if (mWallpaperTarget != null
  19. && mWallpaperTarget.mLayer >= win.mBaseLayer) {
  20. // If there is currently a wallpaper being shown, and
  21. // the base layer of the new window is below the current
  22. // layer of the target window, then adjust the wallpaper.
  23. // This is to avoid a new window being placed between the
  24. // wallpaper and its target.
  25. displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
  26. }
  27. }

我們主要看下addWindowToListInOrderLocked函數,這個函數分有附屬窗口和沒有附屬窗口,我們先看下有附屬窗口的處理。

  1. private void addWindowToListInOrderLocked(final WindowState win, boolean addToToken) {
  2. if (DEBUG_FOCUS_LIGHT) Slog.d(TAG, "addWindowToListInOrderLocked: win=" + win +
  3. " Callers=" + Debug.getCallers(4));
  4. if (win.mAttachedWindow == null) {
  5. final WindowToken token = win.mToken;
  6. int tokenWindowsPos = 0;
  7. if (token.appWindowToken != null) {
  8. tokenWindowsPos = addAppWindowToListLocked(win);
  9. } else {
  10. addFreeWindowToListLocked(win);
  11. }
  12. if (addToToken) {
  13. if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
  14. token.windows.add(tokenWindowsPos, win);
  15. }
  16. } else {
  17. addAttachedWindowToListLocked(win, addToToken);
  18. }
  19. if (win.mAppToken != null && addToToken) {
  20. win.mAppToken.allAppWindows.add(win);
  21. }
  22. }

addAttachedWindowToListLocked函數,先調用getTokenWindowsOnDisplay函數,來得到所有這個WindowToken的WindowState,然後根據這個WindowState插入合適位置。並且把要插入的windowState,也放入token.windows。

  1. private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
  2. final WindowToken token = win.mToken;
  3. final DisplayContent displayContent = win.getDisplayContent();
  4. if (displayContent == null) {
  5. return;
  6. }
  7. final WindowState attached = win.mAttachedWindow;
  8. WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
  9. // Figure out this window's ordering relative to the window
  10. // it is attached to.
  11. final int NA = tokenWindowList.size();
  12. final int sublayer = win.mSubLayer;
  13. int largestSublayer = Integer.MIN_VALUE;
  14. WindowState windowWithLargestSublayer = null;
  15. int i;
  16. for (i = 0; i < NA; i++) {
  17. WindowState w = tokenWindowList.get(i);
  18. final int wSublayer = w.mSubLayer;
  19. if (wSublayer >= largestSublayer) {
  20. largestSublayer = wSublayer;
  21. windowWithLargestSublayer = w;
  22. }
  23. if (sublayer < 0) {
  24. // For negative sublayers, we go below all windows
  25. // in the same sublayer.
  26. if (wSublayer >= sublayer) {
  27. if (addToToken) {
  28. if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
  29. token.windows.add(i, win);//放入WindowToken的windows
  30. }
  31. placeWindowBefore(wSublayer >= 0 ? attached : w, win);//插入合適位置
  32. break;
  33. }
  34. } else {
  35. // For positive sublayers, we go above all windows
  36. // in the same sublayer.
  37. if (wSublayer > sublayer) {
  38. if (addToToken) {
  39. if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
  40. token.windows.add(i, win);
  41. }
  42. placeWindowBefore(w, win);
  43. break;
  44. }
  45. }
  46. }
  47. if (i >= NA) {
  48. if (addToToken) {
  49. if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
  50. token.windows.add(win);
  51. }
  52. if (sublayer < 0) {
  53. placeWindowBefore(attached, win);
  54. } else {
  55. placeWindowAfter(largestSublayer >= 0
  56. ? windowWithLargestSublayer
  57. : attached,
  58. win);
  59. }
  60. }
  61. }

我們先看下getTokenWindowsOnDisplay函數,就是遍歷WindowToken的windows,是得同一個DisplayContent對象。

  1. WindowList getTokenWindowsOnDisplay(WindowToken token, DisplayContent displayContent) {
  2. final WindowList windowList = new WindowList();
  3. final int count = token.windows.size();
  4. for (int i = 0; i < count; i++) {
  5. final WindowState win = token.windows.get(i);
  6. if (win.getDisplayContent() == displayContent) {
  7. windowList.add(win);
  8. }
  9. }
  10. return windowList;
  11. }


DisplayContent的mWindows

再來看placeWindowBefore函數,插入到windows的pos位置

  1. private void placeWindowBefore(WindowState pos, WindowState window) {
  2. final WindowList windows = pos.getWindowList();
  3. int i = windows.indexOf(pos);
  4. if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
  5. TAG, "Adding window " + window + " at "
  6. + i + " of " + windows.size() + " (before " + pos + ")");
  7. if (i < 0) {
  8. Slog.w(TAG, "placeWindowBefore: Unable to find " + pos + " in " + windows);
  9. i = 0;
  10. }
  11. windows.add(i, window);
  12. mWindowsChanged = true;
  13. }

getWindowList就是返回DisplayContent 得到mWindows,所以在placeWindowBefore插入window,最終也都是插入DisplayContent的mWindows

  1. WindowList getWindowList() {
  2. final DisplayContent displayContent = getDisplayContent();
  3. return displayContent == null ? null : displayContent.getWindowList();
  4. }



繼續看addWindowToListInOrderLocked函數,對沒有附屬窗口的調用addAppWindowToListLocked,就是調用WindowState的getWindowList來獲取displayContent.getWindowList,然後調用placeWindowBefore插入合適的位置。

  1. private int addAppWindowToListLocked(final WindowState win) {
  2. final IWindow client = win.mClient;
  3. final WindowToken token = win.mToken;
  4. final DisplayContent displayContent = win.getDisplayContent();
  5. if (displayContent == null) {
  6. // It doesn't matter this display is going away.
  7. return 0;
  8. }
  9. final WindowList windows = win.getWindowList();
  10. final int N = windows.size();
  11. WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
  12. int tokenWindowsPos = 0;
  13. int windowListPos = tokenWindowList.size();
  14. if (!tokenWindowList.isEmpty()) {
  15. // If this application has existing windows, we
  16. // simply place the new window on top of them... but
  17. // keep the starting window on top.
  18. if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
  19. // Base windows go behind everything else.
  20. WindowState lowestWindow = tokenWindowList.get(0);
  21. placeWindowBefore(lowestWindow, win);
  22. ......
  23. }
  24. }
  25. }


Task TaskStack

我們再來看看WMS的addAppToken函數,這個函數中新建了APPWindowToken之後,會看mTaskIdToTask是否有這個taskId,沒有會調用createTaskLocked根據AMS傳進來的taskId和stackId創建Task和TaskStack。

  1. <code class=“language-cpp”>            AppWindowToken atoken = findAppWindowToken(token.asBinder());  
  2.             if (atoken != null) {  
  3.                 Slog.w(TAG, ”Attempted to add existing app token: ” + token);  
  4.                 return;  
  5.             }  
  6.             atoken = new AppWindowToken(this, token, voiceInteraction);  
  7.             ……  
  8.   
  9.             Task task = mTaskIdToTask.get(taskId);  
  10.             if (task == null) {  
  11.                 task = createTaskLocked(taskId, stackId, userId, atoken);  
  12.             }  
  13.             task.addAppToken(addPos, atoken);  
  14.   
  15.             mTokenMap.put(token.asBinder(), atoken);</code>  
  1. AppWindowToken atoken = findAppWindowToken(token.asBinder());
  2. if (atoken != null) {
  3. Slog.w(TAG, "Attempted to add existing app token: " + token);
  4. return;
  5. }
  6. atoken = new AppWindowToken(this, token, voiceInteraction);
  7. ......
  8. Task task = mTaskIdToTask.get(taskId);
  9. if (task == null) {
  10. task = createTaskLocked(taskId, stackId, userId, atoken);
  11. }
  12. task.addAppToken(addPos, atoken);
  13. mTokenMap.put(token.asBinder(), atoken);
createTaskLocked函數如下,TaskStack會在ActivityStackSupervisor中調用WMS的attachStack函數創建,這裏然後創建Task,再把task放入mTaskIdToTask中。再把task加入到TaskStack中。
  1. private Task createTaskLocked(int taskId, int stackId, int userId, AppWindowToken atoken) {
  2. if (DEBUG_STACK) Slog.i(TAG, "createTaskLocked: taskId=" + taskId + " stackId=" + stackId
  3. + " atoken=" + atoken);
  4. final TaskStack stack = mStackIdToStack.get(stackId);
  5. if (stack == null) {
  6. throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId);
  7. }
  8. EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
  9. Task task = new Task(taskId, stack, userId, this);
  10. mTaskIdToTask.put(taskId, task);
  11. stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */, atoken.showForAllUsers);
  12. return task;
  13. }
WMS的attachStack函數如下,當mStackIdToStack沒有這個stackId,這個時候新建TaskStack,然後加入到mStackIdToStack。
  1. public void attachStack(int stackId, int displayId) {
  2. final long origId = Binder.clearCallingIdentity();
  3. try {
  4. synchronized (mWindowMap) {
  5. final DisplayContent displayContent = mDisplayContents.get(displayId);
  6. if (displayContent != null) {
  7. TaskStack stack = mStackIdToStack.get(stackId);
  8. if (stack == null) {
  9. if (DEBUG_STACK) Slog.d(TAG, "attachStack: stackId=" + stackId);
  10. stack = new TaskStack(this, stackId);//新建TaskStack
  11. mStackIdToStack.put(stackId, stack);//加入到mStackIdToStack
  12. }
  13. stack.attachDisplayContent(displayContent);
  14. displayContent.attachStack(stack);
  15. moveStackWindowsLocked(displayContent);
  16. final WindowList windows = displayContent.getWindowList();
  17. for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
  18. windows.get(winNdx).reportResized();
  19. }
  20. }
  21. }


AppWindowToken 的mTask

我們再回到WMS的addAppToken函數,創建完task,之後調用了Task的addAppToken函數

  1. Task task = mTaskIdToTask.get(taskId);
  2. if (task == null) {
  3. task = createTaskLocked(taskId, stackId, userId, atoken);
  4. }
  5. task.addAppToken(addPos, atoken);

Task的addAppToken把AppWindowToken 放入到Task的mAppTokens中,並且賦值AppWindowToken 的mTask

  1. void addAppToken(int addPos, AppWindowToken wtoken) {
  2. final int lastPos = mAppTokens.size();
  3. if (addPos >= lastPos) {
  4. addPos = lastPos;
  5. } else {
  6. for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
  7. if (mAppTokens.get(pos).removed) {
  8. // addPos assumes removed tokens are actually gone.
  9. ++addPos;
  10. }
  11. }
  12. }
  13. mAppTokens.add(addPos, wtoken);
  14. wtoken.mTask = this;
  15. mDeferRemoval = false;
  16. }






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章