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

Commit 60b269d

Browse files
Patrick SosinskiEmmanuel Garcia
andauthored
Support talkback in hybrid composition (#19860) (#19864)
Co-authored-by: Emmanuel Garcia <[email protected]>
1 parent c964bf6 commit 60b269d

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,8 @@ public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformM
676676
// Called by native.
677677
// TODO(mattcarroll): determine if message is nonull or nullable
678678
@SuppressWarnings("unused")
679-
private void handlePlatformMessage(
679+
@VisibleForTesting
680+
public void handlePlatformMessage(
680681
@NonNull final String channel, byte[] message, final int replyId) {
681682
if (platformMessageHandler != null) {
682683
platformMessageHandler.handleMessageFromDart(channel, message, replyId);

shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ public void onPreEngineRestart() {
524524

525525
@Override
526526
public View getPlatformViewById(Integer id) {
527+
// Hybrid composition.
528+
if (platformViews.get(id) != null) {
529+
return platformViews.get(id);
530+
}
527531
VirtualDisplayController controller = vdControllers.get(id);
528532
if (controller == null) {
529533
return null;
@@ -641,7 +645,8 @@ private void initializeRootImageViewIfNeeded() {
641645
}
642646
}
643647

644-
private void initializePlatformViewIfNeeded(int viewId) {
648+
@VisibleForTesting
649+
void initializePlatformViewIfNeeded(int viewId) {
645650
if (platformViews.get(viewId) != null) {
646651
return;
647652
}

shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,30 @@
33
import static io.flutter.embedding.engine.systemchannels.PlatformViewsChannel.PlatformViewTouch;
44
import static org.junit.Assert.assertEquals;
55
import static org.junit.Assert.assertNotEquals;
6+
import static org.junit.Assert.assertNotNull;
7+
import static org.junit.Assert.assertNull;
68
import static org.mockito.Matchers.eq;
9+
import static org.mockito.Mockito.any;
710
import static org.mockito.Mockito.mock;
811
import static org.mockito.Mockito.never;
912
import static org.mockito.Mockito.times;
1013
import static org.mockito.Mockito.verify;
14+
import static org.mockito.Mockito.when;
1115

16+
import android.content.Context;
17+
import android.content.res.AssetManager;
1218
import android.view.MotionEvent;
1319
import android.view.View;
20+
import io.flutter.embedding.android.FlutterView;
1421
import io.flutter.embedding.android.MotionEventTracker;
22+
import io.flutter.embedding.engine.FlutterJNI;
23+
import io.flutter.embedding.engine.dart.DartExecutor;
24+
import io.flutter.plugin.common.MethodCall;
25+
import io.flutter.plugin.common.StandardMethodCodec;
26+
import java.nio.ByteBuffer;
1527
import java.util.Arrays;
28+
import java.util.HashMap;
29+
import java.util.Map;
1630
import org.junit.Ignore;
1731
import org.junit.Test;
1832
import org.junit.runner.RunWith;
@@ -186,4 +200,54 @@ public void itUsesActionEventTypeFromMotionEventForHybridPlatformViews() {
186200
assertNotEquals(resolvedEvent.getAction(), frameWorkTouch.action);
187201
assertEquals(resolvedEvent.getAction(), original.getAction());
188202
}
203+
204+
@Test
205+
public void getPlatformViewById__hybridComposition() {
206+
PlatformViewsController platformViewsController = new PlatformViewsController();
207+
208+
int platformViewId = 0;
209+
assertNull(platformViewsController.getPlatformViewById(platformViewId));
210+
211+
FlutterJNI jni = new FlutterJNI();
212+
AssetManager assetManager = mock(AssetManager.class);
213+
Context context = RuntimeEnvironment.application.getApplicationContext();
214+
215+
DartExecutor executor = new DartExecutor(jni, assetManager);
216+
executor.onAttachedToJNI();
217+
platformViewsController.attach(context, null, executor);
218+
platformViewsController.attachToView(mock(FlutterView.class));
219+
220+
PlatformViewFactory viewFactory = mock(PlatformViewFactory.class);
221+
PlatformView platformView = mock(PlatformView.class);
222+
View androidView = mock(View.class);
223+
when(platformView.getView()).thenReturn(androidView);
224+
when(viewFactory.create(any(), eq(platformViewId), any())).thenReturn(platformView);
225+
226+
platformViewsController.getRegistry().registerViewFactory("testType", viewFactory);
227+
228+
// Simulate create call from the framework.
229+
Map<String, Object> platformViewCreateArguments = new HashMap<>();
230+
platformViewCreateArguments.put("hybrid", true);
231+
platformViewCreateArguments.put("id", platformViewId);
232+
platformViewCreateArguments.put("viewType", "testType");
233+
platformViewCreateArguments.put("direction", 0);
234+
MethodCall platformCreateMethodCall = new MethodCall("create", platformViewCreateArguments);
235+
236+
jni.handlePlatformMessage(
237+
"flutter/platform_views", encodeMethodCall(platformCreateMethodCall), /*replyId=*/ 0);
238+
239+
platformViewsController.initializePlatformViewIfNeeded(platformViewId);
240+
241+
View resultAndroidView = platformViewsController.getPlatformViewById(platformViewId);
242+
assertNotNull(resultAndroidView);
243+
assertEquals(resultAndroidView, androidView);
244+
}
245+
246+
private static byte[] encodeMethodCall(MethodCall call) {
247+
ByteBuffer buffer = StandardMethodCodec.INSTANCE.encodeMethodCall(call);
248+
buffer.rewind();
249+
byte[] dest = new byte[buffer.remaining()];
250+
buffer.get(dest);
251+
return dest;
252+
}
189253
}

0 commit comments

Comments
 (0)