Relayout before creating surface

Since we create starting window surfaces immediately (instead of
waiting for app visibility), we hit a weird corner case in which
the surface was created before the window was laid out. Thus, a
little bit later, we had to call SurfaceControl.setSize, which
made the whole transaction blocking, meaning that we blocked until
the next vsync before returning to the client (starting window).

Fix this by running a layout if the window wasn't laid out yet.

Test: Open hot app, see latency go down by an average of 8ms (up
to 16ms better!)

Bug: 32668632
Change-Id: I9817afc72127e32d7f8f4e497e0dccd7f180a9c0
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 63cc9bf..424f8a5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1952,6 +1952,16 @@
             if (viewVisibility == View.VISIBLE &&
                     (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                             || !win.mAppToken.isClientHidden())) {
+
+                // We are about to create a surface, but we didn't run a layout yet. So better run
+                // a layout now that we already know the right size, as a resize call will make the
+                // surface transaction blocking until next vsync and slow us down.
+                // TODO: Ideally we'd create the surface after running layout a bit further down,
+                // but moving this seems to be too risky at this point in the release.
+                if (win.mLayoutSeq == -1) {
+                    win.setDisplayLayoutNeeded();
+                    mWindowPlacerLocked.performSurfacePlacement(true);
+                }
                 result = win.relayoutVisibleWindow(mergedConfiguration, result, attrChanges,
                         oldVisibility);
                 try {