Android T 窗口层级其三 —— 层级结构树添加窗口

文章目录

  • 节点添加
    • Task
      • 以DefaultTaskDisplayArea为父节点
      • 以Task为父节点
    • ActivityRecord
    • WindowToken
    • WindowState
      • 以WindowToken为父节点
      • 以ActivityRecord为父节点
    • 小结
      • 调用场景
      • 添加差异
  • 流程分析
    • 添加log
    • 堆栈打印流程
      • Launcher
      • StatusBar

尚未添加窗口的层级结构树,如图
在这里插入图片描述DisplayArea层级结构中的每一个DisplayArea,都包含着一个层级值范围,这个层级值范围表明了这个DisplayArea可以容纳哪些类型的窗口。
每种窗口类型,都可以通过WindowManagerPolicy.getWindowLayerFromTypeLw方法,返回一个相应的层级值。

/*** Returns the layer assignment for the window type. Allows you to control how different* kinds of windows are ordered on-screen.** @param type The type of window being assigned.* @param canAddInternalSystemWindow If the owner window associated with the type we are*        evaluating can add internal system windows. I.e they have*        {@link Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window*        types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}*        can be assigned layers greater than the layer for*        {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their*        layers would be lesser.* @return int An arbitrary integer used to order windows, with lower numbers below higher ones.*/default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow,false /* roundedCornerOverlay */);}/*** Returns the layer assignment for the window type. Allows you to control how different* kinds of windows are ordered on-screen.** @param type The type of window being assigned.* @param canAddInternalSystemWindow If the owner window associated with the type we are*        evaluating can add internal system windows. I.e they have*        {@link Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window*        types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}*        can be assigned layers greater than the layer for*        {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their*        layers would be lesser.* @param roundedCornerOverlay {#code true} to indicate that the owner window is rounded corner*                             overlay.* @return int An arbitrary integer used to order windows, with lower numbers below higher ones.*/default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,boolean roundedCornerOverlay) {// Always put the rounded corner layer to the top most.if (roundedCornerOverlay && canAddInternalSystemWindow) {return getMaxWindowLayer();}if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {return APPLICATION_LAYER;}switch (type) {case TYPE_WALLPAPER:// wallpaper is at the bottom, though the window manager may move it.return  1;case TYPE_PRESENTATION:case TYPE_PRIVATE_PRESENTATION:case TYPE_DOCK_DIVIDER:case TYPE_QS_DIALOG:case TYPE_PHONE:return  3;case TYPE_SEARCH_BAR:return  4;case TYPE_INPUT_CONSUMER:return  5;case TYPE_SYSTEM_DIALOG:return  6;case TYPE_TOAST:// toasts and the plugged-in battery thingreturn  7;case TYPE_PRIORITY_PHONE:// SIM errors and unlock.  Not sure if this really should be in a high layer.return  8;case TYPE_SYSTEM_ALERT:// like the ANR / app crashed dialogs// Type is deprecated for non-system apps. For system apps, this type should be// in a higher layer than TYPE_APPLICATION_OVERLAY.return  canAddInternalSystemWindow ? 12 : 9;case TYPE_APPLICATION_OVERLAY:return  11;case TYPE_INPUT_METHOD:// on-screen keyboards and other such input method user interfaces go here.return  13;case TYPE_INPUT_METHOD_DIALOG:// on-screen keyboards and other such input method user interfaces go here.return  14;case TYPE_STATUS_BAR:return  15;case TYPE_STATUS_BAR_ADDITIONAL:return  16;case TYPE_NOTIFICATION_SHADE:return  17;case TYPE_STATUS_BAR_SUB_PANEL:return  18;case TYPE_KEYGUARD_DIALOG:return  19;case TYPE_VOICE_INTERACTION_STARTING:return  20;case TYPE_VOICE_INTERACTION:// voice interaction layer should show above the lock screen.return  21;case TYPE_VOLUME_OVERLAY:// the on-screen volume indicator and controller shown when the user// changes the device volumereturn  22;case TYPE_SYSTEM_OVERLAY:// the on-screen volume indicator and controller shown when the user// changes the device volumereturn  canAddInternalSystemWindow ? 23 : 10;case TYPE_NAVIGATION_BAR:// the navigation bar, if available, shows atop most thingsreturn  24;case TYPE_NAVIGATION_BAR_PANEL:// some panels (e.g. search) need to show on top of the navigation barreturn  25;case TYPE_SCREENSHOT:// screenshot selection layer shouldn't go above system error, but it should cover// navigation bars at the very least.return  26;case TYPE_SYSTEM_ERROR:// system-level error dialogsreturn  canAddInternalSystemWindow ? 27 : 9;case TYPE_MAGNIFICATION_OVERLAY:// used to highlight the magnified portion of a displayreturn  28;case TYPE_DISPLAY_OVERLAY:// used to simulate secondary display devicesreturn  29;case TYPE_DRAG:// the drag layer: input for drag-and-drop is associated with this window,// which sits above all other focusable windowsreturn  30;case TYPE_ACCESSIBILITY_OVERLAY:// overlay put by accessibility services to intercept user interactionreturn  31;case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:return 32;case TYPE_SECURE_SYSTEM_OVERLAY:return  33;case TYPE_BOOT_PROGRESS:return  34;case TYPE_POINTER:// the (mouse) pointer layerreturn  35;default:Slog.e("WindowManager", "Unknown window type: " + type);return 3;}}

在DisplayArea层级结构中,可以直接容纳窗口的父节点,有三种类型:

  • TaskDisplayArea用于容纳App类型窗口,Task的容器是TaskDisplayArea,该容器也就是对应我们层级结构树中的DefaultTaskDisplayArea,ActivityRecord的容器是Task
  • DisplayArea.Tokens用于容纳非App类型窗口,WindowToken的容器是DisplayArea.Tokens,该容器对应层级结构树中的Leaf节点。其中WallpaperWindowToken继承WindowToken,是用来存放和Wallpaper相关的窗口
  • ImeContainer用于容纳输入法窗口,输入法的容器是ImeContainer

这里我们根据上面的代码,以及adb shell dumpsys activity containers的信息简单画出如下树形图
在这里插入图片描述

节点添加

如何知道这些窗口是在什么时候添加的?
我们需要理清各个节点的父子关系,从有助于我们找到关键代码

Task

从以及adb shell dumpsys activity containers和树形图我们知道Task节点的父亲是DefaultTaskDisplayArea
在这里插入图片描述
当然还有一种情况是Task的父节点为Task的情况。
在这里插入图片描述那么DefaultTaskDisplayArea和Task中一定有添加Task相关的方法,比如addTask、addChild。

以DefaultTaskDisplayArea为父节点

我们顺着这个思路在TaskDisplayArea.java中看看有没有相关方法
代码路径:frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java

    void addChild(WindowContainer child, int position) {if (child.asTaskDisplayArea() != null) {if (DEBUG_ROOT_TASK) {Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);}super.addChild(child, position);} else if (child.asTask() != null) {addChildTask(child.asTask(), position);} else {throw new IllegalArgumentException("TaskDisplayArea can only add Task and TaskDisplayArea, but found "+ child);}}private void addChildTask(Task task, int position) {if (DEBUG_ROOT_TASK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);addRootTaskReferenceIfNeeded(task);position = findPositionForRootTask(position, task, true /* adding */);super.addChild(task, position);if (mPreferredTopFocusableRootTask != null&& task.isFocusable()&& mPreferredTopFocusableRootTask.compareTo(task) < 0) {// Clear preferred top because the adding focusable task has a higher z-order.mPreferredTopFocusableRootTask = null;}mAtmService.updateSleepIfNeededLocked();onRootTaskOrderChanged(task);}

我们发现在void addChild(WindowContainer child, int position)中满足条件child.asTask() != null时,就会调用addChildTask(child.asTask(), position);这也是我们添加Task的方法。可以看到里面有一个关键的调用super.addChild(task, position);,也就是说实际的添加在这里
对应的是WindowContainer的void addChild(E child, int index)
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

    /*** Adds the input window container has a child of this container at the input index.*/@CallSupervoid addChild(E child, int index) {if (!child.mReparenting && child.getParent() != null) {throw new IllegalArgumentException("addChild: container=" + child.getName()+ " is already a child of container=" + child.getParent().getName()+ " can't add to container=" + getName()+ "\n callers=" + Debug.getCallers(15, "\n"));}if ((index < 0 && index != POSITION_BOTTOM)|| (index > mChildren.size() && index != POSITION_TOP)) {throw new IllegalArgumentException("addChild: invalid position=" + index+ ", children number=" + mChildren.size());}if (index == POSITION_TOP) {index = mChildren.size();} else if (index == POSITION_BOTTOM) {index = 0;}mChildren.add(index, child);// Set the parent after we've actually added a child in case a subclass depends on this.child.setParent(this);}

实际上调用的我们构建层级结构树时的方法。

以Task为父节点

在Task.java中查找添加节点的相关方法
代码路径:frameworks/base/services/core/java/com/android/server/wm/Task.java

    void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) {Task task = child.asTask();try {if (task != null) {task.setForceShowForAllUsers(showForAllUsers);}// We only want to move the parents to the parents if we are creating this task at the// top of its root task.addChild(child, toTop ? MAX_VALUE : 0, toTop /*moveParents*/);} finally {if (task != null) {task.setForceShowForAllUsers(false);}}}/*** Put a Task in this root task. Used for adding only.* When task is added to top of the root task, the entire branch of the hierarchy (including* root task and display) will be brought to top.* @param child The child to add.* @param position Target position to add the task to.*/private void addChild(WindowContainer child, int position, boolean moveParents) {// Add child task.addChild(child, null);// Move child to a proper position, as some restriction for position might apply.positionChildAt(position, child, moveParents /* includingParents */);}

这里的addChild(child, null);实际调用的是WindowContainer的protected void addChild(E child, Comparator<E> comparator),因为其父类TaskFragment中没有符合该入参的addChild方法,因此继续向上查找TaskFragment的父类WindowContainer中的addChild方法
代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java

   /*** Adds the input window container has a child of this container in order based on the input* comparator.* @param child The window container to add as a child of this window container.* @param comparator Comparator to use in determining the position the child should be added to.*                   If null, the child will be added to the top.*/@CallSuperprotected void addChild(E child, Comparator<E> comparator) {......//记录插入数组的位置,若为-1则将当前child加入到后面int positionToAdd = -1;if (comparator != null) {//判断当前节点中孩子的数量//依次比较将要加入的窗口与已经存在的child的BaseLayer//mChildren越大放到数组最前面final int count = mChildren.size();for (int i = 0; i < count; i++) {//比较baseLayer,如果child大于列表中已经存在的,则需要返回1,否则返回-1//新加入的的child大于mChildren.get(i)则返回1,小于则返回-1//注:comparator比较器的逻辑见上面代码的mWindowComparator if (comparator.compare(child, mChildren.get(i)) < 0) {//记录当前要插入的位置positionToAdd = i;break;}}}//如果新加入的窗口大于现在所有窗口if (positionToAdd == -1) {//将该窗口加入到列表最后mChildren.add(child);} else {mChildren.add(positionToAdd, child);}// Set the parent after we've actually added a child in case a subclass depends on this.//此处将child的mParent设置为thischild.setParent(this);}

protected void addChild(E child, Comparator<E> comparator)是重载addChild,和之前的void addChild(E child, int index)有所不同

ActivityRecord

ActivityRecord的父节点是Task,同样的在Task.java中找添加ActivityRecord的方法
代码路径:frameworks/base/services/core/java/com/android/server/wm/Task.java

    @Overridevoid addChild(WindowContainer child, int index) {index = getAdjustedChildPosition(child, index);super.addChild(child, index);ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);// A rootable task that is now being added to be the child of an organized task. Making// sure the root task references is keep updated.if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {getDisplayArea().addRootTaskReferenceIfNeeded((Task) child);}// Make sure the list of display UID allowlists is updated// now that this record is in a new task.mRootWindowContainer.updateUIDsPresentOnDisplay();// Only pass minimum dimensions for pure TaskFragment. Task's minimum dimensions must be// passed from Task constructor.final TaskFragment childTaskFrag = child.asTaskFragment();if (childTaskFrag != null && childTaskFrag.asTask() == null) {childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);}}

super.addChild(child, index);调用的是Task父类TaskFragment的addChild方法
代码路径:frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java

    @Overridevoid addChild(WindowContainer child, int index) {ActivityRecord r = topRunningActivity();mClearedTaskForReuse = false;mClearedTaskFragmentForPip = false;final ActivityRecord addingActivity = child.asActivityRecord();final boolean isAddingActivity = addingActivity != null;final Task task = isAddingActivity ? getTask() : null;// If this task had any activity before we added this one.boolean taskHadActivity = task != null && task.getTopMostActivity() != null;// getActivityType() looks at the top child, so we need to read the type before adding// a new child in case the new child is on top and UNDEFINED.final int activityType = task != null ? task.getActivityType() : ACTIVITY_TYPE_UNDEFINED;super.addChild(child, index);if (isAddingActivity && task != null) {// TODO(b/207481538): temporary per-activity screenshotingif (r != null && BackNavigationController.isScreenshotEnabled()) {ProtoLog.v(WM_DEBUG_BACK_PREVIEW, "Screenshotting Activity %s",r.mActivityComponent.flattenToString());Rect outBounds = r.getBounds();SurfaceControl.ScreenshotHardwareBuffer backBuffer = SurfaceControl.captureLayers(r.mSurfaceControl,new Rect(0, 0, outBounds.width(), outBounds.height()),1f);mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);}child.asActivityRecord().inHistory = true;task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);}}

super.addChild(child, index);调用TaskFragment父类方法,即WindowContainer的void addChild(E child, int index)

WindowToken

WindowToken的父节点是叶子节点或者输入法节点,叶子节点和输入法节点其实都是DisplayArea.Tokens类型。
WallpaperWindowToken继承WindowToken,因此同理。
所以我们只需在DisplayArea.java的Tokens类中查找相关的添加WindowToken的方法。
代码路径:frameworks/base/services/core/java/com/android/server/wm/DisplayArea.java

		void addChild(WindowToken token) {addChild(token, mWindowComparator);}

这里的addChild(token, mWindowComparator);调用的就是WindowContainer的protected void addChild(E child, Comparator<E> comparator)

WindowState

WindowState的父节点是WindowToken和ActivityRecord,我们在WindowToken.java和中ActivityRecord.java找添加WindowState的方法

以WindowToken为父节点

代码路径:frameworks/base/services/core/java/com/android/server/wm/WindowToken.java

    void addWindow(final WindowState win) {ProtoLog.d(WM_DEBUG_FOCUS,"addWindow: win=%s Callers=%s", win, Debug.getCallers(5));if (win.isChildWindow()) {// Child windows are added to their parent windows.return;}// This token is created from WindowContext and the client requests to addView now, create a// surface for this token.if (mSurfaceControl == null) {createSurfaceControl(true /* force */);// Layers could have been assigned before the surface was created, update them againreassignLayer(getSyncTransaction());}if (!mChildren.contains(win)) {ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);addChild(win, mWindowComparator);mWmService.mWindowsChanged = true;// TODO: Should we also be setting layout needed here and other places?}}

addChild(win, mWindowComparator);调用的就是WindowContainer的protected void addChild(E child, Comparator<E> comparator)添加WindowState

以ActivityRecord为父节点

代码路径:frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

    @Overridevoid addWindow(WindowState w) {super.addWindow(w);boolean gotReplacementWindow = false;for (int i = mChildren.size() - 1; i >= 0; i--) {final WindowState candidate = mChildren.get(i);gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);}// if we got a replacement window, reset the timeout to give drawing more timeif (gotReplacementWindow) {mWmService.scheduleWindowReplacementTimeouts(this);}checkKeyguardFlagsChanged();}

ActivityRecord的父类是WindowToken,其super.addWindow(w);调用的就是WindowToken的addWindow方法,因此最终也是通过WindowContainer的protected void addChild(E child, Comparator<E> comparator)添加WindowState

小结

通过前面的分析,添加窗口最终都是通过WindowContainer的void addChild(E child, int index)protected void addChild(E child, Comparator<E> comparator)来添加的,我们来汇总一下这两种方法的调用情况与区别

调用场景

调用void addChild(E child, int index)的情况

  1. DefaultTaskDisplayArea添加Task
  2. Task添加ActivityRecord

调用protected void addChild(E child, Comparator<E> comparator)的情况

  1. Task添加Task
  2. 叶子节点和输入法节点(Token)添加WindowToken
  3. WindowToken添加WindowState
  4. ActivityRecord添加WindowState

添加差异

WindowContainer中的void addChild(E child, int index)和protected void addChild(E child, Comparator comparator)方法区别是什么?
它们之间的区别其实在于添加子容器的方式和顺序。

void addChild(E child, int index)方法:

  • 该方法通过传入的index参数指定了子容器的插入位置。index表示子容器在当前容器的子容器列表中的位置索引。
  • 调用该方法会将子容器添加到指定的位置,而不会根据任何比较器进行排序。
  • 这种方式适用于需要直接指定子容器的插入位置的情况。

protected void addChild(E child, Comparator<E> comparator)方法:

  • 该方法通过传入的Comparator参数定义了子容器的排序规则。
  • 调用该方法会将子容器添加到当前容器的子容器列表中,并根据指定的比较器对子容器进行排序。
  • 这种方式适用于根据特定的排序规则对子容器进行动态排序的情况。

总结起来,addChild(E child, int index)方法允许直接指定子容器的插入位置,而addChild(E child, Comparator comparator)方法则通过比较器对子容器进行排序并添加到合适的位置。根据实际需求,可以选择适合的方法来添加子容器。

流程分析

添加log

既然从上述分析中发现添加窗口最终都是通过WindowContainer的void addChild(E child, int index)protected void addChild(E child, Comparator<E> comparator)来添加的,那么我们可以添加相关的log,来看看其对应的流程是怎么样的

    void addChild(E child, int index) {if (child instanceof Task || child instanceof ActivityRecord || child instanceof WindowToken || child instanceof WindowState) {android.util.Log.i("WindowContainer.TAG:", this + "addChild child = " + child , new Exception());}......}
    protected void addChild(E child, Comparator<E> comparator) {if (child instanceof Task || child instanceof ActivityRecord || child instanceof WindowToken || child instanceof WindowState) {android.util.Log.i("WindowContainer.TAG:", this + "addChild Comparator child = " + child , new Exception());}......}

堆栈打印流程

这里我们以Launcher和StatusBar为例

Launcher

WindowContainer.TAG   : DefaultTaskDisplayArea@243571827 addChild child = Task{a13d730 #1 type=home ?? U=0 visible=false visibleRequested=false mode=undefined translucent=true sz=0}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:727)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.addChildTask(TaskDisplayArea.java:334)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.addChild(TaskDisplayArea.java:320)
WindowContainer.TAG   : 	at com.android.server.wm.Task$Builder.build(Task.java:6551)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.createRootTask(TaskDisplayArea.java:1066)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.createRootTask(TaskDisplayArea.java:1040)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.getOrCreateRootHomeTask(TaskDisplayArea.java:1640)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.setWindowManager(RootWindowContainer.java:1321)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityTaskManagerService.setWindowManager(ActivityTaskManagerService.java:1006)
WindowContainer.TAG   : 	at com.android.server.am.ActivityManagerService.setWindowManager(ActivityManagerService.java:1923)
WindowContainer.TAG   : 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:1595)
WindowContainer.TAG   : 	at com.android.server.SystemServer.run(SystemServer.java:939)
WindowContainer.TAG   : 	at com.android.server.SystemServer.main(SystemServer.java:649)
WindowContainer.TAG   : 	at java.lang.reflect.Method.invoke(Native Method)
WindowContainer.TAG   : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
WindowContainer.TAG   : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:914)
WindowContainer.TAG   : Task{a13d730 #1 type=home ?? U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=0} addChild Comparator child = Task{63f31d4 #2 type=undefined A=1000:com.android.settings.FallbackHome U=0 visible=false visibleRequested=false mode=undefined translucent=true sz=0}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:694)
WindowContainer.TAG   : 	at com.android.server.wm.Task.addChild(Task.java:5935)
WindowContainer.TAG   : 	at com.android.server.wm.Task.-$$Nest$maddChild(Unknown Source:0)
WindowContainer.TAG   : 	at com.android.server.wm.Task$Builder.build(Task.java:6548)
WindowContainer.TAG   : 	at com.android.server.wm.Task.reuseOrCreateTask(Task.java:5819)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.setNewTask(ActivityStarter.java:2872)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1864)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1661)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1216)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:702)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStartController.startHomeActivity(ActivityStartController.java:179)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnTaskDisplayArea(RootWindowContainer.java:1493)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.lambda$startHomeOnDisplay$12$com-android-server-wm-RootWindowContainer(RootWindowContainer.java:1434)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer$$ExternalSyntheticLambda7.apply(Unknown Source:16)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.reduceOnAllTaskDisplayAreas(TaskDisplayArea.java:513)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.reduceOnAllTaskDisplayAreas(WindowContainer.java:2283)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnDisplay(RootWindowContainer.java:1433)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnDisplay(RootWindowContainer.java:1420)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnAllDisplays(RootWindowContainer.java:1405)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityTaskManagerService$LocalService.startHomeOnAllDisplays(ActivityTaskManagerService.java:5892)
WindowContainer.TAG   : 	at com.android.server.am.ActivityManagerService.systemReady(ActivityManagerService.java:8203)
WindowContainer.TAG   : 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:2801)
WindowContainer.TAG   : 	at com.android.server.SystemServer.run(SystemServer.java:939)
WindowContainer.TAG   : 	at com.android.server.SystemServer.main(SystemServer.java:649)
WindowContainer.TAG   : 	at java.lang.reflect.Method.invoke(Native Method)
WindowContainer.TAG   : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
WindowContainer.TAG   : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:914)
WindowContainer.TAG   : Task{63f31d4 #2 type=undefined A=1000:com.android.settings.FallbackHome U=0 rootTaskId=1 visible=true visibleRequested=false mode=fullscreen translucent=true sz=0} addChild child = ActivityRecord{983a135 u0 com.android.settings/.FallbackHome}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:727)
WindowContainer.TAG   : 	at com.android.server.wm.TaskFragment.addChild(TaskFragment.java:1835)
WindowContainer.TAG   : 	at com.android.server.wm.Task.addChild(Task.java:1429)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.addOrReparentStartingActivity(ActivityStarter.java:2927)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.setNewTask(ActivityStarter.java:2877)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.startActivityInner(ActivityStarter.java:1864)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.startActivityUnchecked(ActivityStarter.java:1661)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1216)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:702)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityStartController.startHomeActivity(ActivityStartController.java:179)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnTaskDisplayArea(RootWindowContainer.java:1493)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.lambda$startHomeOnDisplay$12$com-android-server-wm-RootWindowContainer(RootWindowContainer.java:1434)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer$$ExternalSyntheticLambda7.apply(Unknown Source:16)
WindowContainer.TAG   : 	at com.android.server.wm.TaskDisplayArea.reduceOnAllTaskDisplayAreas(TaskDisplayArea.java:513)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea.reduceOnAllTaskDisplayAreas(DisplayArea.java:404)
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.reduceOnAllTaskDisplayAreas(WindowContainer.java:2283)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnDisplay(RootWindowContainer.java:1433)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnDisplay(RootWindowContainer.java:1420)
WindowContainer.TAG   : 	at com.android.server.wm.RootWindowContainer.startHomeOnAllDisplays(RootWindowContainer.java:1405)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityTaskManagerService$LocalService.startHomeOnAllDisplays(ActivityTaskManagerService.java:5892)
WindowContainer.TAG   : 	at com.android.server.am.ActivityManagerService.systemReady(ActivityManagerService.java:8203)
WindowContainer.TAG   : 	at com.android.server.SystemServer.startOtherServices(SystemServer.java:2801)
WindowContainer.TAG   : 	at com.android.server.SystemServer.run(SystemServer.java:939)
WindowContainer.TAG   : 	at com.android.server.SystemServer.main(SystemServer.java:649)
WindowContainer.TAG   : 	at java.lang.reflect.Method.invoke(Native Method)
WindowContainer.TAG   : 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
WindowContainer.TAG   : 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:914)
WindowContainer.TAG   : ActivityRecord{983a135 u0 com.android.settings/.FallbackHome} t2} addChild Comparator child = Window{ae9b359 u0 com.android.settings/com.android.settings.FallbackHome}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:694)
WindowContainer.TAG   : 	at com.android.server.wm.WindowToken.addWindow(WindowToken.java:302)
WindowContainer.TAG   : 	at com.android.server.wm.ActivityRecord.addWindow(ActivityRecord.java:4212)
WindowContainer.TAG   : 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1773)
WindowContainer.TAG   : 	at com.android.server.wm.Session.addToDisplayAsUser(Session.java:209)
WindowContainer.TAG   : 	at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:652)
WindowContainer.TAG   : 	at com.android.server.wm.Session.onTransact(Session.java:175)
WindowContainer.TAG   : 	at android.os.Binder.execTransactInternal(Binder.java:1280)
WindowContainer.TAG   : 	at android.os.Binder.execTransact(Binder.java:1244)

