当前位置: 首页 > news >正文

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窗口相关流程

相关文章:

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

文章目录 序节点添加Task以DefaultTaskDisplayArea为父节点以Task为父节点 ActivityRecordWindowTokenWindowState以WindowToken为父节点以ActivityRecord为父节点 小结调用场景添加差异 流程分析添加log堆栈打印流程LauncherStatusBar 序 尚未添加窗口的层级结构树&#xff0…...

3D虚拟数字人定制,推动传统文化传播新高度

“数字人”成为“汉语盘点2022”年度十大新词语。伴随着科技发展成长的年轻人逐渐成为消费主力军&#xff0c;如何在虚拟世界与年轻一代用户互动以抓住95后年轻人受众&#xff0c;成为不少传统文化品牌发力的重点。 数字人“天妤”&#xff0c;在3D虚拟数字人定制中&#xff0…...

kubernetes进阶 (三) 基础练习

前两天朋友给了我几道题&#xff0c;看着挺简单的&#xff0c;但实际做的时候发现坑不少&#xff0c;这里做下笔记 一、镜像构建部署lnmp 1、构建镜像 nginx、php、mysql 要求使用centos7作为基础镜像 2、使用deployment部署上面的容器,要求3个服务要放到一个pod中(虽然这样是…...

数据结构 排序

目录 第八章 排序8.1排序的基本概念1. 概念2. 排序算法的分类 8.2 插入排序8.2.1 直接插入排序8.2.2 算法效率分析8.2.2 折半插入排序总结8.2.3 希尔排序 8.3 交换排序8.3.1冒泡排序8.3.2快速排序&#xff08;了解栈的过程&#xff09; 8.4 选择排序8.4.1 简单选择排序8.4.2 堆…...

Cpp/Qtday050912cpp基础

目录 实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#x…...

Git diff 使用 vimdiff 对比差异

在Ubuntu中使用Git时&#xff0c;可使用命令行的git diff命令来对比两次提交的差异&#xff0c;但是这种对比查看方式无法直观地查看修改的差异&#xff0c;在对比和查看时不太方便。 可以使用vimdiff作为Git diff的对比工具&#xff0c;这样就方便了许多&#xff0c;Git的配置…...

c小白勇闯结构体!!!!

目录 1.结构体类型的声明 1.结构的基础 2.结构体的声明 3.结构体成员的类型 4结构体变量的定义和初始化 2.结构体成员的访问 3.结构体传参 1.结构体类型的声明 1.结构的基础 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量 结构体变量的创…...

【DevOps核心理念基础】3. 敏捷开发最佳实践

一、敏捷开发最佳实践 1.1 项目管理 1.2 需求管理 1.3 技术架构 1.4 技术开发 1.5 测试 二、敏捷开发最佳实践 2.1 敏捷开发的执行细节 三、全面的DevOps工具链 四、版本控制和协作开发工具 4.1 集中式版本控制工具 4.2 分布式版本控制工具 一、敏捷开发最佳实践 …...

二进制、数位dp:0912T3

考虑题目转化&#xff0c;二进制下满足 i ⊆ j , ( i x ) ⊆ ( j y ) i\subseteq j,(ix)\subseteq (jy) i⊆j,(ix)⊆(jy) 这显然是个数位dp形式 考虑枚举每一位与进位&#xff0c; d p k , p 1 , p 2 dp_{k,p_1,p_2} dpk,p1​,p2​​ 表示第 k − 1 k-1 k−1 位向第 k k…...

Java基于SpringBoot+Vue的 4S店车辆管理系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 功能总览4 系统设计4.1 系统设计主要功能4.2 数据库设计4.2.1 数据库设计规范4.2…...

助力智能化公路养护,基于YOLOv5s集成SPD-BIFPN-SE开发构建公路开裂检测识别系统

在前文中我们尝试构建了在隧道、涵洞尝尽下的自动智能化养护巡查相关的模型&#xff0c;进行了实地测试评估&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《基于轻量级YOLOv5s开发构建隧道基建裂痕、脱落等缺陷问题检测系统》 本文的想法是相近的&#xff0c;核心…...

C++--day5

实现一个图形类&#xff08;Shape&#xff09;&#xff0c;包含受保护成员属性&#xff1a;周长、面积&#xff0c; 公共成员函数&#xff1a;特殊成员函数书写 定义一个圆形类&#xff08;Circle&#xff09;&#xff0c;继承自图形类&#xff0c;包含私有属性&#xff1a;半…...

Django应用部署实战:从开发到生产,全程解析

部署架构图 版本说明 Centos 7.4 Python 3.6.4 Django 2.0.2 Channels 2.0.0 MySql 5.7 uWSGI Nginx 1.12.2 部署前 1、更新系统环境 yum install epel-release 2、安装所有的开发工具包 yum groupinstall -y “Development tools” 一、安装python 3.6.4 1、下载 cd /usr/…...

群晖NAS如何在内网部署HTTPS服务让浏览器信任证书

前言 最近在折腾内部部署Web服务。通过Vue实现一个H5的内部的管理服务。但在实际部署过程中由于种种原因&#xff0c;必须部署成Https服务。但在部署成Https服务后&#xff0c;由于没有HTTPS证书&#xff0c;每次进入页面都会被浏览器拦截。使用起来非常不便。于是开始各种Goo…...

crAPI靶场学习记录

靶场搭建 [靶场下载地址](我fork了一份) docker安装&#xff0c;笔者是用的wsldocker. [lab0:**初始账户 **] 注册一个账户&#xff0c;邮箱为[APIqq.com]&#xff0c;密码为Admin123 登陆后访问对应IP的8025端口&#xff0c;接收邮件获取车辆信息。 [lab1:**访问其它用户车…...

知识图谱实战应用28-基于py2neo的ICD-11疾病分类的知识图谱的查询与问答实战应用

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用28-基于py2neo的ICD-11疾病分类的知识图谱的查询与问答实战应用。使用基于py2neo的ICD-11疾病分类知识图谱,我们能够像探索一座生物医学宇宙般,穿梭在各种疾病之间。这个神奇的图谱可以帮助我们揭示各种疾病之间复杂而…...

20.Xaml GroupBox控件 ---->带标题的内容控件

1.运行效果 2.运行源码 a.Xaml源码 <Window x:Class="testView.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic…...

基于CycleGAN的山水风格画迁移

基于CycleGAN的山水风格画迁移 1、简介 1.1 研究背景及意义 绘画是人类重要的一种艺术形式&#xff0c;其中中国的山水画源远流长&#xff0c;具有丰富的美学内涵&#xff0c;沉淀着中国人的情思。游山玩水的大陆文化意识&#xff0c;以山为德、水为性的内在修为意识&#x…...

​@Cacheable 注解​

1. 功能说明 Cacheable 注解在方法上&#xff0c;表示该方法的返回结果是可以缓存的。也就是说&#xff0c;该方法的返回结果会放在缓存中&#xff0c;以便于以后使用相同的参数调用该方法时&#xff0c;会返回缓存中的值&#xff0c;而不会实际执行该方法。 注意&#xff0c;这…...

vue3+ts项目打包后的本地访问

注意&#xff1a;打包之后不可直接点击html访问&#xff0c;需要给项目安装本地服务&#xff01; 1、安装servenpm i -g serve 2、打包项目npm run build 生成dist文件夹 3、本地访问serve dist 运行service dist之后的控制台 可复制下方的地址运行打包后的项目&#xff0c;运行…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...