APP端添加窗口->Srv端添加窗口
// app端获取wms
mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
// app端调用wms 会话进行addview完成窗口添加
mWindowManager.addView(mWindowViewLayout, mLayoutParams);
看代码,串一下流程
流程图汇总
从图中可以看到,整体app端到srv端的窗口添加是通过session调用过去的,通过app端的viewRootImpl
;
而Srv端的添加逻辑主要就是在wms中的addWindow了;这里详细展开看下
srv端代码展开分析
public int addWindow(Session session, IWindow client, LayoutParams attrs, int viewVisibility,
int displayId, int requestUserId, @InsetsType int requestedVisibleTypes,
InputChannel outInputChannel, InsetsState outInsetsState,
InsetsSourceControl.Array outActiveControls, Rect outAttachedFrame,
float[] outSizeCompatScale) {
outActiveControls.set(null);
int[] appOp = new int[1];
final boolean isRoundedCornerOverlay = (attrs.privateFlags
& PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
appOp);
if (res != ADD_OKAY) {
return res;
}
WindowState parentWindow = null;
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
final int type = attrs.type;
synchronized (mGlobalLock) {
if (!mDisplayReady) {
throw new IllegalStateException("Display has not been initialialized");
}
final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
if (displayContent == null) {
ProtoLog.w(WM_ERROR, "Attempted to add window to a display that does "
+ "not exist: %d. Aborting.", displayId);
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
if (!displayContent.hasAccess(session.mUid)) {
ProtoLog.w(WM_ERROR,
"Attempted to add window to a display for which the application "
+ "does not have access: %d. Aborting.",
displayContent.getDisplayId());
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
if (mWindowMap.containsKey(client.asBinder())) {
ProtoLog.w(WM_ERROR, "Window %s is already added", client);
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
这里去找了下是否存在 父window,条件是为当前add的window类型是什么暂时不清楚,但是不在这个范围内
具体window类型定义在此文件中:frameworks/base/core/java/android/view/WindowManager.java
这里的限定范围是 (1000) - 1999;
因此这里并没有对parentWindow进行赋值,此时仍然是null;
if (type >= FIRST_SUB_WINDOW&& type <= LAST_SUB_WINDOW) {
parentWindow = windowForClientLocked(null, attrs.token, false);
if (parentWindow == null) {
ProtoLog.w(WM_ERROR, "Attempted to add window with token that is not a window: "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
if (parentWindow.mAttrs.type >= FIRST_SUB_WINDOW
&& parentWindow.mAttrs.type <= LAST_SUB_WINDOW) {
ProtoLog.w(WM_ERROR, "Attempted to add window with token that is a sub-window: "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
}
if (type == TYPE_PRIVATE_PRESENTATION && !displayContent.isPrivate()) {
ProtoLog.w(WM_ERROR,
"Attempted to add private presentation window to a non-private display. "
+ "Aborting.");
return WindowManagerGlobal.ADD_PERMISSION_DENIED;
}
if (type == TYPE_PRESENTATION && !displayContent.getDisplay().isPublicPresentation()) {
ProtoLog.w(WM_ERROR,
"Attempted to add presentation window to a non-suitable display. "
+ "Aborting.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
int userId = UserHandle.getUserId(session.mUid);
if (requestUserId != userId) {
try {
mAmInternal.handleIncomingUser(callingPid, callingUid, requestUserId,
false /*allowAll*/, ALLOW_NON_FULL, null, null);
} catch (Exception exp) {
ProtoLog.w(WM_ERROR, "Trying to add window with invalid user=%d",
requestUserId);
return WindowManagerGlobal.ADD_INVALID_USER;
}
// It's fine to use this userId
userId = requestUserId;
}
hasParent为false;
ActivityRecord activity = null;
final boolean hasParent = parentWindow != null;
// Use existing parent window token for child windows since they go in the same token
// as there parent window so we can apply the same policy on them.
对子窗口使用现有的父窗口令牌,因为它们与父窗口使用相同的令牌,
因此我们可以对它们应用相同的策略
对于当前添加的悬浮窗,并没有一个parentwindow,因此这里使用的是传入的layout的attrs对应的token
去通过getWindowToken 拿到map中是否包含了这个token,显然是没有的,所以这里token是null;
真正的创建token还在下面
WindowToken token = displayContent.getWindowToken(
hasParent ? parentWindow.mAttrs.token : attrs.token);
// If this is a child window, we want to apply the same type checking rules as the
// parent window type.
final int rootType = hasParent ? parentWindow.mAttrs.type : type;
boolean addToastWindowRequiresToken = false;
final IBinder windowContextToken = attrs.mWindowContextToken;
if (token == null) {
if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
rootType, attrs.token, attrs.packageName)) {
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
if (hasParent) {
// Use existing parent window token for child windows.
token = parentWindow.mToken;
} else if (mWindowContextListenerController.hasListener(windowContextToken)) {
// Respect the window context token if the user provided it.
final IBinder binder = attrs.token != null ? attrs.token : windowContextToken;
final Bundle options = mWindowContextListenerController
.getOptions(windowContextToken);
token = new WindowToken.Builder(this, binder, type)
.setDisplayContent(displayContent)
.setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
.setRoundedCornerOverlay(isRoundedCornerOverlay)
.setFromClientToken(true)
.setOptions(options)
.build();
} else {
这里把传入的client作为参数,转为binder对象,并new了一个window token,把这个binder作为关键信息
传了进去;这里的client是函数的入参,类型为IWindow client;
追根溯源,其是viewrootImpl类传入的一个成员变量,是一个很重要的角色,是一个binder的stub对象,可以和
server端进行通信;
final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
token = new WindowToken.Builder(this, binder, type)
.setDisplayContent(displayContent)
.setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
.setRoundedCornerOverlay(isRoundedCornerOverlay)
.build();
}
} else if (rootType >= FIRST_APPLICATION_WINDOW
&& rootType <= LAST_APPLICATION_WINDOW) {
activity = token.asActivityRecord();
if (activity == null) {
ProtoLog.w(WM_ERROR, "Attempted to add window with non-application token "
+ ".%s Aborting.", token);
return WindowManagerGlobal.ADD_NOT_APP_TOKEN;
} else if (activity.getParent() == null) {
ProtoLog.w(WM_ERROR, "Attempted to add window with exiting application token "
+ ".%s Aborting.", token);
return WindowManagerGlobal.ADD_APP_EXITING;
} else if (type == TYPE_APPLICATION_STARTING) {
if (activity.mStartingWindow != null) {
ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
+ "token with already existing starting window");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
if (activity.mStartingData == null) {
ProtoLog.w(WM_ERROR, "Attempted to add starting window to "
+ "token but already cleaned");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
}
} else if (rootType == TYPE_INPUT_METHOD) {
if (token.windowType != TYPE_INPUT_METHOD) {
ProtoLog.w(WM_ERROR, "Attempted to add input method window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (rootType == TYPE_VOICE_INTERACTION) {
if (token.windowType != TYPE_VOICE_INTERACTION) {
ProtoLog.w(WM_ERROR, "Attempted to add voice interaction window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (rootType == TYPE_WALLPAPER) {
if (token.windowType != TYPE_WALLPAPER) {
ProtoLog.w(WM_ERROR, "Attempted to add wallpaper window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (rootType == TYPE_ACCESSIBILITY_OVERLAY) {
if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
ProtoLog.w(WM_ERROR,
"Attempted to add Accessibility overlay window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (type == TYPE_TOAST) {
// Apps targeting SDK above N MR1 cannot arbitrary add toast windows.
addToastWindowRequiresToken = doesAddToastWindowRequireToken(attrs.packageName,
callingUid, parentWindow);
if (addToastWindowRequiresToken && token.windowType != TYPE_TOAST) {
ProtoLog.w(WM_ERROR, "Attempted to add a toast window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (type == TYPE_QS_DIALOG) {
if (token.windowType != TYPE_QS_DIALOG) {
ProtoLog.w(WM_ERROR, "Attempted to add QS dialog window with bad token "
+ "%s. Aborting.", attrs.token);
return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
}
} else if (token.asActivityRecord() != null) {
ProtoLog.w(WM_ERROR, "Non-null activity for system window of rootType=%d",
rootType);
// It is not valid to use an app token with other system types; we will
// instead make a new token for it (as if null had been passed in for the token).
attrs.token = null;
token = new WindowToken.Builder(this, client.asBinder(), type)
.setDisplayContent(displayContent)
.setOwnerCanManageAppTokens(session.mCanAddInternalSystemWindow)
.build();
}
这里是很关键的地方,创建了这个windowtoken对应的windowState,
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], attrs, viewVisibility, session.mUid, userId,
session.mCanAddInternalSystemWindow);
if (win.mDeathRecipient == null) {
// Client has apparently died, so there is no reason to
// continue.
ProtoLog.w(WM_ERROR, "Adding window client %s"
+ " that is dead, aborting.", client.asBinder());
return WindowManagerGlobal.ADD_APP_EXITING;
}
if (win.getDisplayContent() == null) {
ProtoLog.w(WM_ERROR, "Adding window to Display that has been removed.");
return WindowManagerGlobal.ADD_INVALID_DISPLAY;
}
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
displayPolicy.adjustWindowParamsLw(win, win.mAttrs);
attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), callingUid, callingPid);
attrs.inputFeatures = sanitizeSpyWindow(attrs.inputFeatures, win.getName(), callingUid,
callingPid);
win.setRequestedVisibleTypes(requestedVisibleTypes);
res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
if (res != ADD_OKAY) {
return res;
}
这里很关键,创建了对应的inputChannel链路;outInputChannel是入参,有viewrootImpl创建的;
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
// If adding a toast requires a token for this app we always schedule hiding
// toast windows to make sure they don't stick around longer then necessary.
// We hide instead of remove such windows as apps aren't prepared to handle
// windows being removed under them.
//
// If the app is older it can add toasts without a token and hence overlay
// other apps. To be maximally compatible with these apps we will hide the
// window after the toast timeout only if the focused window is from another
// UID, otherwise we allow unlimited duration. When a UID looses focus we
// schedule hiding all of its toast windows.
if (type == TYPE_TOAST) {
if (!displayContent.canAddToastWindowForUid(callingUid)) {
ProtoLog.w(WM_ERROR, "Adding more than one toast window for UID at a time.");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
// Make sure this happens before we moved focus as one can make the
// toast focusable to force it not being hidden after the timeout.
// Focusable toasts are always timed out to prevent a focused app to
// show a focusable toasts while it has focus which will be kept on
// the screen after the activity goes away.
if (addToastWindowRequiresToken
|| (attrs.flags & FLAG_NOT_FOCUSABLE) == 0
|| displayContent.mCurrentFocus == null
|| displayContent.mCurrentFocus.mOwnerUid != callingUid) {
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
win.mAttrs.hideTimeoutMilliseconds);
}
}
// Switch to listen to the {@link WindowToken token}'s configuration changes when
// adding a window to the window context. Filter sub window type here because the sub
// window must be attached to the parent window, which is attached to the window context
// created window token.
if (!win.isChildWindow()
&& mWindowContextListenerController.hasListener(windowContextToken)) {
final int windowContextType = mWindowContextListenerController
.getWindowType(windowContextToken);
final Bundle options = mWindowContextListenerController
.getOptions(windowContextToken);
if (type != windowContextType) {
ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
+ " LayoutParams.type should match! Type from LayoutParams is %d,"
+ " but type from WindowContext is %d", type, windowContextType);
// We allow WindowProviderService to add window other than windowContextType,
// but the WindowProviderService won't be associated with the window's
// WindowToken.
if (!isWindowProviderService(options)) {
return WindowManagerGlobal.ADD_INVALID_TYPE;
}
} else {
mWindowContextListenerController.updateContainerForWindowContextListener(
windowContextToken, token);
}
}
// From now on, no exceptions or errors allowed!
if (displayContent.mCurrentFocus == null) {
displayContent.mWinAddedSinceNullFocus.add(win);
}
if (excludeWindowTypeFromTapOutTask(type)) {
displayContent.mTapExcludedWindows.add(win);
}
这里终于将当前windowState的信息放到了mWindowMap中,key是client(也就是viewrootImpl的binder stub)
后面就先不看了,到此为止
win.attach();
mWindowMap.put(client.asBinder(), win);
win.initAppOpsState();
。。。。
}
Binder.restoreCallingIdentity(origId);
return res;
}
老大一堆,用一句话总结就是,完成mWindowMap
变量的成员添加,key是app端的binder stub,value是创建出来的windowState
小总结一下
对于add到server端的一个window来说,addWindow时主要完成以下4个关键步骤
- 创建这个窗口的WindowToken,并将其挂载到层级结构树中(一般windowTokend会挂载到leaf下,作为倒数第二层,最后一层往往是个windowState对象)
- 创建一个WindowState对象,与当前window进行绑定(使用当前window的信息进行创建)
- 将当前窗口的input链路进行打通,通过openInputChannel完成input链路初始化,创建了对应的 Pair<socket,socket>
- 将当前窗口的windowState挂载到层级结构树中,使其结构完成;
relayout
概述
应用端发起addwindow到wms,wms创建windowtoken和windowstate,并挂载到了层级结构树上面;
此时应用端会发起relayoutWindow的操作
其实上面addWindow时,也只是new出来两个 windowToken和windowState,此时两者只是初始化,并没有surface进行绘制的能力;
其实真正进行surfaceControl创建就是在这个relayout过程中;
代码
绘制阶段
5个绘制阶段,表示当前window所处的绘制状态
应用调用到wms的relayout的过程和之前的 addWindow类似,都是通过viewRootImpl中的session的binder调用过来的,具体应用侧的流程还没有梳理,大概就是doTraversal-> performTraversals的过程;下面主要看下srv端的逻辑
代码梳理
创建surfacecontrol
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags,
ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration,
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
InsetsSourceControl[] outActiveControls, Bundle outSyncIdBundle) {
。。。
// 1. 通过刚刚存储的变量,拿到对应的binder和windowstate
final WindowState win = windowForClientLocked(session, client, false);
。。。
// 2. 创建surfacecontrol
if (shouldRelayout) {
try {
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
。。。
}
}
// 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.
// 3. performSurfacePlacement进行relayout操作!!!!!
mWindowPlacerLocked.performSurfacePlacement(true /* force */);
//ignore
if (!win.isGoneForLayout()) {
win.mResizedWhileGone = false;
}
// 4. 相关配置数据
win.fillClientWindowFramesAndConfiguration(outFrames, mergedConfiguration,
false /* useLatestConfig */, shouldRelayout);
outInsetsState.set(win.getCompatInsetsState(), win.isClientLocal());
。。。
}
。。。
return result;
}
finishDraw
看finishDraw之前,回顾下刚刚看的逻辑
整体上就是从app端通过viewrootimpl到session服务端,完成前期的调用,最后是finishDraw的调用;
我们对finishDraw的流程进行分析
app端的就先不看了,从图中可以看到整体的调用链路,也可以通过抓trace来看调用栈。
我们直接看server端,在finishdraw中的处理。
WindowManagerService.java
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize();
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
这里通过刚刚addwindow保存的信息,直接拿到对应窗口的相关信息;
WindowState win = windowForClientLocked(session, client, false);
ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
mWindowPlacerLocked.requestTraversal();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
看windowState中具体的finishDrawing是怎么处理的;
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction, int syncSeqId) {
// 前面这些暂时忽略,是转屏的逻辑,以及activityRecord的逻辑,这里我们先看一个普通的systemWindow的链路;
if (mOrientationChangeRedrawRequestTime > 0) {
final long duration =
SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
Slog.i(TAG, "finishDrawing of orientation change: " + this + " " + duration + "ms");
mOrientationChangeRedrawRequestTime = 0;
} else if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0
&& mActivityRecord.findMainWindow() == this) {
final long duration =
SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime;
Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
mActivityRecord.finishOrAbortReplacingWindow();
}
if (mActivityRecord != null && mAttrs.type == TYPE_APPLICATION_STARTING) {
mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger()
.notifyStartingWindowDrawn(mActivityRecord);
}
final boolean syncActive = mPrepareSyncSeqId > 0;
final boolean syncStillPending = syncActive && mPrepareSyncSeqId > syncSeqId;
if (syncStillPending && postDrawTransaction != null) {
ProtoLog.d(WM_DEBUG_SYNC_ENGINE, "Got a buffer for request id=%d but latest request is"
+ " id=%d. Since the buffer is out-of-date, drop it. win=%s", syncSeqId,
mPrepareSyncSeqId, this);
// sync is waiting for a newer seqId, so this buffer is obsolete and can be dropped
// to free up the buffer queue.
dropBufferFrom(postDrawTransaction);
}
final boolean hasSyncHandlers = executeDrawHandlers(postDrawTransaction, syncSeqId);
boolean skipLayout = false;
boolean layoutNeeded = false;
// Control the timing to switch the appearance of window with different rotations.
final AsyncRotationController asyncRotationController =
mDisplayContent.getAsyncRotationController();
if (asyncRotationController != null
&& asyncRotationController.handleFinishDrawing(this, postDrawTransaction)) {
// Consume the transaction because the controller will apply it with fade animation.
// Layout is not needed because the window will be hidden by the fade leash.
postDrawTransaction = null;
skipLayout = true;
} else if (syncActive) {
// Currently in a Sync that is using BLAST.
if (!syncStillPending) {
layoutNeeded = onSyncFinishedDrawing();
}
if (postDrawTransaction != null) {
mSyncTransaction.merge(postDrawTransaction);
// Consume the transaction because the sync group will merge it.
postDrawTransaction = null;
}
} else if (useBLASTSync()) {
// Sync that is not using BLAST
layoutNeeded = onSyncFinishedDrawing();
}
// 核心逻辑在这里:WindowStateAnimator中的finishDrawingLocked
layoutNeeded |=
mWinAnimator.finishDrawingLocked(postDrawTransaction, mClientWasDrawingForSync);
mClientWasDrawingForSync = false;
// We always want to force a traversal after a finish draw for blast sync.
return !skipLayout && (hasSyncHandlers || layoutNeeded);
}
WindowStateAnimator.java
这个类也是挺关键的,很多核心逻辑都在这里面
它与WindowState是一一对应的(WindowState成员变量),是用来控制 动画 和 surface操作的;很关键只能说
boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
boolean forceApplyNow) {
final boolean startingWindow =
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
if (startingWindow) {
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s",
mWin, drawStateToString());
}
boolean layoutNeeded = false;
// 最开始这里肯定是 DRAW_PENDING,追一下赋值:是在reset的时候==createSurface的时候;
if (mDrawState == DRAW_PENDING) {
ProtoLog.v(WM_DEBUG_DRAW,
"finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin,
mSurfaceController);
if (startingWindow) {
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin);
}
// 这里直接就下一个阶段~ 直接到commit draw pending,实际上还没有提交,只是先把状态切换过来了;
mDrawState = COMMIT_DRAW_PENDING;
layoutNeeded = true;
}
if (postDrawTransaction != null) {
// If there is no surface, the last draw was for the previous surface. We don't want to
// wait until the new surface is shown and instead just apply the transaction right
// away.
if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) {
mPostDrawTransaction.merge(postDrawTransaction);
} else {
mWin.getSyncTransaction().merge(postDrawTransaction);
}
layoutNeeded = true;
}
return layoutNeeded;
}
到这里发现没什么其他逻辑了,那就返回;回到WindowManagerService.java中finishDrawingWindow
WindowManagerService.java
void finishDrawingWindow(Session session, IWindow client,
@Nullable SurfaceControl.Transaction postDrawTransaction, int seqId) {
if (postDrawTransaction != null) {
postDrawTransaction.sanitize();
}
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
这里通过刚刚addwindow保存的信息,直接拿到对应窗口的相关信息;
WindowState win = windowForClientLocked(session, client, false);
ProtoLog.d(WM_DEBUG_ADD_REMOVE, "finishDrawingWindow: %s mDrawState=%s",
win, (win != null ? win.mWinAnimator.drawStateToString() : "null"));
// 这里看完了,往下走
if (win != null && win.finishDrawing(postDrawTransaction, seqId)) {
if (win.hasWallpaper()) {
win.getDisplayContent().pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
win.setDisplayLayoutNeeded();
// 接下来我们看这里,调用WindowPlacerLocked(WindowSurfacePlacer类窗口surface放置者, 听听这明着)的 requestTraversal方法(请求遍历)!
mWindowPlacerLocked.requestTraversal();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
WindowSurfacePlacer.java
这里看到窗口surface放置类中,直接调用了service的AnimationHandler post出去一个放置任务!
void requestTraversal() {
if (mTraversalScheduled) {
return;
}
// Set as scheduled even the request will be deferred because mDeferredRequests is also
// increased, then the end of deferring will perform the request.
mTraversalScheduled = true;
if (mDeferDepth > 0) {
mDeferredRequests++;
if (DEBUG) Slog.i(TAG, "Defer requestTraversal " + Debug.getCallers(3));
return;
}
// mPerformSurfacePlacement:
// private final Traverser mPerformSurfacePlacement = new Traverser();继承Runnable
// 就是个Runnable!
mService.mAnimationHandler.post(mPerformSurfacePlacement);
}
frameworks/base/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
post的调用,内部的runnable需要追踪一下,这里实际的finishDraw非常关键的逻辑
performSurfacePlacement-》performSurfacePlacement-》performSurfacePlacementLoop
private class Traverser implements Runnable {
@Override
public void run() {
synchronized (mService.mGlobalLock) {
performSurfacePlacement();
}
}
}
final void performSurfacePlacement() {
performSurfacePlacement(false /* force */);
}
final void performSurfacePlacement(boolean force) {
if (mDeferDepth > 0 && !force) {
mDeferredRequests++;
return;
}
int loopCount = 6;
do {
mTraversalScheduled = false;
performSurfacePlacementLoop();
mService.mAnimationHandler.removeCallbacks(mPerformSurfacePlacement);
loopCount--;
} while (mTraversalScheduled && loopCount > 0);
mService.mRoot.mWallpaperActionPending = false;
}
private void performSurfacePlacementLoop() {
if (mInLayout) {
if (DEBUG) {
throw new RuntimeException("Recursive call!");
}
Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout. Callers="
+ Debug.getCallers(3));
return;
}
// TODO(multi-display):
final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
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;
}
mInLayout = true;
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 {
// 调用到这里,是RootWindowContainer的方法
mService.mRoot.performSurfacePlacement();
mInLayout = false;
if (mService.mRoot.isLayoutNeeded()) {
if (++mLayoutRepeatCount < 6) {
requestTraversal();
} else {
Slog.e(TAG, "Performed 6 layouts in a row. Skipping");
mLayoutRepeatCount = 0;
}
} else {
mLayoutRepeatCount = 0;
}
if (mService.mWindowsChanged && !mService.mWindowChangeListeners.isEmpty()) {
mService.mH.removeMessages(REPORT_WINDOWS_CHANGE);
mService.mH.sendEmptyMessage(REPORT_WINDOWS_CHANGE);
}
} catch (RuntimeException e) {
mInLayout = false;
Slog.wtf(TAG, "Unhandled exception while laying out windows", e);
}
}
RootWindowContainer.java: performSurfacePlacement -> performSurfacePlacementNoTrace-》applySurfaceChangesTransaction
void performSurfacePlacement() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement");
try {
performSurfacePlacementNoTrace();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
void performSurfacePlacementNoTrace() {
。。。。。。。
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges");
mWmService.openSurfaceTransaction();
try {
applySurfaceChangesTransaction();
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (SHOW_LIGHT_TRANSACTIONS) {
Slog.i(TAG,
"<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
}
}
。。。。。。
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();
if (mWmService.mWatermark != null) {
mWmService.mWatermark.positionSurface(defaultDw, defaultDh, t);
}
if (mWmService.mStrictModeFlash != null) {
mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, t);
}
if (mWmService.mEmulatorDisplayOverlay != null) {
mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
defaultDc.getRotation(), t);
}
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
// 这里!
dc.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);
}
}
-> DisplayContent.java:applySurfaceChangesTransaction
注意,这里就是核心逻辑了
void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
...........
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
try {
mDisplayPolicy.beginPostLayoutPolicyLw();
forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
mDisplayPolicy.finishPostLayoutPolicyLw();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
mInsetsStateController.onPostLayout();
mTmpApplySurfaceChangesTransactionState.reset();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
// 这里:对于所有的window,使用这个surface changes的任务
forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
prepareSurfaces();
...........
}
void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
forAllWindows(wrapper, traverseTopToBottom);
wrapper.release();
}
mApplySurfaceChangesTransaction
这个成员变量内容很多,我们挑重点看看;
// Moved from updateWindowsAndWallpaperLocked().
// 这里肯定是有surface的,理论上讲,此时已经app已经画完了,怎么会没有呢!
// 赋值的位置是:(下面图)setHasSurface的时候为true时是createSurface的时候;
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();
WindowStateAnimator.java
boolean commitFinishDrawingLocked() {
if (DEBUG_STARTING_WINDOW_VERBOSE &&
mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
+ drawStateToString());
}
// 这里进行一下校验,当前的状态应该是draw_pending的;
if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
return false;
}
ProtoLog.i(WM_DEBUG_ANIM, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW %s",
mSurfaceController);
// 这里直接将状态变为 ready_to_show!并在下面进一步调用
mDrawState = READY_TO_SHOW;
boolean result = false;
final ActivityRecord activity = mWin.mActivityRecord;
// 对于一个普通的系统窗口,不是一个activity,就会进入进来,如果是activity会走其他逻辑,我们后面再看;
// 这里先跟进去看看对于一个普通的系统窗口,会怎么 performShow!
if (activity == null || activity.canShowWindows()
|| mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = mWin.performShowLocked();
}
return result;
}
WindowState.java
boolean performShowLocked() {
......
logPerformShow("Showing ");
mWmService.enableScreenIfNeededLocked();
// 这里也很重要,对于acitivity来说动画很重要,但是这个系统窗口是没有动画的,后面在看;
mWinAnimator.applyEnterAnimationLocked();
// Force the show in the next prepareSurfaceLocked() call.
mWinAnimator.mLastAlpha = -1;
ProtoLog.v(WM_DEBUG_ANIM, "performShowLocked: mDrawState=HAS_DRAWN in %s", this);
// 这里直接进入到下一阶段,state变成 has_drawn,但是实际还没有进行绘制呢!!!
mWinAnimator.mDrawState = HAS_DRAWN;
mWmService.scheduleAnimationLocked();
if (mHidden) {
mHidden = false;
final DisplayContent displayContent = getDisplayContent();
// 这里可以看到,对于all window,每次调用都会对孩子进行处理,调用孩子的performShowLocked
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState c = mChildren.get(i);
if (c.mWinAnimator.mSurfaceController != null) {
c.performShowLocked();
// It hadn't been shown, which means layout not performed on it, so now we
// want to make sure to do a layout. If called from within the transaction
// loop, this will cause it to restart with a new layout.
if (displayContent != null) {
displayContent.setLayoutNeeded();
}
}
}
}
return true;
}
到这里,drawState的流程走完了,但是还没有实际绘制上,下面我们来看看,到底是哪里进行的绘制;
surface
上面我们发现,状态最终的转换核心函数是:
DisplayContent.java:applySurfaceChangesTransaction
在这个transaction执行完成后,整个的drawState已经到达了has_drawn的状态,这已经可以说,在wms侧已经干完了;
但是我们从 DisplayContent.java:applySurfaceChangesTransaction结束完成后,发现真正的提交给surfaceflinger的transaction在后面;
我们继续看这个函数:
DisplayContent.java:applySurfaceChangesTransaction
void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
beginHoldScreenUpdate();
mTmpUpdateAllDrawn.clear();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
pendingLayoutChanges);
if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
mWallpaperController.adjustWallpaperWindows();
}
if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (updateOrientation()) {
setLayoutNeeded();
sendNewConfiguration();
}
}
if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
setLayoutNeeded();
}
// Perform a layout, if needed.
performLayout(true /* initial */, false /* updateInputWindows */);
pendingLayoutChanges = 0;
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyPostLayoutPolicy");
try {
mDisplayPolicy.beginPostLayoutPolicyLw();
forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
mDisplayPolicy.finishPostLayoutPolicyLw();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
mInsetsStateController.onPostLayout();
mTmpApplySurfaceChangesTransactionState.reset();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
try {
forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
// 这里是关键信息!,对于上面执行完forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
之后,就已经完成了状态的切换,这里与sf进行交互,完成真正的任务提交;
prepareSurfaces();
// This should be called after the insets have been dispatched to clients and we have
// committed finish drawing windows.
mInsetsStateController.getImeSourceProvider().checkShowImePostLayout();
mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
if (!mWmService.mDisplayFrozen) {
mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
mLastHasContent,
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredModeId,
mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
true /* inTraversal, must call performTraversalInTrans... below */);
}
// If the display now has content, or no longer has content, update recording.
updateRecording();
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
if (wallpaperVisible != mLastWallpaperVisible) {
mLastWallpaperVisible = wallpaperVisible;
mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
}
while (!mTmpUpdateAllDrawn.isEmpty()) {
final ActivityRecord activity = mTmpUpdateAllDrawn.removeLast();
// See if any windows have been drawn, so they (and others associated with them)
// can now be shown.
activity.updateAllDrawn();
}
finishHoldScreenUpdate();
}
prepareSurfaces:看起来没啥东西,
void prepareSurfaces() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "prepareSurfaces");
try {
final Transaction transaction = getPendingTransaction();
这里父类,追踪一下
super.prepareSurfaces();
// TODO: Once we totally eliminate global transaction we will pass transaction in here
// rather than merging to global.
SurfaceControl.mergeToGlobalTransaction(transaction);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
DisplayArea:prepareSurfaces
void prepareSurfaces() {
mDimmer.resetDimStates();
super.prepareSurfaces();
// Bounds need to be relative, as the dim layer is a child.
getBounds(mTmpDimBoundsRect);
mTmpDimBoundsRect.offsetTo(0 /* newLeft */, 0 /* newTop */);
// If SystemUI is dragging for recents, we want to reset the dim state so any dim layer
// on the display level fades out.
if (forAllTasks(task -> !task.canAffectSystemUiFlags())) {
mDimmer.resetDimStates();
}
if (mDimmer.updateDims(getSyncTransaction(), mTmpDimBoundsRect)) {
scheduleAnimation();
}
}
}
WindowContainer:prepareSurfaces
void prepareSurfaces() {
// If a leash has been set when the transaction was committed, then the leash reparent has
// been committed.
mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
for (int i = 0; i < mChildren.size(); i++) {
mChildren.get(i).prepareSurfaces();
}
}
这里遍历当前窗口的每一个孩子,并调用孩子的prepareSurfaces,实际上对于系统窗口,我们没有activity,也不是个task或者fragment,这里我们就看windowState,最为普通的这个;
WindowState:prepareSurfaces
void prepareSurfaces() {
mIsDimming = false;
applyDims();
updateSurfacePositionNonOrganized();
// Send information to SurfaceFlinger about the priority of the current window.
updateFrameRateSelectionPriorityIfNeeded();
updateScaleIfNeeded();
这里:调用到WindowStateAnimate的surface准备函数;
mWinAnimator.prepareSurfaceLocked(getSyncTransaction());
super.prepareSurfaces();
}
WindowStateAnimator:prepareSurfaceLocked
函数比较长,我们看重点的内容;
void prepareSurfaceLocked(SurfaceControl.Transaction t) {
final WindowState w = mWin;
if (!hasSurface()) {
// There is no need to wait for an animation change if our window is gone for layout
// already as we'll never be visible.
if (w.getOrientationChanging() && w.isGoneForLayout()) {
ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w);
w.setOrientationChanging(false);
}
return;
}
computeShownFrameLocked();
if (w.isParentWindowHidden() || !w.isOnScreen()) {
hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w);
// If we are waiting for this window to handle an orientation change. If this window is
// really hidden (gone for layout), there is no point in still waiting for it.
// Note that this does introduce a potential glitch if the window becomes unhidden
// before it has drawn for the new orientation.
if (w.getOrientationChanging() && w.isGoneForLayout()) {
w.setOrientationChanging(false);
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Orientation change skips hidden %s", w);
}
走到这里:,当前是hid状态,我们进入这儿if,createSurface的时候把mLast配置为true
} else if (mLastAlpha != mShownAlpha
|| mLastHidden) {
mLastAlpha = mShownAlpha;
ProtoLog.i(WM_SHOW_TRANSACTIONS,
"SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s",
mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w);
1. 这里提交一个transaction:通过t.setAlpha传入这个surface,调整surface的alpha值、
// 这里就不进去看了,直接粘贴下函数里面的设置;返回true t.setAlpha(mSurfaceControl, alpha);
boolean prepared =
mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
2. 这里就非常非常关键了,就是这里和surfacecontrol进行的交互,完成了show的调用,我们来详细看一下这里
if (showSurfaceRobustlyLocked(t)) {
mAnimator.requestRemovalOfReplacedWindows(w);
mLastHidden = false;
final DisplayContent displayContent = w.getDisplayContent();
if (!displayContent.getLastHasContent()) {
// This draw means the difference between unique content and mirroring.
// Run another pass through performLayout to set mHasContent in the
// LogicalDisplay.
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
if (DEBUG_LAYOUT_REPEATS) {
mService.mWindowPlacerLocked.debugLayoutRepeats(
"showSurfaceRobustlyLocked " + w,
displayContent.pendingLayoutChanges);
}
}
} else {
w.setOrientationChanging(false);
}
}
}
} else {
if (mWin.isAnimating(TRANSITION | PARENTS)) {
ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
}
}
if (w.getOrientationChanging()) {
if (!w.isDrawn()) {
if (w.mDisplayContent.shouldSyncRotationChange(w)) {
w.mWmService.mRoot.mOrientationChangeComplete = false;
mAnimator.mLastWindowFreezeSource = w;
}
ProtoLog.v(WM_DEBUG_ORIENTATION,
"Orientation continue waiting for draw in %s", w);
} else {
w.setOrientationChanging(false);
ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w);
}
}
}
showSurfaceRobustlyLocked
private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
boolean shown = mSurfaceController.showRobustly(t);
if (!shown)
return false;
t.merge(mPostDrawTransaction);
return true;
}
WindowSurfaceController:showRobustly
boolean showRobustly(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
if (mSurfaceShown) {
return true;
}
setShown(true);
1. 这里!通过transation调用了show,展示当前surfacecontrol
t.show(mSurfaceControl);
if (mAnimator.mIsWallpaper) {
final DisplayContent dc = mAnimator.mWin.getDisplayContent();
EventLog.writeEvent(EventLogTags.WM_WALLPAPER_SURFACE,
dc.mDisplayId, 1 /* request shown */,
String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
}
return true;
}
都调用完成后,回到
RootWindowContainer:performSurfacePlacementNoTrace,重新close transaction
dump查看
从dump可以看出,一共有很多window;能够从
Surface: shown=false layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 1 transform=(1.0, 0.0, 0.0, 1.0)
mDrawState=HAS_DRAWN mLastHidden=true
大致看出,当前是否是显示的。
WINDOW MANAGER WINDOWS (dumpsys window windows)
Window #0 Window{43a0424 u0 pip-dismiss-overlay}:
mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@4f80fb6
mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
mAttrs={(0,220)(fillx500) sim={adjust=pan} ty=NAVIGATION_BAR_PANEL fmt=TRANSLUCENT
fl=NOT_FOCUSABLE NOT_TOUCHABLE LAYOUT_IN_SCREEN
pfl=SHOW_FOR_ALL_USERS FIT_INSETS_CONTROLLED}
Requested w=720 h=500 mLayoutSeq=127385
mBaseLayer=251000 mSubLayer=0 mToken=WindowToken{f2c54b7 android.os.BinderProxy@4f80fb6}
mViewVisibility=0x4 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x0
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
display=[0,0][1440,720]
content=[0,220][1440,720] visible=[0,220][1440,720]
decor=[0,0][1440,720]
mFrame=[0,220][1440,720] last=[0,0][0,0]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
WindowStateAnimator{fb09620 pip-dismiss-overlay}:
mDrawState=NO_SURFACE mLastHidden=false
mEnterAnimationPending=false mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
isOnScreen=false
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { }
Window #1 Window{c12ce36 u0 NotificationShade}:
mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@efd2f8
mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
mAttrs={(0,0)(fillxfill) gr=TOP CENTER_VERTICAL sim={adjust=resize} layoutInDisplayCutoutMode=always ty=2040 fmt=TRANSLUCENT
fl=NOT_FOCUSABLE TOUCHABLE_WHEN_WAKING WATCH_OUTSIDE_TOUCH SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
pfl=COLOR_SPACE_AGNOSTIC BEHAVIOR_CONTROLLED FIT_INSETS_CONTROLLED
bhv=SHOW_TRANSIENT_BARS_BY_SWIPE}
Requested w=720 h=1440 mLayoutSeq=17
mBaseLayer=191000 mSubLayer=0 mToken=WindowToken{c3493d1 android.os.BinderProxy@6f78a5b}
mViewVisibility=0x4 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x0
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][720,1440] parent=[0,0][720,1440]
display=[0,0][720,1440]
content=[0,0][720,1440] visible=[0,0][720,1440]
decor=[0,0][720,1440]
mFrame=[0,0][720,1440] last=[0,0][720,1440]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
WindowStateAnimator{4124123 NotificationShade}:
mDrawState=NO_SURFACE mLastHidden=false
mEnterAnimationPending=false mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
isOnScreen=false
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { }
Window #2 Window{4b25d1a u0 StatusBar}:
mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@ce60910
mOwnerUid=10102 showForAllUsers=true package=com.android.systemui appop=NONE
mAttrs={(0,0)(fillx0) gr=TOP CENTER_VERTICAL sim={adjust=pan} layoutInDisplayCutoutMode=always ty=STATUS_BAR fmt=TRANSLUCENT
fl=NOT_FOCUSABLE SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
pfl=COLOR_SPACE_AGNOSTIC FIT_INSETS_CONTROLLED}
Requested w=1440 h=0 mLayoutSeq=127407
mBaseLayer=171000 mSubLayer=0 mToken=WindowToken{714ec09 android.os.BinderProxy@a1ae9d3}
mViewVisibility=0x0 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x0
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mHasSurface=true isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
display=[0,0][1440,720]
content=[0,0][1440,0] visible=[0,0][1440,0]
decor=[0,0][0,0]
mFrame=[0,0][1440,0] last=[0,0][1440,0]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
ContainerAnimator:
mLeash=Surface(name=Surface(name=4b25d1a StatusBar)/@0x74e7825 - animation-leash)/@0xd65d49e mAnimationType=32
Animation: com.android.server.wm.InsetsSourceProvider$ControlAdapter@b57db7f
ControlAdapter
mCapturedLeash=Surface(name=Surface(name=4b25d1a StatusBar)/@0x74e7825 - animation-leash)/@0xd65d49e WindowStateAnimator{5c17a52 StatusBar}:
mAnimationIsEntrance=true mSurface=Surface(name=StatusBar)/@0x393894f
Surface: shown=false layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 1 transform=(1.0, 0.0, 0.0, 1.0)
mDrawState=HAS_DRAWN mLastHidden=true
mEnterAnimationPending=false mSystemDecorRect=[0,0][1440,0] mLastClipRect=[0,0][1440,0]
mLastFreezeDuration=+282ms
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=-1
isOnScreen=true
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { }
Window #3 Window{17fc334 u0 InputMethod}:
mDisplayId=0 rootTaskId=1 mSession=Session{80b5446 4835:u0a10087} mClient=android.os.BinderProxy@4a46607
mOwnerUid=10087 showForAllUsers=false package=com.android.inputmethod.pinyin appop=NONE
mAttrs={(0,0)(fillxwrap) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan forwardNavigation} ty=INPUT_METHOD fmt=TRANSPARENT wanim=0x1030056
fl=NOT_FOCUSABLE LAYOUT_IN_SCREEN SPLIT_TOUCH DRAWS_SYSTEM_BAR_BACKGROUNDS
pfl=FIT_INSETS_CONTROLLED
fitTypes=STATUS_BARS NAVIGATION_BARS
fitSides=LEFT TOP RIGHT}
Requested w=1440 h=0 mLayoutSeq=127404
mIsImWindow=true mIsWallpaper=false mIsFloatingLayer=true mWallpaperVisible=false
mBaseLayer=151000 mSubLayer=0 mToken=WindowToken{cde643b android.os.Binder@eda5aca}
mViewVisibility=0x8 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x0
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mTouchableInsets=2 mGivenInsetsPending=false
touchable region=SkRegion()
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mLastReportedConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=undefined mAlwaysOnTop=undefined mRotation=undefined}}
mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
display=[0,0][1440,720]
content=[0,720][1440,720] visible=[0,720][1440,720]
decor=[0,0][1440,720]
mFrame=[0,720][1440,720] last=[0,0][0,0]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
ContainerAnimator:
mLeash=Surface(name=Surface(name=17fc334 InputMethod)/@0xb986ed2 - animation-leash)/@0xc83574c mAnimationType=32
Animation: com.android.server.wm.InsetsSourceProvider$ControlAdapter@94d8395
ControlAdapter
mCapturedLeash=Surface(name=Surface(name=17fc334 InputMethod)/@0xb986ed2 - animation-leash)/@0xc83574c WindowStateAnimator{e569caa InputMethod}:
mDrawState=NO_SURFACE mLastHidden=false
mEnterAnimationPending=false mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
mShownAlpha=0.0 mAlpha=1.0 mLastAlpha=0.0
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
isOnScreen=false
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { }
Window #4 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}:
mDisplayId=0 rootTaskId=15 mSession=Session{fbf5011 4610:u0a10115} mClient=android.os.BinderProxy@c0a303c
mOwnerUid=10115 showForAllUsers=false package=com.test.xxxxx appop=NONE
mAttrs={(0,0)(fillxfill) sim={adjust=resize forwardNavigation} layoutInDisplayCutoutMode=shortEdges ty=BASE_APPLICATION fmt=TRANSLUCENT wanim=0x1030001 sysuil=true
fl=KEEP_SCREEN_ON LAYOUT_IN_SCREEN FULLSCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED
pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED
vsysui=HIDE_NAVIGATION FULLSCREEN LAYOUT_STABLE LAYOUT_HIDE_NAVIGATION LAYOUT_FULLSCREEN IMMERSIVE_STICKY
bhv=SHOW_TRANSIENT_BARS_BY_SWIPE
fitSides=}
Requested w=1440 h=720 mLayoutSeq=127407
mBaseLayer=21000 mSubLayer=0 mToken=ActivityRecord{7f6ad57 u0 com.test.xxxxx/com.test.xxxxxClient t15}
mActivityRecord=ActivityRecord{7f6ad57 u0 com.test.xxxxx/com.test.xxxxxClient t15}
mAppDied=false drawnStateEvaluated=true mightAffectAllDrawn=true
mViewVisibility=0x0 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x1706
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.1}
mHasSurface=true isReadyForDisplay()=true mWindowRemovalAllowed=false
Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
display=[0,0][1440,720]
content=[0,0][1440,720] visible=[0,0][1440,720]
decor=[0,0][1440,720]
mFrame=[0,0][1440,720] last=[0,0][1440,720]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
WindowStateAnimator{418b09b com.test.xxxxx/com.test.xxxxxClient}:
mSurface=Surface(name=com.test.xxxxx/com.test.xxxxxClient)/@0x7349c38
Surface: shown=true layer=0 alpha=1.0 rect=(0.0,0.0) 1440 x 720 transform=(1.0, 0.0, 1.0, 0.0)
mDrawState=HAS_DRAWN mLastHidden=false
mEnterAnimationPending=false mSystemDecorRect=[0,0][1440,720] mLastClipRect=[0,0][1440,720]
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
isOnScreen=true
isVisible=true
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][1440,0], mVisible=false} }
Window #5 Window{5e2ca2a u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}:
mDisplayId=0 rootTaskId=1 mSession=Session{a65c98b 802:u0a10101} mClient=android.os.BinderProxy@2dff715
mOwnerUid=10101 showForAllUsers=false package=com.android.launcher3 appop=NONE
mAttrs={(0,0)(fillxfill) sim={adjust=pan forwardNavigation} layoutInDisplayCutoutMode=always ty=BASE_APPLICATION fmt=TRANSPARENT wanim=0x10302f2
fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SHOW_WALLPAPER SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS
pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED
vsysui=LAYOUT_STABLE LAYOUT_HIDE_NAVIGATION LAYOUT_FULLSCREEN
fitSides=}
Requested w=720 h=1440 mLayoutSeq=127374
mBaseLayer=21000 mSubLayer=0 mToken=ActivityRecord{627d118 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t5}
mActivityRecord=ActivityRecord{627d118 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t5}
mAppDied=false drawnStateEvaluated=true mightAffectAllDrawn=true
mViewVisibility=0x8 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x700
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_90} s.83}
mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w360dp h720dp 320dpi nrml long port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 720, 1440) mAppBounds=Rect(0, 0 - 720, 1440) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.81}
mHasSurface=false isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][720,1440] parent=[0,0][720,1440]
display=[0,0][720,1440]
content=[0,0][720,1440] visible=[0,0][720,1440]
decor=[0,0][720,1440]
mFrame=[0,0][720,1440] last=[0,0][720,1440]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0] Lst insets: content=[0,0][0,0] visible=[0,0][0,0] stable=[0,0][0,0]
surface=[0,0][0,0]
WindowStateAnimator{c1961d6 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}:
mDrawState=NO_SURFACE mLastHidden=true
mEnterAnimationPending=false mSystemDecorRect=[0,0][720,1440] mLastClipRect=[0,0][720,1440]
mOrientationChanging=false configOrientationChanging=true mAppFreezing=false mReportOrientationChanged=true
mLastFreezeDuration=+181ms
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
mWallpaperX=0.0 mWallpaperY=0.5
mWallpaperXStep=0.33333334 mWallpaperYStep=1.0
isOnScreen=false
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][720,0], mVisible=true} }
Window #6 Window{d9974be u0 com.android.systemui.ImageWallpaper}:
mDisplayId=0 rootTaskId=1 mSession=Session{5c12a99 553:u0a10102} mClient=android.os.BinderProxy@97b1f79
mOwnerUid=10102 showForAllUsers=false package=com.android.systemui appop=NONE
mAttrs={(0,0)(1440x2880) gr=TOP START CENTER layoutInDisplayCutoutMode=always ty=WALLPAPER fmt=RGBX_8888 wanim=0x103030e
fl=NOT_FOCUSABLE NOT_TOUCHABLE LAYOUT_IN_SCREEN LAYOUT_NO_LIMITS SCALED LAYOUT_INSET_DECOR}
Requested w=720 h=1440 mLayoutSeq=127381
mIsImWindow=false mIsWallpaper=true mIsFloatingLayer=true mWallpaperVisible=false
mBaseLayer=11000 mSubLayer=0 mToken=WallpaperWindowToken{fbf8941 token=android.os.Binder@4007828}
mViewVisibility=0x0 mHaveFrame=true mObscured=false
mSeq=0 mSystemUiVisibility=0x0
mGivenContentInsets=[0,0][0,0] mGivenVisibleInsets=[0,0][0,0]
mFullConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mLastReportedConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mHasSurface=true isReadyForDisplay()=false mWindowRemovalAllowed=false
Frames: containing=[0,0][1440,720] parent=[0,0][1440,720]
display=[-10000,-10000][10000,10000]
content=[0,0][1440,720] visible=[0,0][1440,720]
decor=[0,0][1440,720]
mFrame=[0,0][1440,2880] last=[0,0][720,1440]
cutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}} last=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]}}
Cur insets: content=[0,0][0,2160] visible=[0,0][0,2160] stable=[0,0][0,2160] Lst insets: content=[0,0][0,2160] visible=[0,0][0,2160] stable=[0,0][0,2160]
surface=[0,0][0,0]
WindowStateAnimator{6f0b1f1 com.android.systemui.ImageWallpaper}:
mAnimationIsEntrance=true mSurface=Surface(name=com.android.systemui.ImageWallpaper)/@0x175f1e1
Surface: shown=false layer=0 alpha=0.0 rect=(-72.0,-1224.0) 720 x 1440 transform=(2.2, 0.0, 2.2, 0.0)
mDrawState=HAS_DRAWN mLastHidden=true
mEnterAnimationPending=false mSystemDecorRect=[0,0][0,0] mLastClipRect=[0,0][0,0]
mLastFreezeDuration=+135ms
mForceSeamlesslyRotate=false seamlesslyRotate: pending=null finishedFrameNumber=0
mHScale=2.0 mVScale=2.0
mWallpaperX=0.0 mWallpaperY=0.5
mWallpaperXStep=0.33333334 mWallpaperYStep=1.0
mWallpaperZoomOut=0.0
isOnScreen=true
isVisible=false
mRequestedInsetsState: InsetsState: {mDisplayFrame=Rect(0, 0 - 0, 0), mSources= { }
mGlobalConfiguration={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w720dp h360dp 320dpi nrml long land finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 1440, 720) mAppBounds=Rect(0, 0 - 1440, 720) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_90} s.704}
mHasPermanentDpad=false
mTopFocusedDisplayId=0
mInputMethodTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
mInputMethodInputTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
inputMethodControlTarget in display# 0 Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
mInTouchMode=true
mLastDisplayFreezeDuration=+359ms due to Window{d9974be u0 com.android.systemui.ImageWallpaper}
mLastWakeLockHoldingWindow=Window{2d5f15f u0 com.test.xxxxx/com.test.xxxxxLauncher} mLastWakeLockObscuringWindow=null
mHighResTaskSnapshotScale=1.0
SnapshotCache
mInputMethodWindow=Window{17fc334 u0 InputMethod}
mTraversalScheduled=false
mHoldScreenWindow=Window{57101c5 u0 com.test.xxxxx/com.test.xxxxxClient}
mObscuringWindow=null
mSystemBooted=true mDisplayEnabled=true
mTransactionSequence=161065
mDisplayFrozen=false windows=0 client=false apps=0 mRotation=1 mLastOrientation=6
waitingForConfig=false
Animation settings: disabled=false window=1.0 transition=0.0 animator=1.0
PolicyControl.sImmersiveStatusFilter=null
PolicyControl.sImmersiveNavigationFilter=null
PolicyControl.sImmersivePreconfirmationsFilter=null