home task直接被TaskDisplayArea持有为孩子,这里可以明显看出Task{a13d730 #1 type=home 是在第一次创建WMS就已经创建好了,通过的是TaskDisplayArea.getOrCreateRootHomeTask开始一直到com.android.server.wm.WindowContainer.addChild
之后home task加入一个具体Launcher的task,这里最开始当然是我们的FallbackHome。
具体堆栈可以看出是ActivityManagerService.systemReady时候触发了ActivityTaskManagerService$LocalService.startHomeOnAllDisplays然后把HomeActivity拉起,由于此时还是加密状态,所以获取的的Home当然是setting的fallbackhome
最后ActivityRecord添加WindowState,就是通过跨进程通信addWindow。

StatusBar

WindowContainer.TAG   : Leaf:15:15@65133355 addChild Comparator child = WindowToken{ea411e9 type=2000 android.os.BinderProxy@46a0296}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:694)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayArea$Tokens.addChild(DisplayArea.java:605)
WindowContainer.TAG   : 	at com.android.server.wm.DisplayContent.addWindowToken(DisplayContent.java:1235)
WindowContainer.TAG   : 	at com.android.server.wm.WindowToken.<init>(WindowToken.java:214)
WindowContainer.TAG   : 	at com.android.server.wm.WindowToken$Builder.build(WindowToken.java:817)
WindowContainer.TAG   : 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1577)
WindowContainer.TAG   : 	at com.android.server.wm.Session.addToDisplayAsUser(Session.java:209)
WindowContainer.TAG   : 	at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:652)
WindowContainer.TAG   : 	at com.android.server.wm.Session.onTransact(Session.java:175)
WindowContainer.TAG   : 	at android.os.Binder.execTransactInternal(Binder.java:1280)
WindowContainer.TAG   : 	at android.os.Binder.execTransact(Binder.java:1244)
WindowContainer.TAG   : WindowToken{ea411e9 type=2000 android.os.BinderProxy@46a0296} addChild Comparator child = Window{c86ce6e u0 StatusBar}
WindowContainer.TAG   : java.lang.Exception
WindowContainer.TAG   : 	at com.android.server.wm.WindowContainer.addChild(WindowContainer.java:694)
WindowContainer.TAG   : 	at com.android.server.wm.WindowToken.addWindow(WindowToken.java:302)
WindowContainer.TAG   : 	at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1773)
WindowContainer.TAG   : 	at com.android.server.wm.Session.addToDisplayAsUser(Session.java:209)
WindowContainer.TAG   : 	at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:652)
WindowContainer.TAG   : 	at com.android.server.wm.Session.onTransact(Session.java:175)
WindowContainer.TAG   : 	at android.os.Binder.execTransactInternal(Binder.java:1280)
WindowContainer.TAG   : 	at android.os.Binder.execTransact(Binder.java:1244)

