SurfaceControlViewHostTests: Deflake touchable region test

ViewRootImpl propagates the touchable region to the window-manager
via a one-way call for which there is currently no way to wait
on the result. Rather than add something to the system-image
for this one test, we work around it by polling the dump. In
the future when we consolidate the client->WM interface we should
have a generic method of waiting on the completion of any
"Transaction", which can solve our problems around here.

Bug: 220765793
Test: SurfaceControlViewHostTests
Change-Id: I0ae9a48cd45685b4e4c9585521af9b86c0a9f057
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index 0635661..8e6b6df 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -237,6 +237,34 @@
 
     }
 
+    private String getTouchableRegionFromDump() {
+        final String output = runCommandAndPrintOutput("dumpsys window windows");
+        boolean foundWindow = false;
+        for (String line : output.split("\\n")) {
+            if (line.contains("ConfigChangeHandlingActivity")) {
+                foundWindow = true;
+            }
+            if (foundWindow && line.contains("touchable region")) {
+                return line;
+            }
+        }
+        return null;
+    }
+
+    private boolean waitForTouchableRegionChanged(String originalTouchableRegion) {
+        int retries = 0;
+        while (retries < 50) {
+            if (getTouchableRegionFromDump() != originalTouchableRegion) {
+                return true;
+            }
+            try {
+                Thread.sleep(100);
+            } catch (Exception e) {
+            }
+        }
+        return false;
+    }
+
     @Override
     public void surfaceCreated(SurfaceHolder holder) {
         if (mTestService == null) {
@@ -851,10 +879,21 @@
         mInstrumentation.waitForIdleSync();
         assertFalse(mClicked);
 
+        String originalRegion = getTouchableRegionFromDump();
+
         mActivityRule.runOnUiThread(() -> {
             mSurfaceView.getRootSurfaceControl().setTouchableRegion(new Region(0,0,1,1));
         });
         mInstrumentation.waitForIdleSync();
+        // ViewRootImpl sends the touchable region to the WM via a one-way call, which is great
+        // for performance...however not so good for testability, we have no way
+        // to verify it has arrived! It doesn't make so much sense to bloat
+        // the system image size with a completion callback for just this one test
+        // so we settle for some inelegant spin-polling on the WM dump.
+        // In the future when we revisit WM/Client interface and transactionalize
+        // everything, we should have a standard way to wait on the completion of async
+        // operations
+        waitForTouchableRegionChanged(originalRegion);
 
         CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
         mInstrumentation.waitForIdleSync();
@@ -955,4 +994,3 @@
         assertTrue(mClicked);
     }
 }
-