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)的情况
- DefaultTaskDisplayArea添加Task
- Task添加ActivityRecord
调用protected void addChild(E child, Comparator<E> comparator)的情况
- Task添加Task
- 叶子节点和输入法节点(Token)添加WindowToken
- WindowToken添加WindowState
- 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 序 尚未添加窗口的层级结构树࿰…...
3D虚拟数字人定制,推动传统文化传播新高度
“数字人”成为“汉语盘点2022”年度十大新词语。伴随着科技发展成长的年轻人逐渐成为消费主力军,如何在虚拟世界与年轻一代用户互动以抓住95后年轻人受众,成为不少传统文化品牌发力的重点。 数字人“天妤”,在3D虚拟数字人定制中࿰…...
kubernetes进阶 (三) 基础练习
前两天朋友给了我几道题,看着挺简单的,但实际做的时候发现坑不少,这里做下笔记 一、镜像构建部署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快速排序(了解栈的过程) 8.4 选择排序8.4.1 简单选择排序8.4.2 堆…...
Cpp/Qtday050912cpp基础
目录 实现一个图形类(Shape),包含受保护成员属性:周长、面积, 公共成员函数:特殊成员函数书写 定义一个圆形类(Circle),继承自图形类,包含私有属性&#x…...
Git diff 使用 vimdiff 对比差异
在Ubuntu中使用Git时,可使用命令行的git diff命令来对比两次提交的差异,但是这种对比查看方式无法直观地查看修改的差异,在对比和查看时不太方便。 可以使用vimdiff作为Git diff的对比工具,这样就方便了许多,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
考虑题目转化,二进制下满足 i ⊆ j , ( i x ) ⊆ ( j y ) i\subseteq j,(ix)\subseteq (jy) i⊆j,(ix)⊆(jy) 这显然是个数位dp形式 考虑枚举每一位与进位, 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店车辆管理系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 功能总览4 系统设计4.1 系统设计主要功能4.2 数据库设计4.2.1 数据库设计规范4.2…...
助力智能化公路养护,基于YOLOv5s集成SPD-BIFPN-SE开发构建公路开裂检测识别系统
在前文中我们尝试构建了在隧道、涵洞尝尽下的自动智能化养护巡查相关的模型,进行了实地测试评估,感兴趣的话可以自行移步阅读即可: 《基于轻量级YOLOv5s开发构建隧道基建裂痕、脱落等缺陷问题检测系统》 本文的想法是相近的,核心…...
C++--day5
实现一个图形类(Shape),包含受保护成员属性:周长、面积, 公共成员函数:特殊成员函数书写 定义一个圆形类(Circle),继承自图形类,包含私有属性:半…...
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的内部的管理服务。但在实际部署过程中由于种种原因,必须部署成Https服务。但在部署成Https服务后,由于没有HTTPS证书,每次进入页面都会被浏览器拦截。使用起来非常不便。于是开始各种Goo…...
crAPI靶场学习记录
靶场搭建 [靶场下载地址](我fork了一份) docker安装,笔者是用的wsldocker. [lab0:**初始账户 **] 注册一个账户,邮箱为[APIqq.com],密码为Admin123 登陆后访问对应IP的8025端口,接收邮件获取车辆信息。 [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 研究背景及意义 绘画是人类重要的一种艺术形式,其中中国的山水画源远流长,具有丰富的美学内涵,沉淀着中国人的情思。游山玩水的大陆文化意识,以山为德、水为性的内在修为意识&#x…...
@Cacheable 注解
1. 功能说明 Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的。也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。 注意,这…...
vue3+ts项目打包后的本地访问
注意:打包之后不可直接点击html访问,需要给项目安装本地服务! 1、安装servenpm i -g serve 2、打包项目npm run build 生成dist文件夹 3、本地访问serve dist 运行service dist之后的控制台 可复制下方的地址运行打包后的项目,运行…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
软件工程 期末复习
瀑布模型:计划 螺旋模型:风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合:模块内部功能紧密 模块之间依赖程度小 高内聚:指的是一个模块内部的功能应该紧密相关。换句话说,一个模块应当只实现单一的功能…...
02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...
内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...