WindowToken和WindowState都是通过跨进程通信Session.addToDisplayAsUser来调用。
WindowToken的堆栈中WindowContainer.TAG : at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1577),在1577行开始添加WindowToken,而WindowState的堆栈中WindowContainer.TAG : at com.android.server.wm.WindowManagerService.addWindow(WindowManagerService.java:1773)1773行开始添加WindowState,正好是在添加WindowToken之后。
具体流程可参考Android T WMS窗口相关流程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/130627.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于ESP32S3无法识别到端口问题

前言 &#xff08;1&#xff09;因为实习问题&#xff0c;需要使用ESP32BOX进行二次开发。一般来说&#xff0c;接触一款MCU&#xff0c;3天上手是基本操作。但是对于乐鑫的芯片&#xff0c;环境搭建是真的折磨人&#xff08;苦笑&#xff09;&#xff0c;而且官方文档几乎没有…

安防监控/视频汇聚/云存储/AI智能视频分析平台EasyCVR显示CPU过载,该如何解决?

视频云存储/安防监控/视频汇聚平台EasyCVR基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。安防视频监控系统EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云…

Tomcat配置ssl、jar包

Tomcat配置ssl 部署tomcat服务&#xff0c;项目做到用https访问&#xff0c;使用nginx去做&#xff0c;访问任意一个子网站&#xff0c;都是https 或者 医美项目需要 上传jdk 456 tomcat war包 [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/…

