Add screenshots for Android view (#18367)

diff --git a/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformTextureUiTests.java b/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformTextureUiTests.java
index 927700a..770d1e8 100644
--- a/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformTextureUiTests.java
+++ b/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformTextureUiTests.java
@@ -27,6 +27,8 @@
   @Before
   public void setUp() {
     intent = new Intent(Intent.ACTION_MAIN);
+    // Render a texture.
+    intent.putExtra("use_android_view", false);
   }
 
   @Test
diff --git a/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformViewUiTests.java b/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformViewUiTests.java
new file mode 100644
index 0000000..54fcdf4
--- /dev/null
+++ b/testing/scenario_app/android/app/src/androidTest/java/dev/flutter/scenariosui/PlatformViewUiTests.java
@@ -0,0 +1,99 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package dev.flutter.scenariosui;
+
+import android.content.Intent;
+import androidx.test.filters.LargeTest;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+import dev.flutter.scenarios.TextPlatformViewActivity;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PlatformViewUiTests {
+  Intent intent;
+
+  @Rule
+  public ActivityTestRule<TextPlatformViewActivity> activityRule =
+      new ActivityTestRule<>(
+          TextPlatformViewActivity.class, /*initialTouchMode=*/ false, /*launchActivity=*/ false);
+
+  @Before
+  public void setUp() {
+    intent = new Intent(Intent.ACTION_MAIN);
+    // Render a native android view.
+    intent.putExtra("use_android_view", true);
+  }
+
+  @Test
+  public void testPlatformView() throws Exception {
+    intent.putExtra("scenario", "platform_view");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewMultiple() throws Exception {
+    intent.putExtra("scenario", "platform_view_multiple");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewMultipleBackgroundForeground() throws Exception {
+    intent.putExtra("scenario", "platform_view_multiple_background_foreground");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewCliprect() throws Exception {
+    intent.putExtra("scenario", "platform_view_cliprect");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewCliprrect() throws Exception {
+    intent.putExtra("scenario", "platform_view_cliprrect");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewClippath() throws Exception {
+    intent.putExtra("scenario", "platform_view_clippath");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewTransform() throws Exception {
+    intent.putExtra("scenario", "platform_view_transform");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewOpacity() throws Exception {
+    intent.putExtra("scenario", "platform_view_opacity");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewRotate() throws Exception {
+    intent.putExtra("scenario", "platform_view_rotate");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewMultipleWithoutOverlays() throws Exception {
+    intent.putExtra("scenario", "platform_view_multiple_without_overlays");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+
+  @Test
+  public void testPlatformViewTwoIntersectingOverlays() throws Exception {
+    intent.putExtra("scenario", "platform_view_two_intersecting_overlays");
+    ScreenshotUtil.capture(activityRule.launchActivity(intent));
+  }
+}
diff --git a/testing/scenario_app/android/app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java b/testing/scenario_app/android/app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java
index b4af700..486d848 100644
--- a/testing/scenario_app/android/app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java
+++ b/testing/scenario_app/android/app/src/main/java/dev/flutter/scenarios/TextPlatformViewActivity.java
@@ -20,11 +20,14 @@
 import io.flutter.embedding.engine.loader.FlutterLoader;
 import io.flutter.plugin.common.BasicMessageChannel;
 import io.flutter.plugin.common.BinaryCodec;
-import io.flutter.plugin.common.StringCodec;
+import io.flutter.plugin.common.JSONMethodCodec;
+import io.flutter.plugin.common.MethodChannel;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 public class TextPlatformViewActivity extends TestableFlutterActivity {
@@ -80,10 +83,13 @@
     if (!launchIntent.hasExtra("scenario")) {
       return;
     }
-    BasicMessageChannel<String> channel =
-        new BasicMessageChannel<>(
-            getFlutterEngine().getDartExecutor(), "set_scenario", StringCodec.INSTANCE);
-    channel.send(launchIntent.getStringExtra("scenario"));
+    MethodChannel channel =
+        new MethodChannel(getFlutterEngine().getDartExecutor(), "driver", JSONMethodCodec.INSTANCE);
+    Map<String, Object> test = new HashMap<>(2);
+    test.put("name", launchIntent.getStringExtra("scenario"));
+    test.put("use_android_view", launchIntent.getBooleanExtra("use_android_view", false));
+    channel.invokeMethod("set_scenario", test);
+
     notifyFlutterRenderedAfterVsync();
   }
 
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformView.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformView.png
new file mode 100644
index 0000000..3ec09fc
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformView.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewClippath.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewClippath.png
new file mode 100644
index 0000000..4b99048
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewClippath.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprect.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprect.png
new file mode 100644
index 0000000..3ec09fc
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprect.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png
new file mode 100644
index 0000000..3ec09fc
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewCliprrect.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultiple.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultiple.png
new file mode 100644
index 0000000..3ec09fc
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultiple.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleBackgroundForeground.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleBackgroundForeground.png
new file mode 100644
index 0000000..6326d32
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleBackgroundForeground.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleWithoutOverlays.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleWithoutOverlays.png
new file mode 100644
index 0000000..4e34035
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewMultipleWithoutOverlays.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewOpacity.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewOpacity.png
new file mode 100644
index 0000000..7a91f2a
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewOpacity.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewRotate.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewRotate.png
new file mode 100644
index 0000000..3ec09fc
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewRotate.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTransform.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTransform.png
new file mode 100644
index 0000000..1a2f4b4
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTransform.png
Binary files differ
diff --git a/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTwoIntersectingOverlays.png b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTwoIntersectingOverlays.png
new file mode 100644
index 0000000..4ced8b8
--- /dev/null
+++ b/testing/scenario_app/android/reports/screenshots/dev.flutter.scenariosui.PlatformViewUiTests__testPlatformViewTwoIntersectingOverlays.png
Binary files differ
diff --git a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m
index 95e92ad..9798875 100644
--- a/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m
+++ b/testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m
@@ -89,9 +89,11 @@
   [engine.binaryMessenger
       setMessageHandlerOnChannel:@"waiting_for_status"
             binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) {
-              [engine.binaryMessenger
-                  sendOnChannel:@"set_scenario"
-                        message:[scenarioIdentifier dataUsingEncoding:NSUTF8StringEncoding]];
+              FlutterMethodChannel* channel = [FlutterMethodChannel
+                  methodChannelWithName:@"driver"
+                        binaryMessenger:engine.binaryMessenger
+                                  codec:[FlutterJSONMethodCodec sharedInstance]];
+              [channel invokeMethod:@"set_scenario" arguments:@{@"name" : scenarioIdentifier}];
             }];
   [engine.binaryMessenger
       setMessageHandlerOnChannel:@"touches_scenario"
diff --git a/testing/scenario_app/ios/Scenarios/Scenarios/FlutterEngine+ScenariosTest.m b/testing/scenario_app/ios/Scenarios/Scenarios/FlutterEngine+ScenariosTest.m
index c591917..82aa5bf 100644
--- a/testing/scenario_app/ios/Scenarios/Scenarios/FlutterEngine+ScenariosTest.m
+++ b/testing/scenario_app/ios/Scenarios/Scenarios/FlutterEngine+ScenariosTest.m
@@ -12,16 +12,20 @@
   self = [self initWithName:[NSString stringWithFormat:@"Test engine for %@", scenario]
                     project:nil];
   [self runWithEntrypoint:nil];
-  [self.binaryMessenger
-      setMessageHandlerOnChannel:@"waiting_for_status"
-            binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
-              [self.binaryMessenger
-                  sendOnChannel:@"set_scenario"
-                        message:[scenario dataUsingEncoding:NSUTF8StringEncoding]];
-              if (engineRunCompletion != nil) {
-                engineRunCompletion();
-              }
-            }];
+
+  [self.binaryMessenger setMessageHandlerOnChannel:@"waiting_for_status"
+                              binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
+                                FlutterMethodChannel* channel = [FlutterMethodChannel
+                                    methodChannelWithName:@"driver"
+                                          binaryMessenger:self.binaryMessenger
+                                                    codec:[FlutterJSONMethodCodec sharedInstance]];
+                                [channel invokeMethod:@"set_scenario"
+                                            arguments:@{@"name" : scenario}];
+
+                                if (engineRunCompletion != nil) {
+                                  engineRunCompletion();
+                                }
+                              }];
   return self;
 }
 
diff --git a/testing/scenario_app/lib/main.dart b/testing/scenario_app/lib/main.dart
index 2c97f47..36b903e 100644
--- a/testing/scenario_app/lib/main.dart
+++ b/testing/scenario_app/lib/main.dart
@@ -10,39 +10,7 @@
 import 'dart:typed_data';
 import 'dart:ui';
 
-import 'src/animated_color_square.dart';
-import 'src/platform_view.dart';
-import 'src/poppable_screen.dart';
-import 'src/scenario.dart';
-import 'src/send_text_focus_semantics.dart';
-import 'src/touches_scenario.dart';
-
-Map<String, Scenario> _scenarios = <String, Scenario>{
-  'animated_color_square': AnimatedColorSquareScenario(window),
-  'platform_view': PlatformViewScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_no_overlay_intersection': PlatformViewNoOverlayIntersectionScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_partial_intersection': PlatformViewPartialIntersectionScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_two_intersecting_overlays': PlatformViewTwoIntersectingOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_one_overlay_two_intersecting_overlays': PlatformViewOneOverlayTwoIntersectingOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_multiple_without_overlays': MultiPlatformViewWithoutOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_max_overlays': PlatformViewMaxOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
-  'platform_view_cliprect': PlatformViewClipRectScenario(window, 'PlatformViewClipRect', id: 1),
-  'platform_view_cliprrect': PlatformViewClipRRectScenario(window, 'PlatformViewClipRRect', id: 2),
-  'platform_view_clippath': PlatformViewClipPathScenario(window, 'PlatformViewClipPath', id: 3),
-  'platform_view_transform': PlatformViewTransformScenario(window, 'PlatformViewTransform', id: 4),
-  'platform_view_opacity': PlatformViewOpacityScenario(window, 'PlatformViewOpacity', id: 5),
-  'platform_view_multiple': MultiPlatformViewScenario(window, firstId: 6, secondId: 7),
-  'platform_view_multiple_background_foreground': MultiPlatformViewBackgroundForegroundScenario(window, firstId: 8, secondId: 9),
-  'poppable_screen': PoppableScreenScenario(window),
-  'platform_view_rotate': PlatformViewScenario(window, 'Rotate Platform View', id: 10),
-  'platform_view_gesture_reject_eager': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false),
-  'platform_view_gesture_accept': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: true),
-  'platform_view_gesture_reject_after_touches_ended': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false, rejectUntilTouchesEnded: true),
-  'tap_status_bar': TouchesScenario(window),
-  'text_semantics_focus': SendTextFocusScemantics(window),
-};
-
-Scenario _currentScenario = _scenarios['animated_color_square'];
+import 'src/scenarios.dart';
 
 void main() {
   assert(window.locale != null);
@@ -53,32 +21,38 @@
     ..onMetricsChanged = _onMetricsChanged
     ..onPointerDataPacket = _onPointerDataPacket
     ..scheduleFrame();
+
   final ByteData data = ByteData(1);
   data.setUint8(0, 1);
   window.sendPlatformMessage('waiting_for_status', data, null);
 }
 
+void _handleDriverMessage(Map<String, dynamic> call) {
+  final String methodName = call['method'] as String;
+  switch (methodName) {
+    case 'set_scenario':
+      assert(call['args'] != null);
+      loadScenario(call['args'] as Map<String, dynamic>);
+    break;
+    default:
+      throw 'Unimplemented method: $methodName.';
+  }
+}
+
 Future<void> _handlePlatformMessage(
     String name, ByteData data, PlatformMessageResponseCallback callback) async {
-  print(name);
-  print(utf8.decode(data.buffer.asUint8List()));
-  if (name == 'set_scenario' && data != null) {
-    final String scenarioName = utf8.decode(data.buffer.asUint8List());
-    final Scenario candidateScenario = _scenarios[scenarioName];
-    if (candidateScenario != null) {
-      _currentScenario = candidateScenario;
-      window.scheduleFrame();
-    }
-    if (callback != null) {
-      final ByteData data = ByteData(1);
-      data.setUint8(0, candidateScenario == null ? 0 : 1);
-      callback(data);
-    }
-  } else if (name == 'write_timeline') {
-    final String timelineData = await _getTimelineData();
-    callback(Uint8List.fromList(utf8.encode(timelineData)).buffer.asByteData());
-  } else {
-    _currentScenario?.onPlatformMessage(name, data, callback);
+  print('$name = ${utf8.decode(data.buffer.asUint8List())}');
+
+  switch (name) {
+    case 'driver':
+      _handleDriverMessage(json.decode(utf8.decode(data.buffer.asUint8List())) as Map<String, dynamic>);
+    break;
+    case 'write_timeline':
+      final String timelineData = await _getTimelineData();
+      callback(Uint8List.fromList(utf8.encode(timelineData)).buffer.asByteData());
+    break;
+    default:
+      currentScenario?.onPlatformMessage(name, data, callback);
   }
 }
 
@@ -115,17 +89,17 @@
 }
 
 void _onBeginFrame(Duration duration) {
-  _currentScenario?.onBeginFrame(duration);
+  currentScenario?.onBeginFrame(duration);
 }
 
 void _onDrawFrame() {
-  _currentScenario?.onDrawFrame();
+  currentScenario?.onDrawFrame();
 }
 
 void _onMetricsChanged() {
-  _currentScenario?.onMetricsChanged();
+  currentScenario?.onMetricsChanged();
 }
 
 void _onPointerDataPacket(PointerDataPacket packet) {
-  _currentScenario?.onPointerDataPacket(packet);
+  currentScenario?.onPointerDataPacket(packet);
 }
diff --git a/testing/scenario_app/lib/src/platform_view.dart b/testing/scenario_app/lib/src/platform_view.dart
index 143878f..293569c 100644
--- a/testing/scenario_app/lib/src/platform_view.dart
+++ b/testing/scenario_app/lib/src/platform_view.dart
@@ -10,6 +10,7 @@
 import 'package:vector_math/vector_math_64.dart';
 
 import 'scenario.dart';
+import 'scenarios.dart';
 
 List<int> _to32(int value) {
   final Uint8List temp = Uint8List(4);
@@ -639,8 +640,13 @@
     overlayOffset ??= const Offset(50, 50);
     if (Platform.isIOS) {
       sceneBuilder.addPlatformView(viewId, offset: overlayOffset, width: width, height: height);
-    } else if (Platform.isAndroid && _textureId != null) {
-      sceneBuilder.addTexture(_textureId, offset: overlayOffset, width: width, height: height);
+    } else if (Platform.isAndroid) {
+      if (scenarioParams['use_android_view'] as bool) {
+        // Hybrid composition.
+        sceneBuilder.addPlatformView(viewId, offset: overlayOffset, width: width, height: height);
+      } else if (_textureId != null) {
+        sceneBuilder.addTexture(_textureId, offset: overlayOffset, width: width, height: height);
+      }
     } else {
       throw UnsupportedError('Platform ${Platform.operatingSystem} is not supported');
     }
diff --git a/testing/scenario_app/lib/src/scenarios.dart b/testing/scenario_app/lib/src/scenarios.dart
new file mode 100644
index 0000000..dbfe793
--- /dev/null
+++ b/testing/scenario_app/lib/src/scenarios.dart
@@ -0,0 +1,62 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @dart = 2.6
+import 'dart:ui';
+
+import 'animated_color_square.dart';
+import 'platform_view.dart';
+import 'poppable_screen.dart';
+import 'scenario.dart';
+import 'send_text_focus_semantics.dart';
+import 'touches_scenario.dart';
+
+Map<String, Scenario> _scenarios = <String, Scenario>{
+  'animated_color_square': AnimatedColorSquareScenario(window),
+  'platform_view': PlatformViewScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_no_overlay_intersection': PlatformViewNoOverlayIntersectionScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_partial_intersection': PlatformViewPartialIntersectionScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_two_intersecting_overlays': PlatformViewTwoIntersectingOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_one_overlay_two_intersecting_overlays': PlatformViewOneOverlayTwoIntersectingOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_multiple_without_overlays': MultiPlatformViewWithoutOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_max_overlays': PlatformViewMaxOverlaysScenario(window, 'Hello from Scenarios (Platform View)', id: 0),
+  'platform_view_cliprect': PlatformViewClipRectScenario(window, 'PlatformViewClipRect', id: 1),
+  'platform_view_cliprrect': PlatformViewClipRRectScenario(window, 'PlatformViewClipRRect', id: 2),
+  'platform_view_clippath': PlatformViewClipPathScenario(window, 'PlatformViewClipPath', id: 3),
+  'platform_view_transform': PlatformViewTransformScenario(window, 'PlatformViewTransform', id: 4),
+  'platform_view_opacity': PlatformViewOpacityScenario(window, 'PlatformViewOpacity', id: 5),
+  'platform_view_multiple': MultiPlatformViewScenario(window, firstId: 6, secondId: 7),
+  'platform_view_multiple_background_foreground': MultiPlatformViewBackgroundForegroundScenario(window, firstId: 8, secondId: 9),
+  'poppable_screen': PoppableScreenScenario(window),
+  'platform_view_rotate': PlatformViewScenario(window, 'Rotate Platform View', id: 10),
+  'platform_view_gesture_reject_eager': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false),
+  'platform_view_gesture_accept': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: true),
+  'platform_view_gesture_reject_after_touches_ended': PlatformViewForTouchIOSScenario(window, 'platform view touch', id: 11, accept: false, rejectUntilTouchesEnded: true),
+  'tap_status_bar': TouchesScenario(window),
+  'text_semantics_focus': SendTextFocusScemantics(window),
+};
+
+Map<String, dynamic> _currentScenario = <String, dynamic>{
+  'name': 'animated_color_square',
+};
+
+/// Loads an scenario.
+/// The map must contain a `name` entry, which equals to the name of the scenario.
+void loadScenario(Map<String, dynamic> scenario) {
+  final String scenarioName = scenario['name'] as String;
+  assert(_scenarios[scenarioName] != null);
+  _currentScenario = scenario;
+  window.scheduleFrame();
+  print('Loading scenario $scenarioName');
+}
+
+/// Gets the loaded [Scenario].
+Scenario get currentScenario {
+  return _currentScenario != null ? _scenarios[_currentScenario['name']] : null;
+}
+
+/// Gets the parameters passed to the app over the channel.
+Map<String, dynamic> get scenarioParams {
+  return Map<String, dynamic>.from(_currentScenario);
+}