Revert^2 "Demo of TAPL Common object factory"

5b99e354de41b3730606d12a99674f2b1c325974

Change-Id: I1809b1e7113cace772d156f53beb7026dc0b078f
diff --git a/libraries/tapl-common/Android.bp b/libraries/tapl-common/Android.bp
index 02e1a92..76e1d17 100644
--- a/libraries/tapl-common/Android.bp
+++ b/libraries/tapl-common/Android.bp
@@ -22,6 +22,7 @@
     name: "tapl-common",
     libs: [
         "androidx.test.uiautomator_uiautomator",
+        "androidx.test.runner",
         "junit",
     ],
     srcs: [
diff --git a/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/ObjectFactory.kt b/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/ObjectFactory.kt
new file mode 100644
index 0000000..4817412
--- /dev/null
+++ b/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/ObjectFactory.kt
@@ -0,0 +1,37 @@
+/** Copyright 2022 Google Inc. All Rights Reserved. */
+package android.platform.test.scenario.tapl_common
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.Until
+import java.time.Duration
+
+/**
+ * Object finder for a specific app, represented by its package name. It can be used to find objects
+ * that belong to this specific app.
+ */
+class ObjectFactory(private val packageName: String) {
+    /**
+     * Waits for a UI object with a given resource id. Fails if the object is not visible.
+     *
+     * @param [resourceId] Resource id for the app.
+     * @param [objectName] Name of the object for diags
+     * @return The found UI object.
+     */
+    fun waitForObject(resourceId: String, objectName: String): TaplUiObject {
+        val selector = By.res(packageName, resourceId)
+        val uiObject =
+            device.wait(Until.findObject(selector), WAIT_TIME.toMillis())
+                ?: throw AssertionError(
+                    "UI object '$objectName' is not visible; selector: $selector."
+                )
+        return TaplUiObject(uiObject, objectName)
+    }
+
+    companion object {
+        private val WAIT_TIME = Duration.ofSeconds(10)
+        private val device: UiDevice
+            get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+    }
+}
diff --git a/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/TaplUiObject.kt b/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/TaplUiObject.kt
new file mode 100644
index 0000000..6b0ae46
--- /dev/null
+++ b/libraries/tapl-common/src/android/platform/test/scenario/tapl_common/TaplUiObject.kt
@@ -0,0 +1,52 @@
+/** Copyright 2022 Google Inc. All Rights Reserved. */
+package android.platform.test.scenario.tapl_common
+
+import androidx.test.uiautomator.StaleObjectException
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.UiObject2Condition
+import androidx.test.uiautomator.Until
+import java.time.Duration
+import org.junit.Assert.assertTrue
+
+/**
+ * Ui object with diagnostic metadata and flake-free gestures.
+ * @param [uiObject] UI Automator object
+ * @param [name] Name of the object for diags
+ */
+class TaplUiObject internal constructor(private val uiObject: UiObject2, private val name: String) {
+    private fun waitForObjectCondition(
+        condition: UiObject2Condition<Boolean>,
+        conditionName: String
+    ) {
+        assertTrue(
+            "UI object '$name' is not $conditionName.",
+            uiObject.wait(condition, WAIT_TIME.toMillis())
+        )
+    }
+
+    private fun waitForObjectEnabled() {
+        waitForObjectCondition(Until.enabled(true), "enabled")
+    }
+
+    private fun waitForObjectClickable() {
+        waitForObjectCondition(Until.clickable(true), "clickable")
+    }
+
+    /** Wait for the object to become clickable and enabled, then clicks the object. */
+    fun click() {
+        try {
+            waitForObjectEnabled()
+            waitForObjectClickable()
+            uiObject.click()
+        } catch (e: StaleObjectException) {
+            throw AssertionError(
+                "UI object '$name' has disappeared from the screen during the click gesture.",
+                e
+            )
+        }
+    }
+
+    companion object {
+        private val WAIT_TIME = Duration.ofSeconds(10)
+    }
+}