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之后的控制台 可复制下方的地址运行打包后的项目,运行…...
探索程序员需要掌握的算法?
文章目录 一:引言二:常见算法介绍三:重点算法总结 🎉欢迎来到数据结构学习专栏~探索程序员需要掌握的算法? ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客🎈该系列文章…...
性能测试 —— Jmeter定时器
固定定时器 如果你需要让每个线程在请求之前按相同的指定时间停顿,那么可以使用这个定时器;需要注意的是,固定定时器的延时不会计入单个sampler的响应时间,但会计入事务控制器的时间 1、使用固定定时器位置在http请求中…...
mp4视频太大怎么压缩?几种常见压缩方法
mp4视频太大怎么压缩?科技的飞速发展使得视频成为人们生活中不可或缺的一部分。然而,随着视频质量的不断提高,视频文件的大小也与日俱增,给我们的存储和传输带来了巨大的挑战和困扰。特别是MP4格式的视频,由于其出色的…...
论文复制ChatGPT按钮被发表,撤回后再曝多个类似案例;Midjourney 生成大师级的人像
🦉 AI新闻 🚀 论文复制ChatGPT按钮被发表,撤回后再曝多个类似案例 摘要:一篇物理论文复制了ChatGPT按钮内容,经过两个月同行评审并在杂志上发表。这一现象被知名打假人发现后,发表商决定撤回该论文。此外…...
Python自动化测试 史上最全的进阶教程
Python自动化测试就是把以前人为测试转化为机器测试的一种过程。自动化测试是一种比手工测试更快获得故障反馈的方法。 随着时代的变革,也许在未来测试这个职位的需求会越来越少甚至消失,但是每一个组织,每一个客户对软件质量的要求是永远不…...
centos pip失效
在 CentOS 上安装和配置 pip3 可能需要以下步骤: 确保 Python 3 已正确安装:请确保您已经正确地安装了 Python 3。在 CentOS 上,Python 3 可能默认安装在 /usr/bin/python3 路径下。您可以通过运行以下命令来验证 Python 3 是否正确安装&…...
Java——》ThreadLocal
推荐链接: 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…...
如何做好利益相关方的期望管理?
利益相关方对项目而言非常重要,有效管理利益相关方的期望可以帮助项目团队更好地满足利益相关方的需求,助于建立良好的合作伙伴关系,提高项目的可持续性和成功率。 如果项目团队无法满足利益相关方的需求,可能会引发冲突、争议或其…...
【K8S系列】深入解析k8s网络插件—Canal
序言 做一件事并不难,难的是在于坚持。坚持一下也不难,难的是坚持到底。 文章标记颜色说明: 黄色:重要标题红色:用来标记结论绿色:用来标记论点蓝色:用来标记论点 在现代容器化应用程序的世界中…...
从单页面应用角度去解决不跳转页面,也能更改浏览器url地址
正常来说不刷新页面,也能更改浏览器url地址的方法有很多,我们在网上搜的话可以看到有pushState、replaceState、popstate等方法,那还有没有其他方法呢? 答案是有的! 最近做一个vue商城项目的时候,用户点击支…...
wordpress禁用主题字体/推广网站大全
案例:电脑清理怎么做? 【求一个电脑清理的好方法!电脑垃圾文件太多了又不敢随意删除,怕误删重要的文件!哪位友友可以帮我出出主意呀?到底应该怎么清理电脑呢?】 电脑使用的时间长了都会慢慢变…...
自己建还是找代理建网站/建网站需要多少钱和什么条件
什么是一个高度平衡的二叉搜索树? 树结构中的常见用语: 节点的深度 - 从树的根节点到该节点的边数 节点的高度 - 该节点和叶子之间最长路径上的边数 树的高度 - 其根节点的高度 一个高度平衡的二叉搜索树(平衡二叉搜索树)是在插入和删除任何节点之…...
wordpress数据库软件/百度推广优化技巧
LM35温度传感器驱动 文章目录 LM35温度传感器驱动1、LM35介绍2、硬件准备3、软件准备4、驱动实现1、LM35介绍 LM35 系列是精密集成电路温度传感器,其输出电压与摄氏(摄氏度)温度成线性比例。 因此,LM35 优于以开尔文校准的线性温度传感器,因为用户无需从其输出中减去较大…...
拉丝机东莞网站建设/日本搜索引擎naver入口
Win 7英文系统显示中文乱码的解决http://www.enet.com.cn/article/2011/0811/A20110811896633.shtml 请点击Startmenu并点击Control Panel来打开控制面板,点击Clock Language andRegion下面的Change display language, 在弹出窗口中点击Administrative选项卡, 将Cur…...
那里可以做PC28网站的/一网信息一个简单便捷的新闻网站
点击上方“iOS开发”,选择“置顶公众号”关键时刻,第一时间送达!iOS 通过 runtime 的 API 可以给分类添加属性,关联属性总共有下边3个 API///获取某个对象的关联属性id objc_getAssociatedObject(id object, const void *key) { return _o…...
深圳网站建设seo/百度网页游戏
转: http://www.blogjava.net/kent/articles/200991.html只有MDF文件如何恢复数据库 由于种种原因,我们如果当时仅仅备份了mdf文件,那么恢复起来就是一件很麻烦的事情了。 如果您的mdf文件是当前数据库产生的,那么很侥幸,也许你使…...