DataGrip实时模板的配置2.0

印象里一直记着配置过代码实时模板&#xff0c;但是忘了换了工作电脑&#xff0c;之前配置的模板在我另一台电脑上 需要重新配置一下&#xff0c;我是笨蛋orz 配置方法和之前的一致 DataGrip实时模板的配置_王小小鸭的博客-CSDN博客https://blog.csdn.net/clover_oreo/articl…

AHR亚马逊账户健康评级多久更新,如何查看解决

AHR&#xff08;Account Health Rating&#xff09;即亚马逊账户健康评级&#xff0c;是亚马逊为卖家提供的一种评估卖家账户健康状况的工具。通过AHR&#xff0c;亚马逊会对卖家的账户进行综合评估&#xff0c;并给出相应的评级&#xff0c;以反映账户的整体表现和信誉。 亚马…

C++中使用R“()“标记符书写多行字符串

在C#中使用表示的字符串能够跨越数行。用于在C#中写JS或SQL代码比较方便。 string sqlInsert "INSERT INTO tb_param(protocol, slave, number, ptype, pid, name, format) VALUES(2, 24, 0, 1, 1, a04005, .3);INSERT INTO tb_param(protocol, slave, number, ptype, …

水循环原理VR实景教学课件开发

日本核污水排海让人们越来越重视海洋大气层水循环的安全&#xff0c;水循环是一个周而复始、循环往复的动态过程&#xff0c;为了将水循环过程以形象、生动地形式展示出来&#xff0c;水循环VR全景动态演示逐渐受到大家青睐。 传统的水循环教育方式通常是通过图片、动画或实地考…

