diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index da29ead5521d..93e6b140a730 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -456,6 +456,7 @@ action("robolectric_tests") { "test/io/flutter/plugin/localization/LocalizationPluginTest.java", "test/io/flutter/plugin/mouse/MouseCursorPluginTest.java", "test/io/flutter/plugin/platform/PlatformPluginTest.java", + "test/io/flutter/plugin/platform/PlatformViewsControllerTest.java", "test/io/flutter/plugin/platform/SingleViewPresentationTest.java", "test/io/flutter/plugins/GeneratedPluginRegistrant.java", "test/io/flutter/util/FakeKeyEvent.java", diff --git a/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java b/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java index a772d14a88c9..3b8cc7ebc413 100644 --- a/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java +++ b/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java @@ -176,7 +176,8 @@ private void addPointerForIndex( return; } - MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(event); + // TODO (kaushikiska) : pass this in when we have a way to evict framework only events. + // MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(event); int pointerKind = getPointerDeviceTypeForToolType(event.getToolType(pointerIndex)); @@ -187,7 +188,7 @@ private void addPointerForIndex( long timeStamp = event.getEventTime() * 1000; // Convert from milliseconds to microseconds. - packet.putLong(motionEventId.getId()); + packet.putLong(0); // motionEventId packet.putLong(timeStamp); // time_stamp packet.putLong(pointerChange); // change packet.putLong(pointerKind); // kind diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java index 3f238c98d99a..19ebe0abe1ac 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java @@ -384,7 +384,7 @@ public static class PlatformViewTouch { /** TODO(iskakaushik): javadoc */ public final long motionEventId; - PlatformViewTouch( + public PlatformViewTouch( int viewId, @NonNull Number downTime, @NonNull Number eventTime, diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 92b77de1b0d8..7fe48d536b59 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -254,10 +254,11 @@ public void onTouch(@NonNull PlatformViewsChannel.PlatformViewTouch touch) { final int viewId = touch.viewId; float density = context.getResources().getDisplayMetrics().density; ensureValidAndroidVersion(Build.VERSION_CODES.KITKAT_WATCH); - final MotionEvent event = toMotionEvent(density, touch); if (vdControllers.containsKey(viewId)) { + final MotionEvent event = toMotionEvent(density, touch, /*usingVirtualDiplays=*/ true); vdControllers.get(touch.viewId).dispatchTouchEvent(event); } else if (platformViews.get(viewId) != null) { + final MotionEvent event = toMotionEvent(density, touch, /*usingVirtualDiplays=*/ false); View view = platformViews.get(touch.viewId); view.dispatchTouchEvent(event); } else { @@ -305,7 +306,9 @@ private void ensureValidAndroidVersion(int minSdkVersion) { } }; - private MotionEvent toMotionEvent(float density, PlatformViewsChannel.PlatformViewTouch touch) { + @VisibleForTesting + public MotionEvent toMotionEvent( + float density, PlatformViewsChannel.PlatformViewTouch touch, boolean usingVirtualDiplays) { MotionEventTracker.MotionEventId motionEventId = MotionEventTracker.MotionEventId.from(touch.motionEventId); MotionEvent trackedEvent = motionEventTracker.pop(motionEventId); @@ -321,7 +324,7 @@ private MotionEvent toMotionEvent(float density, PlatformViewsChannel.PlatformVi parsePointerCoordsList(touch.rawPointerCoords, density) .toArray(new PointerCoords[touch.pointerCount]); - if (trackedEvent != null) { + if (!usingVirtualDiplays && trackedEvent != null) { return MotionEvent.obtain( trackedEvent.getDownTime(), trackedEvent.getEventTime(), diff --git a/shell/platform/android/test/io/flutter/FlutterTestSuite.java b/shell/platform/android/test/io/flutter/FlutterTestSuite.java index 3775bbaccc5d..075e33c24b53 100644 --- a/shell/platform/android/test/io/flutter/FlutterTestSuite.java +++ b/shell/platform/android/test/io/flutter/FlutterTestSuite.java @@ -25,6 +25,7 @@ import io.flutter.plugin.editing.TextInputPluginTest; import io.flutter.plugin.mouse.MouseCursorPluginTest; import io.flutter.plugin.platform.PlatformPluginTest; +import io.flutter.plugin.platform.PlatformViewsControllerTest; import io.flutter.plugin.platform.SingleViewPresentationTest; import io.flutter.util.PreconditionsTest; import io.flutter.view.AccessibilityBridgeTest; @@ -55,6 +56,7 @@ InputConnectionAdaptorTest.class, LocalizationPluginTest.class, PlatformPluginTest.class, + PlatformViewsControllerTest.class, PluginComponentTest.class, PreconditionsTest.class, RenderingComponentTest.class, diff --git a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java index 8b2dfce5fbf0..5317f2feff37 100644 --- a/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java +++ b/shell/platform/android/test/io/flutter/plugin/platform/PlatformViewsControllerTest.java @@ -1,12 +1,19 @@ package io.flutter.plugin.platform; +import static io.flutter.embedding.engine.systemchannels.PlatformViewsChannel.PlatformViewTouch; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import android.view.MotionEvent; import android.view.View; +import io.flutter.embedding.android.MotionEventTracker; +import java.util.Arrays; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -16,6 +23,8 @@ @Config(manifest = Config.NONE) @RunWith(RobolectricTestRunner.class) public class PlatformViewsControllerTest { + + @Ignore @Test public void itNotifiesVirtualDisplayControllersOfViewAttachmentAndDetachment() { // Setup test structure. @@ -58,6 +67,7 @@ public void itNotifiesVirtualDisplayControllersOfViewAttachmentAndDetachment() { verify(fakeVdController2, times(1)).onFlutterViewDetached(); } + @Ignore @Test public void itCancelsOldPresentationOnResize() { // Setup test structure. @@ -79,4 +89,100 @@ public void itCancelsOldPresentationOnResize() { assertEquals(fakeVdController1.presentation != presentation, true); assertEquals(presentation.isShowing(), false); } + + @Test + public void itUsesActionEventTypeFromFrameworkEventForVirtualDisplays() { + MotionEventTracker motionEventTracker = MotionEventTracker.getInstance(); + PlatformViewsController platformViewsController = new PlatformViewsController(); + + MotionEvent original = + MotionEvent.obtain( + 100, // downTime + 100, // eventTime + 1, // action + 0, // x + 0, // y + 0 // metaState + ); + + // track an event that will later get passed to us from framework + MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(original); + + PlatformViewTouch frameWorkTouch = + new PlatformViewTouch( + 0, // viewId + original.getDownTime(), + original.getEventTime(), + 2, // action + 1, // pointerCount + Arrays.asList(Arrays.asList(0, 0)), // pointer properties + Arrays.asList(Arrays.asList(0., 1., 2., 3., 4., 5., 6., 7., 8.)), // pointer coords + original.getMetaState(), + original.getButtonState(), + original.getXPrecision(), + original.getYPrecision(), + original.getDeviceId(), + original.getEdgeFlags(), + original.getSource(), + original.getFlags(), + motionEventId.getId()); + + MotionEvent resolvedEvent = + platformViewsController.toMotionEvent( + 1, // density + frameWorkTouch, + true // usingVirtualDisplays + ); + + assertEquals(resolvedEvent.getAction(), frameWorkTouch.action); + assertNotEquals(resolvedEvent.getAction(), original.getAction()); + } + + @Test + public void itUsesActionEventTypeFromMotionEventForHybridPlatformViews() { + MotionEventTracker motionEventTracker = MotionEventTracker.getInstance(); + PlatformViewsController platformViewsController = new PlatformViewsController(); + + MotionEvent original = + MotionEvent.obtain( + 100, // downTime + 100, // eventTime + 1, // action + 0, // x + 0, // y + 0 // metaState + ); + + // track an event that will later get passed to us from framework + MotionEventTracker.MotionEventId motionEventId = motionEventTracker.track(original); + + PlatformViewTouch frameWorkTouch = + new PlatformViewTouch( + 0, // viewId + original.getDownTime(), + original.getEventTime(), + 2, // action + 1, // pointerCount + Arrays.asList(Arrays.asList(0, 0)), // pointer properties + Arrays.asList(Arrays.asList(0., 1., 2., 3., 4., 5., 6., 7., 8.)), // pointer coords + original.getMetaState(), + original.getButtonState(), + original.getXPrecision(), + original.getYPrecision(), + original.getDeviceId(), + original.getEdgeFlags(), + original.getSource(), + original.getFlags(), + motionEventId.getId()); + + MotionEvent resolvedEvent = + platformViewsController.toMotionEvent( + 1, // density + frameWorkTouch, + false // usingVirtualDisplays + ); + + assertNotEquals(resolvedEvent.getAction(), frameWorkTouch.action); + assertEquals(resolvedEvent.getAction(), original.getAction()); + } }