Loading core/java/android/view/ViewRootImpl.java +20 −4 Original line number Diff line number Diff line Loading @@ -776,6 +776,16 @@ public final class ViewRootImpl implements ViewParent, int mSyncSeqId = 0; int mLastSyncSeqId = 0; /** * Specific optimization where a sync relayout (WM) has determined that the results of a * relayout are likely-valid despite this client providing parameters based on an out-dated * configuration. In this case, relayout will provide a (later) seqId (this one) which it * believes doesn't require another sync relayout and then will NOT cancel. This allows the * VRI to assume the frames are already correct, layout/draw immediately, and then skip the * next sync relayout. */ int mNonSyncEarlySeqId = 0; /** @hide */ public static final class NoPreloadHolder { public static final boolean sAlwaysSeqId; Loading Loading @@ -9597,7 +9607,9 @@ public final class ViewRootImpl implements ViewParent, if ((mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0 && mWindowAttributes.type != TYPE_APPLICATION_STARTING && mSyncSeqId <= mLastSyncSeqId && (mSeqId <= mLastSeqId || !NoPreloadHolder.sAlwaysSeqId) && (!NoPreloadHolder.sAlwaysSeqId || mSeqId <= mLastSeqId || mSeqId <= mNonSyncEarlySeqId) && winConfigFromAm.diff(winConfigFromWm, false /* compareUndefined */) == 0) { final InsetsState state = mInsetsController.getState(); final Rect displayCutoutSafe = mTempRect; Loading Loading @@ -9688,9 +9700,13 @@ public final class ViewRootImpl implements ViewParent, mPendingActivityWindowInfo.set(outInfo); } } final int maybeSyncSeqId = mRelayoutResult.syncSeqId; if (maybeSyncSeqId > (NoPreloadHolder.sAlwaysSeqId ? mSyncSeqId : 0)) { mSyncSeqId = maybeSyncSeqId; if (NoPreloadHolder.sAlwaysSeqId) { // mRelayoutResult.syncSeqId is a legacy name. In practice, with sAlwaysSeqId, it // has been repurposed to be "the highest (non-sync) seqId that this relayout // result is valid for". See docstring on mNonSyncEarlySeqId for more info. mNonSyncEarlySeqId = Math.max(mRelayoutResult.syncSeqId, mNonSyncEarlySeqId); } else if (mRelayoutResult.syncSeqId > 0) { mSyncSeqId = mRelayoutResult.syncSeqId; } mWinFrameInScreen.set(mTmpFrames.frame); Loading services/core/java/com/android/server/wm/WindowManagerService.java +40 −4 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import static com.android.server.wm.SensitiveContentPackages.PackageInfo; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; Loading Loading @@ -2431,7 +2432,12 @@ public class WindowManagerService extends IWindowManager.Stub return false; } return win.cancelAndRedraw(seqId); final boolean cancel = win.cancelAndRedraw(seqId); if (cancel && Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancelDraw clientSeqId=" + seqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } return cancel; } } Loading Loading @@ -2480,6 +2486,11 @@ public class WindowManagerService extends IWindowManager.Stub // 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; if (mAlwaysSeqId && Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "earlyCancelDraw clientSeqId=" + syncSeqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } } final DisplayContent displayContent = win.getDisplayContent(); Loading Loading @@ -2854,12 +2865,37 @@ public class WindowManagerService extends IWindowManager.Stub : -1; win.markRedrawForSyncReported(); } else { if (mAlwaysSeqId && win.cancelAndRedraw(syncSeqId)) { outRelayoutResult.syncSeqId = -1; if (mAlwaysSeqId && (result & RELAYOUT_RES_CANCEL_AND_REDRAW) == 0 && win.cancelAndRedraw(syncSeqId)) { // Surface-placement has resulted in a new configuration or a new sync, // so this current layout is invalid until subsequent reportResized. // However, make a targeted optimization to let the client draw early if the // relayout result won't change even after the client receives the new // configuration. If there is an explicit sync, though, the user-perceived // latency will be worse due to the client drawing content that won't be // presented; so, don't "optimize" in that case. final boolean inExplicitSync = syncSeqId <= win.mBufferSeqId || win.mSyncState == SYNC_STATE_WAITING_FOR_DRAW; if (!inExplicitSync && win.layoutIgnoresClientConfig()) { // Returning a seqId indicates, to the client, that it can use this // result even though it's configuration is out-dated. outRelayoutResult.syncSeqId = win.mSyncSeqId; if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "ignoreCancelDraw seqId=" + win.mSyncSeqId); } } else { result |= RELAYOUT_RES_CANCEL_AND_REDRAW; if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "lateCancelDraw " + " clientSeqId=" + syncSeqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } } } outRelayoutResult.syncSeqId = -1; } } Loading services/core/java/com/android/server/wm/WindowState.java +19 −6 Original line number Diff line number Diff line Loading @@ -6138,12 +6138,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (!mWmService.mAlwaysSeqId) { return mPrepareSyncSeqId > 0; } final boolean cancel = Math.max(mSyncSeqId, mBufferSeqId) > seqId; if (cancel) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancelDraw clientSeqId=" + seqId + " serverSeqId=" + mSyncSeqId + " bufferSeqId=" + mBufferSeqId); return Math.max(mSyncSeqId, mBufferSeqId) > seqId; } return cancel; /** * Normally, if the client hasn't received the latest configuration yet, we can't assume that * the layout parameters are accurate (since they can depend on the configuration). * * However, there are specific situations where layout logic ignores configuration-dependent * layout params AND where we are confident that those layout params aren't, themselves, * configuration-dependent. We can use this information for certain optimizations. * * @return {@code true} if this window's client configuration is irrelevant to layout. */ boolean layoutIgnoresClientConfig() { // We are only confident that fullscreen system-ui windows remain fullscreen regardless of // of configuration. return mActivityRecord == null && !mIsWallpaper && mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT && mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT; } public boolean isActivityWindow() { Loading Loading
core/java/android/view/ViewRootImpl.java +20 −4 Original line number Diff line number Diff line Loading @@ -776,6 +776,16 @@ public final class ViewRootImpl implements ViewParent, int mSyncSeqId = 0; int mLastSyncSeqId = 0; /** * Specific optimization where a sync relayout (WM) has determined that the results of a * relayout are likely-valid despite this client providing parameters based on an out-dated * configuration. In this case, relayout will provide a (later) seqId (this one) which it * believes doesn't require another sync relayout and then will NOT cancel. This allows the * VRI to assume the frames are already correct, layout/draw immediately, and then skip the * next sync relayout. */ int mNonSyncEarlySeqId = 0; /** @hide */ public static final class NoPreloadHolder { public static final boolean sAlwaysSeqId; Loading Loading @@ -9597,7 +9607,9 @@ public final class ViewRootImpl implements ViewParent, if ((mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0 && mWindowAttributes.type != TYPE_APPLICATION_STARTING && mSyncSeqId <= mLastSyncSeqId && (mSeqId <= mLastSeqId || !NoPreloadHolder.sAlwaysSeqId) && (!NoPreloadHolder.sAlwaysSeqId || mSeqId <= mLastSeqId || mSeqId <= mNonSyncEarlySeqId) && winConfigFromAm.diff(winConfigFromWm, false /* compareUndefined */) == 0) { final InsetsState state = mInsetsController.getState(); final Rect displayCutoutSafe = mTempRect; Loading Loading @@ -9688,9 +9700,13 @@ public final class ViewRootImpl implements ViewParent, mPendingActivityWindowInfo.set(outInfo); } } final int maybeSyncSeqId = mRelayoutResult.syncSeqId; if (maybeSyncSeqId > (NoPreloadHolder.sAlwaysSeqId ? mSyncSeqId : 0)) { mSyncSeqId = maybeSyncSeqId; if (NoPreloadHolder.sAlwaysSeqId) { // mRelayoutResult.syncSeqId is a legacy name. In practice, with sAlwaysSeqId, it // has been repurposed to be "the highest (non-sync) seqId that this relayout // result is valid for". See docstring on mNonSyncEarlySeqId for more info. mNonSyncEarlySeqId = Math.max(mRelayoutResult.syncSeqId, mNonSyncEarlySeqId); } else if (mRelayoutResult.syncSeqId > 0) { mSyncSeqId = mRelayoutResult.syncSeqId; } mWinFrameInScreen.set(mTmpFrames.frame); Loading
services/core/java/com/android/server/wm/WindowManagerService.java +40 −4 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import static com.android.server.wm.SensitiveContentPackages.PackageInfo; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.SYNC_STATE_WAITING_FOR_DRAW; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; Loading Loading @@ -2431,7 +2432,12 @@ public class WindowManagerService extends IWindowManager.Stub return false; } return win.cancelAndRedraw(seqId); final boolean cancel = win.cancelAndRedraw(seqId); if (cancel && Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancelDraw clientSeqId=" + seqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } return cancel; } } Loading Loading @@ -2480,6 +2486,11 @@ public class WindowManagerService extends IWindowManager.Stub // 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; if (mAlwaysSeqId && Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "earlyCancelDraw clientSeqId=" + syncSeqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } } final DisplayContent displayContent = win.getDisplayContent(); Loading Loading @@ -2854,12 +2865,37 @@ public class WindowManagerService extends IWindowManager.Stub : -1; win.markRedrawForSyncReported(); } else { if (mAlwaysSeqId && win.cancelAndRedraw(syncSeqId)) { outRelayoutResult.syncSeqId = -1; if (mAlwaysSeqId && (result & RELAYOUT_RES_CANCEL_AND_REDRAW) == 0 && win.cancelAndRedraw(syncSeqId)) { // Surface-placement has resulted in a new configuration or a new sync, // so this current layout is invalid until subsequent reportResized. // However, make a targeted optimization to let the client draw early if the // relayout result won't change even after the client receives the new // configuration. If there is an explicit sync, though, the user-perceived // latency will be worse due to the client drawing content that won't be // presented; so, don't "optimize" in that case. final boolean inExplicitSync = syncSeqId <= win.mBufferSeqId || win.mSyncState == SYNC_STATE_WAITING_FOR_DRAW; if (!inExplicitSync && win.layoutIgnoresClientConfig()) { // Returning a seqId indicates, to the client, that it can use this // result even though it's configuration is out-dated. outRelayoutResult.syncSeqId = win.mSyncSeqId; if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "ignoreCancelDraw seqId=" + win.mSyncSeqId); } } else { result |= RELAYOUT_RES_CANCEL_AND_REDRAW; if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "lateCancelDraw " + " clientSeqId=" + syncSeqId + " serverSeqId=" + win.mSyncSeqId + " bufferSeqId=" + win.mBufferSeqId); } } } outRelayoutResult.syncSeqId = -1; } } Loading
services/core/java/com/android/server/wm/WindowState.java +19 −6 Original line number Diff line number Diff line Loading @@ -6138,12 +6138,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (!mWmService.mAlwaysSeqId) { return mPrepareSyncSeqId > 0; } final boolean cancel = Math.max(mSyncSeqId, mBufferSeqId) > seqId; if (cancel) { Trace.instant(TRACE_TAG_WINDOW_MANAGER, "cancelDraw clientSeqId=" + seqId + " serverSeqId=" + mSyncSeqId + " bufferSeqId=" + mBufferSeqId); return Math.max(mSyncSeqId, mBufferSeqId) > seqId; } return cancel; /** * Normally, if the client hasn't received the latest configuration yet, we can't assume that * the layout parameters are accurate (since they can depend on the configuration). * * However, there are specific situations where layout logic ignores configuration-dependent * layout params AND where we are confident that those layout params aren't, themselves, * configuration-dependent. We can use this information for certain optimizations. * * @return {@code true} if this window's client configuration is irrelevant to layout. */ boolean layoutIgnoresClientConfig() { // We are only confident that fullscreen system-ui windows remain fullscreen regardless of // of configuration. return mActivityRecord == null && !mIsWallpaper && mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT && mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT; } public boolean isActivityWindow() { Loading