Add test for force relayout behavior

Test: self
Fixes: 153832271
Change-Id: I7a0d4a48a36c9af76fafe5094b3f7afee62b0328
diff --git a/tests/framework/base/windowmanager/Android.bp b/tests/framework/base/windowmanager/Android.bp
index cf35fd0..64710de 100644
--- a/tests/framework/base/windowmanager/Android.bp
+++ b/tests/framework/base/windowmanager/Android.bp
@@ -26,3 +26,8 @@
     name: "cts-wm-decor-inset-test-base",
     srcs: ["src/android/server/wm/DecorInsetTestsBase.java"],
 }
+
+filegroup {
+    name: "cts-wm-force-relayout-test-base",
+    srcs: ["src/android/server/wm/ForceRelayoutTestBase.java"],
+}
diff --git a/tests/framework/base/windowmanager/AndroidManifest.xml b/tests/framework/base/windowmanager/AndroidManifest.xml
index 4402729..997cfdc 100644
--- a/tests/framework/base/windowmanager/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/AndroidManifest.xml
@@ -402,6 +402,9 @@
 
         <activity android:name="android.server.wm.WindowInsetsAnimationTests$TestActivity"
                   android:theme="@android:style/Theme.Material.NoActionBar" />
+
+        <activity android:name="android.server.wm.ForceRelayoutTestBase$TestActivity"
+                  android:exported="true" />
     </application>
 
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTest.java b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTest.java
new file mode 100644
index 0000000..b352df2
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+
+@Presubmit
+public class ForceRelayoutTest extends ForceRelayoutTestBase {
+
+    @Test
+    public void testNoRelayoutWhenInsetsChange() throws Throwable {
+        testRelayoutWhenInsetsChange(false /* testRelayoutWhenInsetsChange */);
+    }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
new file mode 100644
index 0000000..a2ff568
--- /dev/null
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm;
+
+import static android.view.WindowInsets.Type.systemBars;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.graphics.Insets;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsets;
+
+import androidx.annotation.Nullable;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.Rule;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ForceRelayoutTestBase {
+
+    @Rule
+    public ActivityTestRule<TestActivity> mDecorActivity = new ActivityTestRule<>(
+            TestActivity.class);
+
+    void testRelayoutWhenInsetsChange(boolean expectRelayoutWhenInsetsChange)
+            throws Throwable {
+        TestActivity activity = mDecorActivity.getActivity();
+        assertNotNull("test setup failed", activity.mLastContentInsets);
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            activity.mLayoutHappened = false;
+            activity.mMeasureHappened = false;
+            activity.getWindow().getInsetsController().hide(systemBars());
+        });
+        activity.mZeroInsets.await(180, TimeUnit.SECONDS);
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            if (expectRelayoutWhenInsetsChange) {
+                assertTrue(activity.mLayoutHappened);
+                assertTrue(activity.mMeasureHappened);
+            } else {
+                assertFalse(activity.mLayoutHappened);
+                assertFalse(activity.mMeasureHappened);
+            }
+        });
+    }
+
+    public static class TestActivity extends Activity {
+        WindowInsets mLastContentInsets;
+        final CountDownLatch mZeroInsets = new CountDownLatch(1);
+
+        volatile boolean mLayoutHappened;
+        volatile boolean mMeasureHappened;
+
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
+            getWindow().setDecorFitsSystemWindows(false);
+            View view = new View(this) {
+                @Override
+                protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+                    super.onLayout(changed, left, top, right, bottom);
+                    mLayoutHappened = true;
+                }
+
+                @Override
+                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+                    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+                    mMeasureHappened = true;
+
+                }
+            };
+            view.setOnApplyWindowInsetsListener((v, wi) -> {
+                mLastContentInsets = wi;
+                if (wi.getInsets(systemBars()).equals(Insets.NONE)) {
+
+                    // Make sure full traversal happens before counting down.
+                    v.post(mZeroInsets::countDown);
+                }
+                return WindowInsets.CONSUMED;
+            });
+            setContentView(view);
+        }
+    }
+}
diff --git a/tests/framework/base/windowmanager/testsdk29/Android.bp b/tests/framework/base/windowmanager/testsdk29/Android.bp
index 5f8806b..ca76c86 100644
--- a/tests/framework/base/windowmanager/testsdk29/Android.bp
+++ b/tests/framework/base/windowmanager/testsdk29/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "src/**/*.java",
         ":cts-wm-decor-inset-test-base",
+        ":cts-wm-force-relayout-test-base"
     ],
 
     // Intentionally don't set the compile SDK to 29, because we want to test
diff --git a/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml b/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml
index faa11fe..a0194d3 100644
--- a/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/testsdk29/AndroidManifest.xml
@@ -27,6 +27,10 @@
             android:name="android.server.wm.DecorInsetTestsBase$TestActivity"
             android:label="DecorInsetTestsBase.TestActivity"
             android:exported="true" />
+
+        <activity
+            android:name="android.server.wm.ForceRelayoutTestBase$TestActivity"
+            android:exported="true" />
     </application>
 
     <instrumentation
diff --git a/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/ForceRelayoutSdk29Test.java b/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/ForceRelayoutSdk29Test.java
new file mode 100644
index 0000000..1860571
--- /dev/null
+++ b/tests/framework/base/windowmanager/testsdk29/src/android/server/wm/ForceRelayoutSdk29Test.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.server.wm;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+
+@Presubmit
+public class ForceRelayoutSdk29Test extends ForceRelayoutTestBase {
+
+    @Test
+    public void testRelayoutWhenInsetsChange() throws Throwable {
+        testRelayoutWhenInsetsChange(true /* testRelayoutWhenInsetsChange */);
+    }
+}