Consume sync draw handlers if the surface is destroyed

After requesting blast sync, the window may want to remove
itself and there won't be a finish draw event. Then the
handlers of sync such as seamless rotation keeps waiting
until timeout. So simply notify them to clear the state
if the window surface is destroyed.

Bug: 222048036
Test: atest WindowStateTests#testApplyWithNextDraw
Test: 1. Enable auto rotation and launcher is portrait only.
      2. Launch Settings while holding device in landscape.
      3. Use gesture navigation to swipe up.
      4. Click app icon above the task view.
      5. Click the task view to back to Settings.
      6. The status/nav bars should be visible immediately.
         (No timeout from SecondaryHomeHandle0)
Change-Id: I2c8edf230a149b520032ec132e5df1aaa6683ef8
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d547275..e698e2f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3583,6 +3583,10 @@
         // Clear animating flags now, since the surface is now gone. (Note this is true even
         // if the surface is saved, to outside world the surface is still NO_SURFACE.)
         mAnimatingExit = false;
+
+        if (useBLASTSync()) {
+            immediatelyNotifyBlastSync();
+        }
     }
 
     void onSurfaceShownChanged(boolean shown) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index a554fab..e70dd08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -61,6 +61,7 @@
 import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
@@ -492,6 +493,26 @@
     }
 
     @Test
+    public void testApplyWithNextDraw() {
+        final WindowState win = createWindow(null, TYPE_APPLICATION_OVERLAY, "app");
+        final SurfaceControl.Transaction[] handledT = { null };
+        // The normal case that the draw transaction is applied with finishing drawing.
+        win.applyWithNextDraw(t -> handledT[0] = t);
+        assertTrue(win.useBLASTSync());
+        final SurfaceControl.Transaction drawT = new StubTransaction();
+        win.prepareDrawHandlers();
+        assertTrue(win.finishDrawing(drawT));
+        assertEquals(drawT, handledT[0]);
+        assertFalse(win.useBLASTSync());
+
+        // If the window is gone before reporting drawn, the sync state should be cleared.
+        win.applyWithNextDraw(t -> handledT[0] = t);
+        win.destroySurfaceUnchecked();
+        assertFalse(win.useBLASTSync());
+        assertNotEquals(drawT, handledT[0]);
+    }
+
+    @Test
     public void testSeamlesslyRotateWindow() {
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
         final SurfaceControl.Transaction t = spy(StubTransaction.class);