Adding a rule for forcing a test to run either in Portrait or in Landscape mode

Plus some fixes for stuff the popped up while working on the change.

Bug: 202567877, 144870223
Test: presubmit, local runs
Change-Id: I724a693300152c3f811fa530a4956c5f5a8fb69e
diff --git a/libraries/health/rules/Android.bp b/libraries/health/rules/Android.bp
index 8f889a8..ecfa08d 100644
--- a/libraries/health/rules/Android.bp
+++ b/libraries/health/rules/Android.bp
@@ -49,6 +49,7 @@
         "package-helper",
         "statsd-helper",
         "launcher-aosp-tapl",
+        "systemui-helper",
     ],
     srcs: ["src/**/*.java"],
     exclude_srcs: [
diff --git a/libraries/health/rules/src/android/platform/test/rule/LandscapeOrientationRule.java b/libraries/health/rules/src/android/platform/test/rule/LandscapeOrientationRule.java
index d5e5de2..6b3b1cd 100644
--- a/libraries/health/rules/src/android/platform/test/rule/LandscapeOrientationRule.java
+++ b/libraries/health/rules/src/android/platform/test/rule/LandscapeOrientationRule.java
@@ -15,16 +15,17 @@
  */
 package android.platform.test.rule;
 
+import android.graphics.Rect;
 import android.os.RemoteException;
-import android.os.SystemClock;
+import android.platform.helpers.CommonUtils;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiObject2;
 
 import com.android.launcher3.tapl.LauncherInstrumentation;
 
 import org.junit.runner.Description;
 
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static org.junit.Assert.assertEquals;
-
 /**
  * Locks landscape orientation before running a test and goes back to natural orientation
  * afterwards.
@@ -35,25 +36,28 @@
     @Override
     protected void starting(Description description) {
         try {
-            getUiDevice().setOrientationNatural();
-            int currentOrientation = getContext().getResources().getConfiguration().orientation;
-            if (currentOrientation != ORIENTATION_LANDSCAPE) { // ORIENTATION_PORTRAIT
-                getUiDevice().pressHome();
-                mLauncher.setEnableRotation(true);
-                getUiDevice().setOrientationLeft();
-                for (int i = 0; i != 100; ++i) {
-                    int rotatedOrientation =
-                            getContext().getResources().getConfiguration().orientation;
-                    if (rotatedOrientation == ORIENTATION_LANDSCAPE) break;
-                    if (i == 99) {
-                        assertEquals(
-                                "Orientation should be landscape",
-                                ORIENTATION_LANDSCAPE,
-                                rotatedOrientation);
-                    }
-                    SystemClock.sleep(100);
-                }
-            }
+            getUiDevice().pressHome();
+            mLauncher.setEnableRotation(true);
+            getUiDevice().setOrientationLeft();
+
+            CommonUtils.waitForNullDiag(
+                    () -> {
+                        final UiObject2 launcher =
+                                getUiDevice()
+                                        .findObject(
+                                                By.res("android", "content")
+                                                        .pkg(
+                                                                getUiDevice()
+                                                                        .getLauncherPackageName()));
+                        if (launcher == null) return "Launcher is not found";
+
+                        final Rect launcherRectangle = launcher.getVisibleBounds();
+                        if (launcherRectangle.width() < launcherRectangle.height()) {
+                            return "Visible orientation is not landscape";
+                        }
+
+                        return null; // No error == success.
+                    });
         } catch (RemoteException e) {
             String message = "RemoteException when forcing landscape rotation on the device";
             throw new RuntimeException(message, e);
@@ -63,9 +67,7 @@
     @Override
     protected void finished(Description description) {
         try {
-            if (!getUiDevice().isNaturalOrientation()) {
-                getUiDevice().setOrientationNatural();
-            }
+            getUiDevice().setOrientationNatural();
             mLauncher.setEnableRotation(false);
             getUiDevice().unfreezeRotation();
         } catch (RemoteException e) {
diff --git a/libraries/health/rules/src/android/platform/test/rule/OrientationRule.java b/libraries/health/rules/src/android/platform/test/rule/OrientationRule.java
new file mode 100644
index 0000000..dbb1e19
--- /dev/null
+++ b/libraries/health/rules/src/android/platform/test/rule/OrientationRule.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 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.platform.test.rule;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This rule will lock orientation before running a test class and unlock after. The orientation is
+ * portrait by default, and landscape if the test or one of its superclasses is marked with
+ * the @Landscape annotation.
+ */
+public class OrientationRule implements TestRule {
+    @Override
+    public Statement apply(Statement base, Description description) {
+        final boolean landscape = hasLandscapeAnnotation(description.getTestClass());
+        final TestRule orientationRule =
+                landscape ? new LandscapeOrientationRule() : new NaturalOrientationRule();
+        return orientationRule.apply(base, description);
+    }
+
+    private boolean hasLandscapeAnnotation(Class<?> testClass) {
+        if (testClass == null) return false;
+        if (testClass.isAnnotationPresent(Landscape.class)) return true;
+        return hasLandscapeAnnotation(testClass.getSuperclass());
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    public @interface Landscape {}
+}