Skip to content

Commit 5f3119a

Browse files
authored
android accessibility bridge performSetText also removes string attributes (flutter#33217)
1 parent 8f604da commit 5f3119a

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

shell/platform/android/io/flutter/view/AccessibilityBridge.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1297,9 +1297,10 @@ private boolean performSetText(SemanticsNode node, int virtualViewId, @NonNull B
12971297
newText = arguments.getString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE);
12981298
}
12991299
accessibilityChannel.dispatchSemanticsAction(virtualViewId, Action.SET_TEXT, newText);
1300-
// The voice access expects the semantics node to update immediately. We update the semantics
1300+
// The voice access expects the semantics node to update immediately. Update the semantics
13011301
// node based on prediction. If the result is incorrect, it will be updated in the next frame.
13021302
node.value = newText;
1303+
node.valueAttributes = null;
13031304
return true;
13041305
}
13051306

shell/platform/android/test/io/flutter/view/AccessibilityBridgeTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.content.Context;
2828
import android.graphics.Rect;
2929
import android.os.Bundle;
30+
import android.text.SpannableString;
3031
import android.text.SpannedString;
3132
import android.text.style.LocaleSpan;
3233
import android.text.style.TtsSpan;
@@ -721,6 +722,65 @@ public void itBuildsAttributedString() {
721722
assertEquals(actual.getSpanEnd(spellOutSpan), 9);
722723
}
723724

725+
@TargetApi(21)
726+
@Test
727+
public void itSetsTextCorrectly() {
728+
AccessibilityChannel mockChannel = mock(AccessibilityChannel.class);
729+
AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
730+
AccessibilityManager mockManager = mock(AccessibilityManager.class);
731+
View mockRootView = mock(View.class);
732+
Context context = mock(Context.class);
733+
when(mockRootView.getContext()).thenReturn(context);
734+
when(context.getPackageName()).thenReturn("test");
735+
AccessibilityBridge accessibilityBridge =
736+
setUpBridge(
737+
/*rootAccessibilityView=*/ mockRootView,
738+
/*accessibilityChannel=*/ mockChannel,
739+
/*accessibilityManager=*/ mockManager,
740+
/*contentResolver=*/ null,
741+
/*accessibilityViewEmbedder=*/ mockViewEmbedder,
742+
/*platformViewsAccessibilityDelegate=*/ null);
743+
744+
ViewParent mockParent = mock(ViewParent.class);
745+
when(mockRootView.getParent()).thenReturn(mockParent);
746+
when(mockManager.isEnabled()).thenReturn(true);
747+
748+
TestSemanticsNode root = new TestSemanticsNode();
749+
root.id = 0;
750+
root.value = "value";
751+
TestStringAttribute attribute = new TestStringAttributeSpellOut();
752+
attribute.start = 1;
753+
attribute.end = 2;
754+
attribute.type = TestStringAttributeType.SPELLOUT;
755+
root.valueAttributes = new ArrayList<>();
756+
root.valueAttributes.add(attribute);
757+
758+
TestSemanticsUpdate testSemanticsUpdate = root.toUpdate();
759+
testSemanticsUpdate.sendUpdateToBridge(accessibilityBridge);
760+
AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0);
761+
SpannableString actual = (SpannableString) nodeInfo.getContentDescription();
762+
assertEquals(actual.toString(), "value");
763+
Object[] objectSpans = actual.getSpans(0, actual.length(), Object.class);
764+
assertEquals(objectSpans.length, 1);
765+
TtsSpan spellOutSpan = (TtsSpan) objectSpans[0];
766+
assertEquals(spellOutSpan.getType(), TtsSpan.TYPE_VERBATIM);
767+
assertEquals(actual.getSpanStart(spellOutSpan), 1);
768+
assertEquals(actual.getSpanEnd(spellOutSpan), 2);
769+
770+
// Perform a set text action.
771+
Bundle bundle = new Bundle();
772+
String expectedText = "a";
773+
bundle.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, expectedText);
774+
accessibilityBridge.performAction(0, AccessibilityNodeInfo.ACTION_SET_TEXT, bundle);
775+
776+
// The action should remove the string attributes.
777+
nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0);
778+
actual = (SpannableString) nodeInfo.getContentDescription();
779+
assertEquals(actual.toString(), expectedText);
780+
objectSpans = actual.getSpans(0, actual.length(), Object.class);
781+
assertEquals(objectSpans.length, 0);
782+
}
783+
724784
@TargetApi(28)
725785
@Test
726786
public void itSetsTooltipCorrectly() {

0 commit comments

Comments
 (0)