REST风格【SpringBoot】

1.REST简介 行为动作 通常模块名使用复数&#xff0c;也就是加s 2.RESTful入门 Controller public class UserController {RequestMapping(value "/users", method RequestMethod.POST)public String save() {System.out.println("user save");return &…

iwebsec靶场 文件包含漏洞通关笔记3-session文件包含

目录 1.打开靶场 2.源码分析 &#xff08;1&#xff09;session文件包含漏洞的的工作原理 &#xff08;2&#xff09;sessionstart()做了哪些初始化工作 3.获取session文件位置 4.向session写入webshell 5.访问webshell 1.打开靶场 iwebsec 靶场漏洞库iwebsechttp://iw…

【CesiumJS入门】(10)绘制多边形(动态实时画面)

前言 如果你是在寻求解决方案&#xff0c;可以直接用cesium-draw这个插件。 鼠标左键添加点、右键完成绘制,单击右侧弹窗关闭按钮清空绘制。参考沙盒示例&#xff1a;Drawing on Terrain 直接上代码了 /** Date: 2023-07-12 18:47:18* LastEditors: ReBeX 420659880qq.com* L…

OneFormer: One Transformer to Rule Universal Image Segmentation论文笔记

论文https://arxiv.org/pdf/2211.06220.pdfCodehttps://github.com/SHI-Labs/OneFormer 文章目录 1. Motivation2. 方法2.1 与Mask2Former的相同之处2.2 OneFormer创新之处2.3 Task Conditioned Joint Training2.4 Query Representations2.4 Task Guided Contrastive Queries 3…

