本文接着如下文章往下讲
Android14 WMS-窗口绘制之relayoutWindow流程(一)-Client端-CSDN博客
然后就到了Server端WMS的核心实现方法relayoutWindow里
WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stubimplements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
...public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,int lastSyncSeqId, ClientWindowFrames outFrames,MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,InsetsState outInsetsState, InsetsSourceControl.Array outActiveControls,Bundle outSyncIdBundle) {
由于此方法太长,所以分开讲述
1. 第一步
if (outActiveControls != null) {outActiveControls.set(null);}int result = 0;boolean configChanged = false;
//获取发起者的Uid和Pidfinal int pid = Binder.getCallingPid();final int uid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();synchronized (mGlobalLock) {
//通过IBinder client查询mWindowMap中对应的WindowState final WindowState win = windowForClientLocked(session, client, false);if (win == null) {return 0;}if (win.mRelayoutSeq < seq) {win.mRelayoutSeq = seq;} else if (win.mRelayoutSeq > seq) {return 0;}if (win.cancelAndRedraw() && win.mPrepareSyncSeqId <= lastSyncSeqId) {// The client has reported the sync draw, but we haven't finished it yet.// Don't let the client perform a non-sync draw at this time.result |= RELAYOUT_RES_CANCEL_AND_REDRAW;}
//获取window对应的DisplayContent final DisplayContent displayContent = win.getDisplayContent();
//获取window对应的DisplayPolicy final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
//获取window对应的WindowStateAnimator WindowStateAnimator winAnimator = win.mWinAnimator;if (viewVisibility != View.GONE) {
//如果不是Gone,则更新全局变量之窗口申请的宽高 mRequestedWidth mRequestedHeight win.setRequestedSize(requestedWidth, requestedHeight);}
2. 第二步
int attrChanges = 0;int flagChanges = 0;int privateFlagChanges = 0;
//如果窗口的属性不为空,则说明有要更新的窗口属性if (attrs != null) {
//调整窗口参数,主要是针对某些窗口类型,清理一些窗口属性参数displayPolicy.adjustWindowParamsLw(win, attrs);
...
窗口type在窗口add之后不能被改变,否则就会异常,窗口type是区分窗口层级很重要的一个东西if (win.mAttrs.type != attrs.type) {throw new IllegalArgumentException("Window type can not be changed after the window is added.");}
...
//异或^ 两个位相同为0,相异为1flagChanges = win.mAttrs.flags ^ attrs.flags;privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;attrChanges = win.mAttrs.copyFrom(attrs);final boolean layoutChanged =(attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0;if (layoutChanged || (attrChanges& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
窗口布局有变化,需要更新win.mLayoutNeeded = true;}if (layoutChanged && win.providesDisplayDecorInsets()) {configChanged = displayPolicy.updateDecorInsetsInfo();}
//看下有没有锁屏相关的flag变化if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0|| (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {win.mActivityRecord.checkKeyguardFlagsChanged();}if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {updateNonSystemOverlayWindowsVisibilityIfNeeded(win, win.mWinAnimator.getShown());}if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);}
...}
3. 第三步
int attrChanges = 0;int flagChanges = 0;int privateFlagChanges = 0;
//如果窗口的属性不为空,则说明有要更新的窗口属性if (attrs != null) {
//调整窗口参数,主要是针对某些窗口类型,清理一些窗口属性参数displayPolicy.adjustWindowParamsLw(win, attrs);
...
窗口type在窗口add之后不能被改变,否则就会异常,窗口type是区分窗口层级很重要的一个东西if (win.mAttrs.type != attrs.type) {throw new IllegalArgumentException("Window type can not be changed after the window is added.");}
...
//异或^ 两个位相同为0,相异为1flagChanges = win.mAttrs.flags ^ attrs.flags;privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;attrChanges = win.mAttrs.copyFrom(attrs);final boolean layoutChanged =(attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0;if (layoutChanged || (attrChanges& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
窗口布局有变化,需要更新win.mLayoutNeeded = true;}if (layoutChanged && win.providesDisplayDecorInsets()) {configChanged = displayPolicy.updateDecorInsetsInfo();}
//看下有没有锁屏相关的flag变化if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0|| (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {win.mActivityRecord.checkKeyguardFlagsChanged();}if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {updateNonSystemOverlayWindowsVisibilityIfNeeded(win, win.mWinAnimator.getShown());}if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);}
...}
4. 第四步
//06-01 10:12:18.006 1890 2256 V WindowManager: Relayout Window{8d0d088 u0
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}:
//viewVisibility=0 req=7104x3840 {(0,0)(fillxfill) sim={adjust=resize forwardNavigation}
//ty=BASE_APPLICATION wanim=0x10302f2
//06-01 10:12:18.006 1890 2256 V WindowManager: fl=LAYOUT_IN_SCREEN //LAYOUT_INSET_DECOR
//SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
//06-01 10:12:18.006 1890 2256 V WindowManager: pfl=NO_MOVE_ANIMATION
//FORCE_DRAW_STATUS_BAR_BACKGROUND HIDE_NON_SYSTEM_OVERLAY_WINDOWS USE_BLAST
//FIT_INSETS_CONTROLLED
//06-01 10:12:18.006 1890 2256 V WindowManager: vsysui=LIGHT_STATUS_BAR
//LIGHT_NAVIGATION_BAR
//06-01 10:12:18.006 1890 2256 V WindowManager: apr=LIGHT_STATUS_BARS
//LIGHT_NAVIGATION_BARS
//06-01 10:12:18.006 1890 2256 V WindowManager: bhv=DEFAULT
//06-01 10:12:18.006 1890 2256 V WindowManager: fitSides=}if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility+ " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {winAnimator.mAlpha = attrs.alpha;}
//设置窗口大小win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);if (win.mAttrs.surfaceInsets.left != 0|| win.mAttrs.surfaceInsets.top != 0|| win.mAttrs.surfaceInsets.right != 0|| win.mAttrs.surfaceInsets.bottom != 0) {winAnimator.setOpaqueLocked(false);}final int oldVisibility = win.mViewVisibility;// If the window is becoming visible, visibleOrAdding may change which may in turn// change the IME target.
//窗口由不可见/Gone变为可见final boolean becameVisible =(oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)&& viewVisibility == View.VISIBLE;boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0|| becameVisible;
//窗口焦点更新--当之前的可见性和现在不一致,并且窗口没有携带FLAG_NOT_FOCUSABLE,并且mRelayoutCalled为falseboolean focusMayChange = win.mViewVisibility != viewVisibility|| ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)|| (!win.mRelayoutCalled);boolean wallpaperMayMove = win.mViewVisibility != viewVisibility&& win.hasWallpaper();wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {winAnimator.mSurfaceController.setSecure(win.isSecureLocked());}final boolean wasVisible = win.isVisible();win.mRelayoutCalled = true;win.mInRelayout = true;
//设置窗口可见性为申请的可见性,可见则viewVisibility=0win.setViewVisibility(viewVisibility);ProtoLog.i(WM_DEBUG_SCREEN_ON,"Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,viewVisibility, new RuntimeException().fillInStackTrace());
//06-01 10:12:18.008 1890 2256 W WindowManager: setLayoutNeeded:
//callers=com.android.server.wm.WindowState.setDisplayLayoutNeeded:2671
//com.android.server.wm.WindowManagerService.relayoutWindow:2419
//com.android.server.wm.Session.relayout:249 win.setDisplayLayoutNeeded();win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
viewVisibility代表当前View的可见性
mViewVisibility | Vlaue | 含义 |
---|---|---|
VISIBLE | 0x00000000 | 这个视图可见 与#setVisibility和#attr_android:visibility" android:visibility}一起使用。 |
INVISIBLE | 0x00000004 | 这个视图不可见 与#setVisibility和#attr_android:visibility" android:visibility}一起使用。 |
GONE | 0x00000008 | 这个视图是不可见的,它不占用任何空间进行布局 与#setVisibility和#attr_android:visibility" android:visibility}一起使用。 |
5. 第五步 创建Surface图层流程
// We should only relayout if the view is visible, it is a starting window, or the// associated appToken is not hidden.
//只有当视图可见、并且它是STARTING窗口或关联的 appToken 未隐藏时,我们才应该重新布局。final boolean shouldRelayout = viewVisibility == View.VISIBLE &&(win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING|| win.mActivityRecord.isClientVisible());// If we are not currently running the exit animation, we need to see about starting// one.// This must be called before the call to performSurfacePlacement.
//如果我们当前没有运行退出动画,满足下列条件,则需执行退出动画if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {if (DEBUG_VISIBILITY) {
//06-01 10:12:14.228 1890 2256 I WindowManager: Relayout invis Window{8c33950 u0
//NotificationShade}: mAnimatingExit=falseSlog.i(TAG_WM,"Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit);}result |= RELAYOUT_RES_SURFACE_CHANGED;// When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag// in DC#pendingLayoutChanges and update the wallpaper target later.// However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window// when the window is about to exit, so we update the wallpaper target// immediately here. Otherwise this window will be stuck in exiting and its// surface remains on the screen.// TODO(b/189856716): Allow destroying surface even if it belongs to the// keyguard target.if (wallpaperMayMove) {displayContent.mWallpaperController.adjustWallpaperWindows();}
//执行窗口退出动画tryStartExitingAnimation(win, winAnimator);}// Create surfaceControl before surface placement otherwise layout will be skipped// (because WS.isGoneForLayout() is true when there is no surface.
//outSurfaceControl是client端传入的,在ViewRootImpl全局变量中就实例化好了
//http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/view/ViewRootImpl.java#708
//private final SurfaceControl mSurfaceControl = new SurfaceControl();
//所以这个不会为空if (shouldRelayout && outSurfaceControl != null) {try {
//创建图层result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);} catch (Exception e) {displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);ProtoLog.w(WM_ERROR,"Exception thrown when creating surface for client %s (%s). %s",client, win.mAttrs.getTitle(), e);Binder.restoreCallingIdentity(origId);return 0;}}
5.1 WindowManagerService#createSurfaceControl
WindowManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,WindowState win, WindowStateAnimator winAnimator) {if (!win.mHasSurface) {result |= RELAYOUT_RES_SURFACE_CHANGED;}WindowSurfaceController surfaceController;try {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
//创建window对应的surface图层surfaceController = winAnimator.createSurfaceLocked();
...if (surfaceController != null) {surfaceController.getSurfaceControl(outSurfaceControl);ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);} else {
...}
5.2 WindowStateAnimator#createSurfaceLocked
WindowStateAnimator.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowStateAnimator.java
WindowSurfaceController createSurfaceLocked() {final WindowState w = mWin;if (mSurfaceController != null) {return mSurfaceController;}
//设置是否有Surface标志位为falsew.setHasSurface(false);ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this);
//重置图层绘制状态resetDrawState();
//要开始绘制图层了,要先freeze(冻住)住屏幕,等待绘制完成再Unfreeze,这里有个超时机制,即
//冻住屏幕有个最大时间WINDOW_FREEZE_TIMEOUT_DURATION--2000msmService.makeWindowFreezingScreenIfNeededLocked(w);int flags = SurfaceControl.HIDDEN;final WindowManager.LayoutParams attrs = w.mAttrs;
//如果window是加密窗口,则添加此flagif (w.isSecureLocked()) {flags |= SurfaceControl.SECURE;}if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {flags |= SurfaceControl.SKIP_SCREENSHOT;}
//06-01 10:12:18.009 1890 2256 V WindowManager: Creating surface in session
//android.view.SurfaceSession@fcb7984 window WindowStateAnimator{31728a0
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity} format=-1
//flags=4if (DEBUG_VISIBILITY) {Slog.v(TAG, "Creating surface in session "+ mSession.mSurfaceSession + " window " + this+ " format=" + attrs.format + " flags=" + flags);}// Set up surface control with initial size.try {// This can be removed once we move all Buffer Layers to use BLAST.final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
//创建图层----创建WindowSurfaceController,主要是管理图层的,可设置图层位置,大小,是否可见等 mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,flags, this, attrs.type);
//将 Surface 设置为与颜色空间无关。mSurfaceController.setColorSpaceAgnostic(w.getPendingTransaction(),(attrs.privateFlags & LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
//图层创建好了,更新是否有Surface的标志位为truew.setHasSurface(true);
...
//06-01 10:12:18.015 1890 2256 V WindowManager: Got surface:
//Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivit//y)@0xafd3c59, set left=0 top=0if (DEBUG) {Slog.v(TAG, "Got surface: " + mSurfaceController+ ", set left=" + w.getFrame().left + " top=" + w.getFrame().top);}
...mLastHidden = true;
//06-01 10:12:18.015 1890 2256 V WindowManager: Created surface
//WindowStateAnimator{31728a0
//com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}if (DEBUG) Slog.v(TAG, "Created surface " + this);return mSurfaceController;}
5.3 WindowSurfaceController之创建图层
WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,int windowType) {mAnimator = animator;title = name;mService = animator.mService;final WindowState win = animator.mWin;mWindowType = windowType;mWindowSession = win.mSession;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
//创建图层final SurfaceControl.Builder b = win.makeSurface().setParent(win.getSurfaceControl()).setName(name).setFormat(format).setFlags(flags).setMetadata(METADATA_WINDOW_TYPE, windowType).setMetadata(METADATA_OWNER_UID, mWindowSession.mUid).setMetadata(METADATA_OWNER_PID, mWindowSession.mPid).setCallsite("WindowSurfaceController");final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags& WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);if (useBLAST) {b.setBLASTLayer();}mSurfaceControl = b.build();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}
-------------------------------------------------------------------
//http://aospxref.com/android-14.0.0_r2/xref/frameworks/base/core/java/android/view/SurfaceControl.java#857public static class Builder {/*** Begin building a SurfaceControl.*/public Builder() {}/*** Construct a new {@link SurfaceControl} with the set parameters. The builder* remains valid.*/@NonNullpublic SurfaceControl build() {if (mWidth < 0 || mHeight < 0) {throw new IllegalStateException("width and height must be positive or unset");}if ((mWidth > 0 || mHeight > 0) && (isEffectLayer() || isContainerLayer())) {throw new IllegalStateException("Only buffer layers can set a valid buffer size.");}if (mName == null) {Log.w(TAG, "Missing name for SurfaceControl", new Throwable());}if ((mFlags & FX_SURFACE_MASK) == FX_SURFACE_NORMAL) {setBLASTLayer();}return new SurfaceControl(mSession, mName, mWidth, mHeight, mFormat, mFlags, mParent, mMetadata,mLocalOwnerView, mCallsite);}---------------------------------------------------------private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,SurfaceControl parent, SparseIntArray metadata, WeakReference<View> localOwnerView,String callsite)throws OutOfResourcesException, IllegalArgumentException {if (name == null) {throw new IllegalArgumentException("name must not be null");}mName = name;mWidth = w;mHeight = h;mLocalOwnerView = localOwnerView;Parcel metaParcel = Parcel.obtain();long nativeObject = 0;try {if (metadata != null && metadata.size() > 0) {metaParcel.writeInt(metadata.size());for (int i = 0; i < metadata.size(); ++i) {metaParcel.writeInt(metadata.keyAt(i));metaParcel.writeByteArray(ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(metadata.valueAt(i)).array());}metaParcel.setDataPosition(0);}nativeObject = nativeCreate(session, name, w, h, format, flags,parent != null ? parent.mNativeObject : 0, metaParcel);} finally {metaParcel.recycle();}if (nativeObject == 0) {throw new OutOfResourcesException("Couldn't allocate SurfaceControl native object");}assignNativeObject(nativeObject, callsite);}
6. 第六步 刷新界面和更新焦点
// We may be deferring layout passes at the moment, but since the client is interested// in the new out values right now we need to force a layout.mWindowPlacerLocked.performSurfacePlacement(true /* force */);
6.1 WindowSurfacePlacer#performSurfacePlacement 刷新界面和更新焦点
performSurfacePlacement 看方法名,perform surface place,即负责所有窗口的Surface的摆放工作,如何显示位置,大小等等,是WMS中的核心方法
下面这些流程的流程图如上
final void performSurfacePlacement(boolean force) {if (mDeferDepth > 0 && !force) {mDeferredRequests++;return;}
//最大执行6次循环int loopCount = 6;do {mTraversalScheduled = false;performSurfacePlacementLoop();mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);loopCount--;} while (mTraversalScheduled && loopCount > 0);mService.mRoot.mWallpaperActionPending = false;}private void performSurfacePlacementLoop() {
//此方法下面已经有地方将mInLayout置为true,说明已经正在执行performSurfacePlacementLoop方法了if (mInLayout) {
...return;}// TODO(multi-display):final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
//mWaitingForConfig作用是Used to gate application window layout until we have sent the complete configuration.
//当没有完成configuration change的时候,无需做relayout,直到configuration change完成if (defaultDisplay.mWaitingForConfig) {// Our configuration has changed (most likely rotation), but we// don't yet have the complete configuration to report to// applications. Don't do any window layout until we have it.return;}
//屏幕没准备好,直接返回if (!mService.mDisplayReady) {// Not yet initialized, nothing to do.return;}
//对应第一行标志位,表示正在layoutmInLayout = true;
//内存不足时,强制清理mForceRemoves集合,释放内存if (!mService.mForceRemoves.isEmpty()) {// Wait a little bit for things to settle down, and off we go.while (!mService.mForceRemoves.isEmpty()) {final WindowState ws = mService.mForceRemoves.remove(0);Slog.i(TAG, "Force removing: " + ws);ws.removeImmediately();}Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");Object tmp = new Object();synchronized (tmp) {try {tmp.wait(250);} catch (InterruptedException e) {}}}try {
//核心的一步mService.mRoot.performSurfacePlacement();
//标志位置为false,走完上面这步,layout就完成了mInLayout = false;if (mService.mRoot.isLayoutNeeded()) {
//需要layout,并且count<6if (++mLayoutRepeatCount < 6) {requestTraversal();} else {
...}
6.2 RootWindowContainer#performSurfacePlacement
RootWindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
void performSurfacePlacement() {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");try {performSurfacePlacementNoTrace();} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}
6.3 RootWindowContainer#performSurfacePlacementNoTrace - part1
这个方法也很长,当窗口的某些东西改变的时候,就会走到这里,由于太长,我们分开去讲
void performSurfacePlacementNoTrace() {if (DEBUG_WINDOW_TRACE) {
//06-01 10:12:18.016 1890 2256 V WindowManager: performSurfacePlacementInner: entry.
//Called by com.android.server.wm.RootWindowContainer.performSurfacePlacement:765
//com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:177
//com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:126 Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "+ Debug.getCallers(3));}int i;if (mWmService.mFocusMayChange) {mWmService.mFocusMayChange = false;
//更新焦点窗口mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);}mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;mUserActivityTimeout = -1;mObscureApplicationContentOnSecondaryDisplays = false;mSustainedPerformanceModeCurrent = false;mWmService.mTransactionSequence++;// TODO(multi-display): recents animation & wallpaper need support multi-display.final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
//获取WindowSurfacePlacer,这个类专门用于摆放windows和他们的surfaces,
//全系统只有一个实例,在WMS实例化中进行的final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
//要开始进行过渡动画了if (SHOW_LIGHT_TRANSACTIONS) {Slog.i(TAG,">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");}Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
//设置surface参数,start a transaction,对一组 SurfaceControl 的原子更改。
//即通过SurfaceControl来通知native开始一个TransactionmWmService.openSurfaceTransaction();try {
//执行Transaction
//下面详细解释这里applySurfaceChangesTransaction();} catch (RuntimeException e) {Slog.wtf(TAG, "Unhandled exception in Window Manager", e);} finally {
//close surface TransactionmWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);if (SHOW_LIGHT_TRANSACTIONS) {Slog.i(TAG,"<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");}}
...
剩下的分另一半说
6.3.1 RootWindowContainer#applySurfaceChangesTransaction
RootWindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
private void applySurfaceChangesTransaction() {// TODO(multi-display): Support these features on secondary screens.final DisplayContent defaultDc = mDefaultDisplay;final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();final int defaultDw = defaultInfo.logicalWidth;final int defaultDh = defaultInfo.logicalHeight;final SurfaceControl.Transaction t = defaultDc.getSyncTransaction();
...
//mChildren为“List of children for this window container”,
//也就是这个WindowContainer的一系列子windowContainer的集合final int count = mChildren.size();
//循环遍历for (int j = 0; j < count; ++j) {
//获取到这个WindowContainer对应的DisplayContent final DisplayContent dc = mChildren.get(j);
//对这个DisplayContent进行applySurfaceChangesTransactiondc.applySurfaceChangesTransaction();}// Give the display manager a chance to adjust properties like display rotation if it needs// to.mWmService.mDisplayManagerInternal.performTraversal(t);if (t != defaultDc.mSyncTransaction) {SurfaceControl.mergeToGlobalTransaction(t);}}
借用一张图来表示mChildren,mChildren里保存的都是WidowContainer,并且这些WidowContainer按Z值排序,Z值越大越靠前
WindowContainer.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java "List of children for this window container. List is in z-order as the children appear on screen with the top-most window container at the tail of the list."
protected final WindowList<E> mChildren = new WindowList<E>();
6.3.2 DisplayContent#applySurfaceChangesTransaction
DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
void applySurfaceChangesTransaction() {final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;beginHoldScreenUpdate();mTmpUpdateAllDrawn.clear();
...// Perform a layout, if needed.performLayout(true /* initial */, false /* updateInputWindows */);pendingLayoutChanges = 0;Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");try {mDisplayPolicy.beginPostLayoutPolicyLw();
//遍历windows 执行mApplyPostLayoutPolicyforAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);mDisplayPolicy.finishPostLayoutPolicyLw();} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}mInsetsStateController.onPostLayout();mTmpApplySurfaceChangesTransactionState.reset();Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");try {
//遍历windows
//执行mApplySurfaceChangesTransactionforAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}prepareSurfaces();
...finishHoldScreenUpdate();}
6.3.3 DisplayContent#performLayout
DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
void performLayout(boolean initial, boolean updateInputWindows) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performLayout");try {performLayoutNoTrace(initial, updateInputWindows);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}private void performLayoutNoTrace(boolean initial, boolean updateInputWindows) {if (!isLayoutNeeded()) {return;}
//将mLayoutNeeded = false;
//会打印堆栈:06-01 10:12:18.016 1890 2256 W WindowManager: clearLayoutNeeded:
//callers=com.android.server.wm.DisplayContent.performLayoutNoTrace:5051
//com.android.server.wm.DisplayContent.performLayout:5041
//com.android.server.wm.DisplayContent.applySurfaceChangesTransaction:4963 clearLayoutNeeded();if (DEBUG_LAYOUT) {
//06-01 10:12:18.016 1890 2256 V WindowManager: performLayout: dw=3840 dh=7104 Slog.v(TAG, "-------------------------------------");Slog.v(TAG, "performLayout: dw=" + mDisplayInfo.logicalWidth+ " dh=" + mDisplayInfo.logicalHeight);}int seq = mLayoutSeq + 1;if (seq < 0) seq = 0;mLayoutSeq = seq;mTmpInitial = initial;// First perform layout of any root windows (not attached to another window).
//首先给所有windows执行layout,mPerformLayout稍后解释forAllWindows(mPerformLayout, true /* traverseTopToBottom */);// Now perform layout of attached windows, which usually depend on the position of the// window they are attached to. XXX does not deal with windows that are attached to windows// that are themselves attached.
//给所有attached windows执行layout操作forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);// Window frames may have changed. Tell the input dispatcher about it.
//更新input windowmInputMonitor.setUpdateInputWindowsNeededLw();if (updateInputWindows) {mInputMonitor.updateInputWindowsLw(false /*force*/);}}
DisplayContent# mPerformLayout赋值如下:
DisplayContent.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
private final Consumer<WindowState> mPerformLayout = w -> {if (w.mLayoutAttached) {return;}// Don't do layout of a window if it is not visible, or soon won't be visible, to avoid// wasting time and funky changes while a window is animating away.final boolean gone = w.isGoneForLayout();if (DEBUG_LAYOUT) {Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame+ " config reported=" + w.isLastConfigReportedToClient());final ActivityRecord activity = w.mActivityRecord;if (gone) Slog.v(TAG, " GONE: mViewVisibility=" + w.mViewVisibility+ " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()+ " visibleRequested=" + (activity != null && activity.isVisibleRequested())+ " parentHidden=" + w.isParentWindowHidden());else Slog.v(TAG, " VIS: mViewVisibility=" + w.mViewVisibility+ " mRelayoutCalled=" + w.mRelayoutCalled + " visible=" + w.mToken.isVisible()+ " visibleRequested=" + (activity != null && activity.isVisibleRequested())+ " parentHidden=" + w.isParentWindowHidden());}// If this view is GONE, then skip it -- keep the current frame, and let the caller know// so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,// since that means "perform layout as normal, just don't display").if (!gone || !w.mHaveFrame || w.mLayoutNeeded) {if (mTmpInitial) {w.resetContentChanged();}w.mSurfacePlacementNeeded = true;w.mLayoutNeeded = false;final boolean firstLayout = !w.isLaidOut();
// Called for each window attached to the window manager as layout is proceeding
//在布局进行时调用附加到窗口管理器的每个窗口getDisplayPolicy().layoutWindowLw(w, null, mDisplayFrames);w.mLayoutSeq = mLayoutSeq;// If this is the first layout, we need to initialize the last frames and inset values,// as otherwise we'd immediately cause an unnecessary resize.if (firstLayout) {// The client may compute its actual requested size according to the first layout,// so we still request the window to resize if the current frame is empty.if (!w.getFrame().isEmpty()) {w.updateLastFrames();}w.onResizeHandled();}if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.getFrame()+ " mParentFrame=" + w.getParentFrame()+ " mDisplayFrame=" + w.getDisplayFrame());}};
DisplayPolicy#layoutWindowLw
public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) {
...mWindowLayout.computeFrames(attrs, win.getInsetsState(), displayFrames.mDisplayCutoutSafe,win.getBounds(), win.getWindowingMode(), requestedWidth, requestedHeight,win.getRequestedVisibleTypes(), win.mGlobalScale, sTmpClientFrames);win.setFrames(sTmpClientFrames, win.mRequestedWidth, win.mRequestedHeight);}
DisplayContent# mApplyPostLayoutPolicy赋值如下:
private final Consumer<WindowState> mApplyPostLayoutPolicy =w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), mImeLayeringTarget);
DisplayPolicy.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
/*** Called following layout of all window to apply policy to each window.** @param win The window being positioned.* @param attrs The LayoutParams of the window.* @param attached For sub-windows, the window it is attached to. Otherwise null.*/public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget) {
DisplayContent# mApplySurfaceChangesTransaction赋值如下
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;final boolean obscuredChanged = w.mObscured !=mTmpApplySurfaceChangesTransactionState.obscured;final RootWindowContainer root = mWmService.mRoot;// Update effect.w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;if (!mTmpApplySurfaceChangesTransactionState.obscured) {final boolean isDisplayed = w.isDisplayed();if (isDisplayed && w.isObscuringDisplay()) {// This window completely covers everything behind it, so we want to leave all// of them as undimmed (for performance reasons).mObscuringWindow = w;mTmpApplySurfaceChangesTransactionState.obscured = true;}final boolean displayHasContent = root.handleNotObscuredLocked(w,mTmpApplySurfaceChangesTransactionState.obscured,mTmpApplySurfaceChangesTransactionState.syswin);if (!mTmpApplySurfaceChangesTransactionState.displayHasContent&& !getDisplayPolicy().isWindowExcludedFromContent(w)) {mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent;}if (w.mHasSurface && isDisplayed) {if ((w.mAttrs.flags & FLAG_KEEP_SCREEN_ON) != 0) {mTmpHoldScreenWindow = w;} else if (w == mLastWakeLockHoldingWindow) {ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,"handleNotObscuredLocked: %s was holding screen wakelock but no longer "+ "has FLAG_KEEP_SCREEN_ON!!! called by%s",w, Debug.getCallers(10));}final int type = w.mAttrs.type;if (type == TYPE_SYSTEM_DIALOG|| type == TYPE_SYSTEM_ERROR|| (type == TYPE_NOTIFICATION_SHADE&& mWmService.mPolicy.isKeyguardShowing())) {mTmpApplySurfaceChangesTransactionState.syswin = true;}if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0&& w.mAttrs.preferredRefreshRate != 0) {mTmpApplySurfaceChangesTransactionState.preferredRefreshRate= w.mAttrs.preferredRefreshRate;}mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing|= w.mAttrs.preferMinimalPostProcessing;mTmpApplySurfaceChangesTransactionState.disableHdrConversion|= !(w.mAttrs.isHdrConversionEnabled());final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy().getPreferredModeId(w);if (w.getWindowingMode() != WINDOWING_MODE_PINNED&& mTmpApplySurfaceChangesTransactionState.preferredModeId == 0&& preferredModeId != 0) {mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;}final float preferredMinRefreshRate = getDisplayPolicy().getRefreshRatePolicy().getPreferredMinRefreshRate(w);if (mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate == 0&& preferredMinRefreshRate != 0) {mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate =preferredMinRefreshRate;}final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy().getPreferredMaxRefreshRate(w);if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0&& preferredMaxRefreshRate != 0) {mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate =preferredMaxRefreshRate;}}}if (obscuredChanged && w.isVisible() && mWallpaperController.isWallpaperTarget(w)) {// This is the wallpaper target and its obscured state changed... make sure the// current wallpaper's visibility has been updated accordingly.mWallpaperController.updateWallpaperVisibility();}w.handleWindowMovedIfNeeded();final WindowStateAnimator winAnimator = w.mWinAnimator;//Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");w.resetContentChanged();// Moved from updateWindowsAndWallpaperLocked().if (w.mHasSurface) {// Take care of the window being ready to display.final boolean committed = winAnimator.commitFinishDrawingLocked();if (isDefaultDisplay && committed) {if (w.hasWallpaper()) {ProtoLog.v(WM_DEBUG_WALLPAPER,"First draw done in potential wallpaper target %s", w);mWallpaperMayChange = true;pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;if (DEBUG_LAYOUT_REPEATS) {surfacePlacer.debugLayoutRepeats("wallpaper and commitFinishDrawingLocked true",pendingLayoutChanges);}}}}final ActivityRecord activity = w.mActivityRecord;if (activity != null && activity.isVisibleRequested()) {activity.updateLetterboxSurface(w);final boolean updateAllDrawn = activity.updateDrawnWindowStates(w);if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(activity)) {mTmpUpdateAllDrawn.add(activity);}}w.updateResizingWindowIfNeeded();};
在这个过程中会通过commitFinishDrawingLocked去检查当前窗口的mDrawState情况。Surface的mDrawState的绘制状态是由ViewRootImpl通过Session调用到WMS端,然后在WMS端设置的。
当此window窗口的mDrawState变化状态从NO_SURFACE -> DRAW_PENDING -> COMMIT_DRAW_PENDING -> HAS_DRAWN-> READY_TO_SHOW,然后才会将图层置为可见状态,设置为可见的log如下:
05-25 10:56:31.956 1915 1973 V WindowManager: performShow on Window{f4647f5 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=false tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4372 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0
05-25 10:56:31.962 1915 1973 V WindowManager: Showing Window{f4647f5 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=true tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4387 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0
大概log如下:
06-01 10:12:18.006 1890 2256 V WindowManager: Relayout Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: viewVisibility=0 req=7104x3840 {(0,0)(fillxfill) sim={adjust=resize forwardNavigation} ty=BASE_APPLICATION wanim=0x10302f2
06-01 10:12:18.006 1890 2256 V WindowManager: fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
06-01 10:12:18.006 1890 2256 V WindowManager: pfl=NO_MOVE_ANIMATION FORCE_DRAW_STATUS_BAR_BACKGROUND HIDE_NON_SYSTEM_OVERLAY_WINDOWS USE_BLAST FIT_INSETS_CONTROLLED
06-01 10:12:18.006 1890 2256 V WindowManager: vsysui=LIGHT_STATUS_BAR LIGHT_NAVIGATION_BAR
06-01 10:12:18.006 1890 2256 V WindowManager: apr=LIGHT_STATUS_BARS LIGHT_NAVIGATION_BARS
06-01 10:12:18.006 1890 2256 V WindowManager: bhv=DEFAULT
06-01 10:12:18.006 1890 2256 V WindowManager: fitSides=}
06-01 10:12:18.008 1890 2256 W WindowManager: setLayoutNeeded: callers=com.android.server.wm.WindowState.setDisplayLayoutNeeded:2671 com.android.server.wm.WindowManagerService.relayoutWindow:2419 com.android.server.wm.Session.relayout:249
06-01 10:12:18.009 1890 2256 V WindowManager: Creating surface in session android.view.SurfaceSession@fcb7984 window WindowStateAnimator{31728a0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity} format=-1 flags=4
06-01 10:12:18.015 1890 2256 V WindowManager: Got surface: Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivity)/@0xafd3c59, set left=0 top=0
06-01 10:12:18.015 1890 2256 I WindowManager: >>> OPEN TRANSACTION createSurfaceLocked
06-01 10:12:18.015 1890 2256 I WindowManager: SURFACE CREATE pos=(0,0) HIDE: Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.015 1890 2256 V WindowManager: Created surface WindowStateAnimator{31728a0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.016 1890 2256 V WindowManager: performSurfacePlacementInner: entry. Called by com.android.server.wm.RootWindowContainer.performSurfacePlacement:765 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:177 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:126
06-01 10:12:18.016 1890 2256 I WindowManager: >>> OPEN TRANSACTION performLayoutAndPlaceSurfaces
...
06-01 10:12:18.020 1890 2256 I WindowManager: <<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces
06-01 10:12:18.021 1890 2256 E WindowManager: performSurfacePlacementInner exit
06-01 10:12:18.021 1890 2256 V WindowManager: Already visible and does not turn on screen, skip preparing: Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}
06-01 10:12:18.022 1890 2256 W WindowManager: Moving IM target from null to null since mInputMethodWindow is null
06-01 10:12:18.022 1890 2256 V WindowManager: Win Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: isDrawn=false, animating=false
06-01 10:12:18.022 1890 2256 V WindowManager: Not displayed: s=Surface(name=com.android.settings/com.android.settings.homepage.SettingsHomepageActivity)/@0xafd3c59 pv=true mDrawState=1 ph=false th=true a=false
06-01 10:12:18.022 1890 2256 V WindowManager: Relayout complete Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: outFrames=ClientWindowFrames{frame=[0,0][7104,3840] display=[0,0][7104,3840] parentFrame=[0,0][0,0]}
06-01 10:12:18.214 1890 1950 I WindowManager: commitFinishDrawingLocked: Window{d8b1e28 u0 Splash Screen com.android.settings} cur mDrawState=HAS_DRAWN
06-01 10:12:18.214 1890 1950 D ActivityTaskManager: updateWindows: starting Window{d8b1e28 u0 Splash Screen com.android.settings} isOnScreen=true allDrawn=false freezingScreen=false
06-01 10:12:18.214 1890 1950 V WindowManager: Resizing Window{d8b1e28 u0 Splash Screen com.android.settings}: configChanged=false last=Rect(0, 0 - 7104, 3840) frame=Rect(0, 0 - 7104, 3840)
06-01 10:12:18.215 1890 1950 V WindowManager: performShow on Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=false tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4372 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0
...
06-01 10:12:18.220 1890 1950 V WindowManager: Win Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: isDrawn=true, animating=true06-01 10:12:18.228 1890 1950 V WindowManager: Showing Window{8d0d088 u0 com.android.settings/com.android.settings.homepage.SettingsHomepageActivity}: mDrawState=READY_TO_SHOW readyForDisplay=true starting=false during animation: policyVis=true parentHidden=false tok.visibleRequested=true tok.visible=true animating=true tok animating=false Callers=com.android.server.wm.WindowState.performShowLocked:4387 com.android.server.wm.WindowStateAnimator.commitFinishDrawingLocked:256 com.android.server.wm.DisplayContent.lambda$new$8:1082 com.android.server.wm.DisplayContent.$r8$lambda$NJwM1ysKPNyOazqyI2QXlp2I4yA:0