Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 714987f

Browse files
[Android] Send " did gain focus" message from engine to framework (#47114)
issue:flutter/flutter#97747 framework pr:flutter/flutter#135771 ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat --------- Co-authored-by: Reid Baker <[email protected]>
1 parent e010f17 commit 714987f

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import androidx.annotation.NonNull;
44
import androidx.annotation.Nullable;
5+
import androidx.annotation.VisibleForTesting;
56
import io.flutter.Log;
67
import io.flutter.embedding.engine.FlutterJNI;
78
import io.flutter.embedding.engine.dart.DartExecutor;
@@ -102,6 +103,13 @@ public AccessibilityChannel(@NonNull DartExecutor dartExecutor, @NonNull Flutter
102103
this.flutterJNI = flutterJNI;
103104
}
104105

106+
@VisibleForTesting
107+
public AccessibilityChannel(
108+
@NonNull BasicMessageChannel<Object> channel, @NonNull FlutterJNI flutterJNI) {
109+
this.channel = channel;
110+
this.flutterJNI = flutterJNI;
111+
}
112+
105113
/**
106114
* Informs Flutter that the Android OS currently has accessibility enabled.
107115
*

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,12 @@ public boolean performAction(
11661166

11671167
accessibilityChannel.dispatchSemanticsAction(
11681168
virtualViewId, Action.DID_GAIN_ACCESSIBILITY_FOCUS);
1169+
1170+
HashMap<String, Object> message = new HashMap<>();
1171+
message.put("type", "didGainFocus");
1172+
message.put("nodeId", semanticsNode.id);
1173+
accessibilityChannel.channel.send(message);
1174+
11691175
sendAccessibilityEvent(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
11701176

11711177
if (semanticsNode.hasAction(Action.INCREASE)

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

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,9 @@ public void itCanPredictSetSelection() {
11871187

11881188
@Test
11891189
public void itPerformsClearAccessibilityFocusCorrectly() {
1190-
AccessibilityChannel mockChannel = mock(AccessibilityChannel.class);
1190+
BasicMessageChannel mockChannel = mock(BasicMessageChannel.class);
1191+
AccessibilityChannel accessibilityChannel =
1192+
new AccessibilityChannel(mockChannel, mock(FlutterJNI.class));
11911193
AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
11921194
AccessibilityManager mockManager = mock(AccessibilityManager.class);
11931195
View mockRootView = mock(View.class);
@@ -1197,7 +1199,7 @@ public void itPerformsClearAccessibilityFocusCorrectly() {
11971199
AccessibilityBridge accessibilityBridge =
11981200
setUpBridge(
11991201
/*rootAccessibilityView=*/ mockRootView,
1200-
/*accessibilityChannel=*/ mockChannel,
1202+
/*accessibilityChannel=*/ accessibilityChannel,
12011203
/*accessibilityManager=*/ mockManager,
12021204
/*contentResolver=*/ null,
12031205
/*accessibilityViewEmbedder=*/ mockViewEmbedder,
@@ -1220,6 +1222,11 @@ public void itPerformsClearAccessibilityFocusCorrectly() {
12201222
accessibilityBridge.performAction(0, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
12211223
AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0);
12221224
assertTrue(nodeInfo.isAccessibilityFocused());
1225+
1226+
HashMap<String, Object> message = new HashMap<>();
1227+
message.put("type", "didGainFocus");
1228+
message.put("nodeId", 0);
1229+
verify(mockChannel).send(message);
12231230
// Clear focus on non-focused node shouldn't do anything
12241231
accessibilityBridge.performAction(
12251232
1, AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
@@ -1310,7 +1317,10 @@ public void itSetsBoldTextFlagCorrectly() {
13101317

13111318
@Test
13121319
public void itSetsFocusedNodeBeforeSendingEvent() {
1313-
AccessibilityChannel mockChannel = mock(AccessibilityChannel.class);
1320+
BasicMessageChannel mockChannel = mock(BasicMessageChannel.class);
1321+
AccessibilityChannel accessibilityChannel =
1322+
new AccessibilityChannel(mockChannel, mock(FlutterJNI.class));
1323+
13141324
AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
13151325
AccessibilityManager mockManager = mock(AccessibilityManager.class);
13161326
View mockRootView = mock(View.class);
@@ -1320,7 +1330,7 @@ public void itSetsFocusedNodeBeforeSendingEvent() {
13201330
AccessibilityBridge accessibilityBridge =
13211331
setUpBridge(
13221332
/*rootAccessibilityView=*/ mockRootView,
1323-
/*accessibilityChannel=*/ mockChannel,
1333+
/*accessibilityChannel=*/ accessibilityChannel,
13241334
/*accessibilityManager=*/ mockManager,
13251335
/*contentResolver=*/ null,
13261336
/*accessibilityViewEmbedder=*/ mockViewEmbedder,
@@ -1361,11 +1371,18 @@ public boolean verify(InvocationOnMock invocation) {
13611371
.thenAnswer(invocation -> verifier.verify(invocation));
13621372
accessibilityBridge.performAction(0, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
13631373
assertTrue(verifier.verified);
1374+
1375+
HashMap<String, Object> message = new HashMap<>();
1376+
message.put("type", "didGainFocus");
1377+
message.put("nodeId", 0);
1378+
verify(mockChannel).send(message);
13641379
}
13651380

13661381
@Test
13671382
public void itClearsFocusedNodeBeforeSendingEvent() {
1368-
AccessibilityChannel mockChannel = mock(AccessibilityChannel.class);
1383+
BasicMessageChannel mockChannel = mock(BasicMessageChannel.class);
1384+
AccessibilityChannel accessibilityChannel =
1385+
new AccessibilityChannel(mockChannel, mock(FlutterJNI.class));
13691386
AccessibilityViewEmbedder mockViewEmbedder = mock(AccessibilityViewEmbedder.class);
13701387
AccessibilityManager mockManager = mock(AccessibilityManager.class);
13711388
View mockRootView = mock(View.class);
@@ -1375,7 +1392,7 @@ public void itClearsFocusedNodeBeforeSendingEvent() {
13751392
AccessibilityBridge accessibilityBridge =
13761393
setUpBridge(
13771394
/*rootAccessibilityView=*/ mockRootView,
1378-
/*accessibilityChannel=*/ mockChannel,
1395+
/*accessibilityChannel=*/ accessibilityChannel,
13791396
/*accessibilityManager=*/ mockManager,
13801397
/*contentResolver=*/ null,
13811398
/*accessibilityViewEmbedder=*/ mockViewEmbedder,
@@ -1395,6 +1412,10 @@ public void itClearsFocusedNodeBeforeSendingEvent() {
13951412
accessibilityBridge.performAction(0, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
13961413
AccessibilityNodeInfo nodeInfo = accessibilityBridge.createAccessibilityNodeInfo(0);
13971414
assertTrue(nodeInfo.isAccessibilityFocused());
1415+
HashMap<String, Object> message = new HashMap<>();
1416+
message.put("type", "didGainFocus");
1417+
message.put("nodeId", 0);
1418+
verify(mockChannel).send(message);
13981419

13991420
class Verifier {
14001421
public Verifier(AccessibilityBridge accessibilityBridge) {

0 commit comments

Comments
 (0)