c++的引用和指针

我们要清楚的知道&#xff0c;使用指针和引用都可以的传入函数的main函数的变量在局部函数改变值时&#xff0c;main函数里面相应的变量也会改变值。但他俩的方式不同。 我们先来说指针&#xff0c;指针传入局部参数时&#xff0c;他会在创建个局部指针变量&#xff0c;然后把…

Unity——导航系统补充说明

一、导航系统补充说明 1、导航与动画 我们可以通过设置动画状态机的变量&#xff0c;让动画匹配由玩家直接控制的角色的移动。那么自动导航的角色如何与动画系统结合呢&#xff1f; 有两个常用的属性可以获得导航代理当前的状态&#xff1a; 一是agent.velocity&#xff0c;…

Pyinstaller打包EXE时添加版本信息、作者信息并在运行时读取外部配置文件

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

【计算机网络】UDP协议详解

目录 前言 端口号的拓展 端口号范围划分 netstat pidof UDP协议 UDP协议端格式 UDP的特点 面向数据报 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议 前言 我们前面讲完了http和https协议&#xff0c;它们都属于应用层&#xff0c;按照TCP/IP五层模…

优思学院|为什么质量工程师在别人看是“救火“的呢?

为什么质量工程师在别人看是‘救火’的呢&#xff1f;现今的质量管理体系已经很成熟&#xff0c;一家公司质量部门会有IQC、IPQC、OQC负责来料、过程质量、成品质量等等&#xff0c;而质量工程师&#xff08;QE&#xff09;的工作是要确保这些活动合理和有效&#xff0c;不产生…

