Bug 1527022 - Pass AccessibilityTest on Android 11 or early. r=eeejay,geckoview-reviewers,owlish

When getting virtual ID of a11y tree, we use internal method via
reflection. But `AccessibilityNodeInfo.getChildId` is hidden now.

As workaround, since `mChildNodeIds` is still `@UnsupportedAppUsage`,
we can use it to get child node id.

This has another fix. Clipboard access requires foreground on Android 10+.
So we have to set window foucs when using clipboard.

Also, `AccessibilityTest` won't work on Android 12 since more methods
seem to be hidden from Android 12.
(by `@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R)`).

Differential Revision: https://phabricator.services.mozilla.com/D170550
This commit is contained in:
Makoto Kato 2023-03-02 03:15:43 +00:00
Родитель 774d379b0b
Коммит 263e20dd87
1 изменённых файлов: 36 добавлений и 14 удалений

Просмотреть файл

@ -18,6 +18,7 @@ import android.view.accessibility.AccessibilityNodeProvider
import android.view.accessibility.AccessibilityRecord import android.view.accessibility.AccessibilityRecord
import android.widget.EditText import android.widget.EditText
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry import androidx.test.platform.app.InstrumentationRegistry
@ -26,7 +27,9 @@ import org.junit.After
import org.junit.Assume.assumeThat import org.junit.Assume.assumeThat
import org.junit.Before import org.junit.Before
import org.junit.Ignore import org.junit.Ignore
import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.geckoview.AllowOrDeny import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoResult
@ -47,6 +50,10 @@ class AccessibilityTest : BaseSessionTest() {
val screenRect = Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT) val screenRect = Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)
val provider: AccessibilityNodeProvider get() = view.accessibilityNodeProvider val provider: AccessibilityNodeProvider get() = view.accessibilityNodeProvider
private val nodeInfos = mutableListOf<AccessibilityNodeInfo>() private val nodeInfos = mutableListOf<AccessibilityNodeInfo>()
private val activityRule = ActivityScenarioRule(GeckoViewTestActivity::class.java)
@get:Rule
override val rules: RuleChain = RuleChain.outerRule(activityRule).around(sessionRule)
// Given a child ID, return the virtual descendent ID. // Given a child ID, return the virtual descendent ID.
private fun getVirtualDescendantId(childId: Long): Int { private fun getVirtualDescendantId(childId: Long): Int {
@ -78,20 +85,28 @@ class AccessibilityTest : BaseSessionTest() {
} }
// Get a child ID by index. // Get a child ID by index.
private fun AccessibilityNodeInfo.getChildId(index: Int): Int = private fun AccessibilityNodeInfo.getChildId(index: Int): Int {
getVirtualDescendantId( try {
if (Build.VERSION.SDK_INT >= 21) { val field = AccessibilityNodeInfo::class.java.getDeclaredField("mChildNodeIds")
AccessibilityNodeInfo::class.java.getMethod( field.setAccessible(true)
"getChildId", val id = Class.forName("android.util.LongArray").getMethod("get", Int::class.java).invoke(field.get(this), index) as Long
Int::class.java return getVirtualDescendantId(id)
).invoke(this, index) as Long } catch (ex: Exception) {
} else { return getVirtualDescendantId(
( if (Build.VERSION.SDK_INT >= 21) {
AccessibilityNodeInfo::class.java.getMethod("getChildNodeIds") AccessibilityNodeInfo::class.java.getMethod(
.invoke(this) as SparseLongArray "getChildId",
).get(index) Int::class.java
} ).invoke(this, index) as Long
) } else {
(
AccessibilityNodeInfo::class.java.getMethod("getChildNodeIds")
.invoke(this) as SparseLongArray
).get(index)
}
)
}
}
private interface EventDelegate { private interface EventDelegate {
fun onAccessibilityFocused(event: AccessibilityEvent) { } fun onAccessibilityFocused(event: AccessibilityEvent) { }
@ -547,6 +562,13 @@ class AccessibilityTest : BaseSessionTest() {
} }
@Test fun testClipboard() { @Test fun testClipboard() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Writing clipboard requires foreground on Android 10.
activityRule.scenario?.onActivity { activity ->
activity.onWindowFocusChanged(true)
}
}
var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID
loadTestPage("test-clipboard") loadTestPage("test-clipboard")
waitForInitialFocus() waitForInitialFocus()