Handle null a11y node info Test: presubmit Bug: 153607914 Change-Id: Icbb56e8b395a8a3ecbd115ab83e3985969d7c29e
diff --git a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt index 1a22658..4787617 100644 --- a/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt +++ b/tests/tests/os/src/android/os/cts/AutoRevokeTest.kt
@@ -28,6 +28,7 @@ import android.test.InstrumentationTestCase import android.view.accessibility.AccessibilityNodeInfo import android.widget.Switch +import com.android.compatibility.common.util.SystemUtil import com.android.compatibility.common.util.SystemUtil.* import com.android.compatibility.common.util.ThrowingSupplier import com.android.compatibility.common.util.UiAutomatorUtils @@ -35,6 +36,7 @@ import org.hamcrest.CoreMatchers.containsString import org.junit.Assert.assertThat import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference import java.util.regex.Pattern private const val APK_PATH = "/data/local/tmp/cts/os/CtsAutoRevokeDummyApp.apk" @@ -211,16 +213,18 @@ private fun getWhitelistToggle(): AccessibilityNodeInfo { waitForIdle() - val ui = instrumentation.uiAutomation.rootInActiveWindow - return ui.depthFirstSearch { - depthFirstSearch { - (text as CharSequence?).toString() == "Remove permissions if app isn’t used" - } != null && - depthFirstSearch { className == Switch::class.java.name } != null - }.assertNotNull { - "No auto-revoke whitelist toggle found in\n" + - buildString { UiDumpUtils.dumpNodes(ui, this) } - }.depthFirstSearch { className == Switch::class.java.name }!! + return eventually { + val ui = instrumentation.uiAutomation.rootInActiveWindow + return@eventually ui.depthFirstSearch { + depthFirstSearch { + (text as CharSequence?).toString() == "Remove permissions if app isn’t used" + } != null && + depthFirstSearch { className == Switch::class.java.name } != null + }.assertNotNull { + "No auto-revoke whitelist toggle found in\n" + + buildString { UiDumpUtils.dumpNodes(ui, this) } + }.depthFirstSearch { className == Switch::class.java.name }!! + } } private fun waitForIdle() { @@ -231,6 +235,14 @@ return if (this == null) throw AssertionError(errorMsg()) else this } + private inline fun <T> eventually(crossinline action: () -> T): T { + val res = AtomicReference<T>() + SystemUtil.eventually { + res.set(action()) + } + return res.get() + } + private fun waitFindObject(selector: BySelector): UiObject2 { try { return UiAutomatorUtils.waitFindObject(selector) @@ -268,10 +280,10 @@ condition: AccessibilityNodeInfo.() -> Boolean ): AccessibilityNodeInfo? { for (child in children) { - child.depthFirstSearch(condition)?.let { return it } + child?.depthFirstSearch(condition)?.let { return it } } if (this.condition()) return this return null } -val AccessibilityNodeInfo.children get() = List(childCount) { i -> getChild(i) } +val AccessibilityNodeInfo.children: List<AccessibilityNodeInfo?> get() = List(childCount) { i -> getChild(i) }