9.9|day 2|整数拆分|不同的二叉搜索树

整数拆分&#xff1a; class Solution {public int integerBreak(int n) {int[] dp new int[n1];dp[2] 1;for(int i 3;i<n;i){for(int j 1;j<i-j;j){dp[i] Math.max(dp[i],Math.max(j*dp[i-j],j*(i-j)));}}//这里感觉要注意的就是j是我们要拆分的数&#xff0c;所…

蓝桥杯打卡Day7

文章目录 阶乘的末尾0整除问题 一、阶乘的末尾0IO链接 本题思路&#xff1a;由于本题需要求阶乘的末尾0&#xff0c;由于我们知道2*510可以得到一个0&#xff0c;那么我们就可以找出2的数和5的数&#xff0c;但是由于是阶乘&#xff0c;所以5的数量肯定是小于2的数量&#xf…

【数据结构】3000字剖析链表及双向链表

文章目录 &#x1f490; 链表的概念与结构&#x1f490;链表的介绍&#x1f490;链表的模拟实现 &#x1f490;双向链表&#x1f490;双向链表的模拟实现 &#x1f490;链表常用的方法&#x1f490;链表及顺序表的遍历&#x1f490;ArrayList和LinkedList的差异 &#x1f490; …

logback/log4j基本配置和标签详解

什么是logback logback 继承自 log4j&#xff0c;它建立在有十年工业经验的日志系统之上。它比其它所有的日志系统更快并且更小&#xff0c;包含了许多独特并且有用的特性。 logback.xml 首先直接上配置&#xff0c;我在项目过程中发现一些同时遇到需要logback文件的时候就去…