Added demo projects for splash screen support on Android. (#35728)


diff --git a/dev/automated_tests/pubspec.yaml b/dev/automated_tests/pubspec.yaml
index 394f362..219092e 100644
--- a/dev/automated_tests/pubspec.yaml
+++ b/dev/automated_tests/pubspec.yaml
@@ -34,7 +34,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
   assets:
   - icon/
 
-# PUBSPEC CHECKSUM: c729
+# PUBSPEC CHECKSUM: b02a
diff --git a/dev/benchmarks/complex_layout/pubspec.yaml b/dev/benchmarks/complex_layout/pubspec.yaml
index 7aa11fb..632ded5 100644
--- a/dev/benchmarks/complex_layout/pubspec.yaml
+++ b/dev/benchmarks/complex_layout/pubspec.yaml
@@ -58,7 +58,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -82,4 +82,4 @@
     - packages/flutter_gallery_assets/people/square/ali.png
     - packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png
 
-# PUBSPEC CHECKSUM: 78b8
+# PUBSPEC CHECKSUM: 61b9
diff --git a/dev/benchmarks/macrobenchmarks/pubspec.yaml b/dev/benchmarks/macrobenchmarks/pubspec.yaml
index dba376c..f82755a 100644
--- a/dev/benchmarks/macrobenchmarks/pubspec.yaml
+++ b/dev/benchmarks/macrobenchmarks/pubspec.yaml
@@ -58,7 +58,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -79,4 +79,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 78b8
+# PUBSPEC CHECKSUM: 61b9
diff --git a/dev/benchmarks/microbenchmarks/pubspec.yaml b/dev/benchmarks/microbenchmarks/pubspec.yaml
index 7415529..4b77a03 100644
--- a/dev/benchmarks/microbenchmarks/pubspec.yaml
+++ b/dev/benchmarks/microbenchmarks/pubspec.yaml
@@ -41,7 +41,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -73,4 +73,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 398e
+# PUBSPEC CHECKSUM: 468f
diff --git a/dev/bots/pubspec.yaml b/dev/bots/pubspec.yaml
index 2710a88..b00955d 100644
--- a/dev/bots/pubspec.yaml
+++ b/dev/bots/pubspec.yaml
@@ -39,7 +39,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
   mockito: 4.1.0
   test_api: 0.2.5
 
-# PUBSPEC CHECKSUM: 058a
+# PUBSPEC CHECKSUM: e98b
diff --git a/dev/devicelab/README.md b/dev/devicelab/README.md
index 6bc1d7a..882726d 100644
--- a/dev/devicelab/README.md
+++ b/dev/devicelab/README.md
@@ -154,6 +154,19 @@
 ../../bin/cache/dart-sdk/bin/dart bin/run.dart -s {NAME_OF_STAGE}
 ```
 
+## Running tests against a local engine build
+
+To run device lab tests against a local engine build, pass the appropriate
+flags to `bin/run.dart`:
+
+```sh
+../../bin/cache/dart-sdk/bin/dart bin/run.dart --task=[some_task] \
+  --local-engine-src-path=[path_to_local]/engine/src \
+  --local-engine=[local_engine_architecture]
+```
+
+An example of of a local engine architecture is `android_debug_unopt_x86`.
+
 # Reproducing broken builds locally
 
 To reproduce the breakage locally `git checkout` the corresponding Flutter
diff --git a/dev/devicelab/bin/tasks/android_splash_screen_integration_test.dart b/dev/devicelab/bin/tasks/android_splash_screen_integration_test.dart
new file mode 100644
index 0000000..0cbe7e0
--- /dev/null
+++ b/dev/devicelab/bin/tasks/android_splash_screen_integration_test.dart
@@ -0,0 +1,12 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/tasks/integration_tests.dart';
+
+Future<void> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.android;
+  await task(createAndroidSplashScreenKitchenSinkTest());
+}
diff --git a/dev/devicelab/lib/tasks/integration_tests.dart b/dev/devicelab/lib/tasks/integration_tests.dart
index a940a24..f53f5cf 100644
--- a/dev/devicelab/lib/tasks/integration_tests.dart
+++ b/dev/devicelab/lib/tasks/integration_tests.dart
@@ -101,6 +101,13 @@
   };
 }
 
+TaskFunction createAndroidSplashScreenKitchenSinkTest() {
+  return DriverTest(
+    '${flutterDirectory.path}/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink',
+    'test_driver/main.dart',
+  );
+}
+
 class DriverTest {
 
   DriverTest(
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index bb8ea8e..5cc3573 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -632,3 +632,9 @@
     stage: devicelab
     required_agent_capabilities: ["mac/android"]
     flaky: true
+
+  android_splash_screen_integration_test:
+    description: >
+      Runs end-to-end test of Flutter's Android splash behavior.
+    stage: devicelab
+    required_agent_capabilities: ["linux/android"]
diff --git a/dev/devicelab/pubspec.yaml b/dev/devicelab/pubspec.yaml
index 233dd3e..210141b 100644
--- a/dev/devicelab/pubspec.yaml
+++ b/dev/devicelab/pubspec.yaml
@@ -56,7 +56,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -73,4 +73,4 @@
   watcher: 0.9.7+12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   yaml: 2.1.16 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: aa03
+# PUBSPEC CHECKSUM: c704
diff --git a/dev/integration_tests/android_semantics_testing/pubspec.yaml b/dev/integration_tests/android_semantics_testing/pubspec.yaml
index b0854e0..22974ac 100644
--- a/dev/integration_tests/android_semantics_testing/pubspec.yaml
+++ b/dev/integration_tests/android_semantics_testing/pubspec.yaml
@@ -33,7 +33,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -63,4 +63,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore
new file mode 100644
index 0000000..ac4a906
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore
@@ -0,0 +1,72 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.metadata b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.metadata
new file mode 100644
index 0000000..693ab4f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 87a4fb567bcd3db87eb49f80d13e8ef95cfaa21e
+  channel: unknown
+
+project_type: app
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/README.md b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/README.md
new file mode 100644
index 0000000..49c2cf0
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/README.md
@@ -0,0 +1,23 @@
+# Splash Demo: Kitchen Sink
+
+This project is an example of a splash screen that shows a logo for a launch screen and then
+zooms that logo towards the screen while fading content beneath it, masked by the logo.
+
+The purpose of this example project is to push the limits of what Flutter's splash system affords.
+
+This project is also run as a device lab test via Flutter Driver.
+
+The files that are relevant to test execution are:
+
+ - /test_driver/main.dart
+ - /test_driver/main_test.dart
+ - /android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/MainActivity.java
+ 
+ The files that should be inspected to learn about splash behavior are:
+ 
+ - /android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashScreen.java
+ - /android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashView.java
+ 
+ Communication takes place from Android to Flutter to Driver to communicate splash screen events.
+ This communication takes place over a channel called "testChannel", whose definition can be
+ found in `MainActivity.java` and `test_driver/main.dart`.
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/build.gradle
new file mode 100644
index 0000000..6f6f4f0
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/build.gradle
@@ -0,0 +1,65 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion 28
+
+    lintOptions {
+        disable 'InvalidPackage'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "io.flutter.splash_screen_kitchen_sink"
+        minSdkVersion 16
+        targetSdkVersion 28
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation 'androidx.fragment:fragment:1.1.0-beta01'
+    implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0-alpha01'
+    implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0-alpha01'
+
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/debug/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..3c723cc
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_kitchen_sink">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7b4f097
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_kitchen_sink">
+
+    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
+         calls FlutterMain.startInitialization(this); in its onCreate method.
+         In most cases you can leave this as-is, but you if you want to provide
+         additional functionality it is fine to subclass or reimplement
+         FlutterApplication and put your custom class here. -->
+    <application
+        android:name="io.flutter.app.FlutterApplication"
+        android:label="splash_screen_kitchen_sink"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <meta-data
+                android:name="io.flutter.embedding.android.SplashScreenDrawable"
+                android:resource="@drawable/launch_background" />
+            <meta-data
+                android:name="io.flutter.embedding.android.NormalTheme"
+                android:resource="@style/NormalTheme"
+                />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashScreen.java b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashScreen.java
new file mode 100644
index 0000000..e53a7e3
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashScreen.java
@@ -0,0 +1,64 @@
+package io.flutter.splash_screen_kitchen_sink;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import io.flutter.embedding.android.SplashScreen;
+
+/**
+ * {@code SplashScreen} that displays a yellow splash screen {@code View}, which slowly fades
+ * out when Flutter is ready.
+ * <p>
+ * See {@link VeryLongTransitionSplashView} for visual details.
+ */
+public class FlutterZoomSplashScreen implements SplashScreen {
+  private FlutterZoomSplashView splashView;
+
+  @Override
+  public View createSplashView(@NonNull Context context, @Nullable Bundle savedInstanceState) {
+    splashView = new FlutterZoomSplashView(context);
+    splashView.restoreSplashState(savedInstanceState);
+    return splashView;
+  }
+
+  @Override
+  public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
+    if (splashView != null) {
+      splashView.transitionToFlutter(onTransitionComplete);
+    } else {
+      onTransitionComplete.run();
+    }
+  }
+
+  /**
+   * Informs Flutter that we are capable of restoring a transition that was previously
+   * in progress.
+   * <p>
+   * A splash transition can be interrupted by configuration changes or other OS operations.
+   * <p>
+   * If we were to return false here, then an orientation change would skip the rest of
+   * the transition and jump directly to the Flutter UI.
+   */
+  @Override
+  public boolean doesSplashViewRememberItsTransition() {
+    return true;
+  }
+
+  /**
+   * Saves the state of our {@code splashView} so that we can restore the long fade transition
+   * when we are recreated after a config change or other recreation event.
+   */
+  @Override
+  @Nullable
+  public Bundle saveSplashScreenState() {
+    if (splashView != null) {
+      return splashView.saveSplashState();
+    } else {
+      return null;
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashView.java b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashView.java
new file mode 100644
index 0000000..e1270a8
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/FlutterZoomSplashView.java
@@ -0,0 +1,156 @@
+package io.flutter.splash_screen_kitchen_sink;
+
+import android.animation.TimeAnimator;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.ScaleAnimation;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+
+public class FlutterZoomSplashView extends FrameLayout {
+  private static final String TAG = "FlutterZoomSplashView";
+
+  private float transitionPercentWhenAnimationStarted = 0.0f;
+  private float totalTransitionPercent = 0.0f;
+  private Runnable onTransitionComplete;
+  private View whiteUnderlay;
+  private ImageView imageView;
+  private AnimationSet transitionAnimation;
+  private TimeAnimator timeAnimator;
+
+  private final TimeAnimator.TimeListener timeListener = new TimeAnimator.TimeListener() {
+    @Override
+    public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+      // We have to represent transition percent as a starting value + the fraction of the
+      // running animation. This is because there is no way to start an Animator and inform
+      // it that it should already be X percent complete.
+      totalTransitionPercent = transitionPercentWhenAnimationStarted
+          + (animation.getAnimatedFraction() * (1.0f - transitionPercentWhenAnimationStarted));
+    }
+  };
+
+  private final Animation.AnimationListener animationListener = new Animation.AnimationListener() {
+    @Override
+    public void onAnimationStart(Animation animation) {}
+
+    @Override
+    public void onAnimationEnd(Animation animation) {
+      Log.d(TAG, "Animation ended.");
+      transitionAnimation = null;
+      animation.setAnimationListener(null);
+
+      timeAnimator.cancel();
+      timeAnimator.setTimeListener(null);
+
+      onTransitionComplete.run();
+    }
+
+    @Override
+    public void onAnimationRepeat(Animation animation) {}
+  };
+
+  public FlutterZoomSplashView(Context context) {
+    super(context);
+    Log.d(TAG, "Creating FlutterZoomSplashView");
+
+    whiteUnderlay = new View(getContext());
+    whiteUnderlay.setBackgroundColor(Color.WHITE);
+    addView(whiteUnderlay);
+
+    imageView = new ImageView(getContext());
+    imageView.setImageDrawable(getResources().getDrawable(R.drawable.splash_screen, getContext().getTheme()));
+    imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+    addView(imageView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+  }
+
+  public void transitionToFlutter(Runnable onTransitionComplete) {
+    Log.d(TAG, "Animating transition.");
+    this.onTransitionComplete = onTransitionComplete;
+    animateWhiteUnderlay();
+    animateLogoOverlay();
+  }
+
+  private void animateWhiteUnderlay() {
+    AlphaAnimation fadeOut = new AlphaAnimation(1f, 0f);
+    fadeOut.setStartOffset(0);
+    fadeOut.setDuration(500);
+
+    whiteUnderlay.startAnimation(fadeOut);
+  }
+
+  @SuppressLint("NewApi")
+  private void animateLogoOverlay() {
+    // Notice that each animation might begin part way through the animation based on
+    // a previous transition amount that we need to restore.
+    float startAlpha = 1f - totalTransitionPercent;
+    long fadeStartDelay = Math.round(400 * (1.0 - (Math.min(totalTransitionPercent, 0.8) / 0.8)));
+    long fadeDuration = Math.round(100 * (1.0 - Math.max(0, (totalTransitionPercent - 0.8)) / 0.2));
+
+    float startScale = 1f + (7f * totalTransitionPercent);
+    long scaleDuration = Math.round(500 * (1.0 - totalTransitionPercent));
+
+    long globalTimerLength = Math.round(500 * (1.0 - totalTransitionPercent));
+
+    Animation scaleUp = new ScaleAnimation(
+        startScale, 8f,
+        startScale, 8f,
+        Animation.RELATIVE_TO_SELF, 0.5f,
+        Animation.RELATIVE_TO_SELF, 0.5f
+    );
+    scaleUp.setFillAfter(true);
+    scaleUp.setDuration(scaleDuration);
+    scaleUp.setInterpolator(new AccelerateInterpolator());
+
+    AlphaAnimation fadeOut = new AlphaAnimation(startAlpha, 0f);
+    fadeOut.setStartOffset(fadeStartDelay);
+    fadeOut.setDuration(fadeDuration);
+
+    transitionAnimation = new AnimationSet(false);
+    transitionAnimation.addAnimation(scaleUp);
+    transitionAnimation.addAnimation(fadeOut);
+    transitionAnimation.setFillAfter(true);
+    transitionAnimation.setAnimationListener(animationListener);
+
+    timeAnimator = new TimeAnimator();
+    timeAnimator.setDuration(globalTimerLength);
+    timeAnimator.setTimeListener(timeListener);
+
+    imageView.startAnimation(transitionAnimation);
+    timeAnimator.start();
+  }
+
+  @Nullable
+  public Bundle saveSplashState() {
+    Log.d(TAG, "Saving splash state.");
+    if (totalTransitionPercent > 0.0f && totalTransitionPercent < 1.0f) {
+      Bundle state = new Bundle();
+      state.putFloat("totalTransitionPercent", totalTransitionPercent);
+      Log.d(TAG, String.format("Transition percent: %.2f", totalTransitionPercent));
+      return state;
+    } else {
+      Log.d(TAG, "No transition to save.");
+      return null;
+    }
+  }
+
+  public void restoreSplashState(@Nullable Bundle bundle) {
+    Log.d(TAG, "Restoring splash state: " + bundle);
+    if (bundle != null) {
+      transitionPercentWhenAnimationStarted = bundle.getFloat("totalTransitionPercent");
+      Log.d(TAG, String.format("State restored with transition percent: %.2f", transitionPercentWhenAnimationStarted));
+    } else {
+      Log.d(TAG, "No state provided.");
+    }
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/MainActivity.java b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/MainActivity.java
new file mode 100644
index 0000000..8892ea9
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/java/io/flutter/splash_screen_kitchen_sink/MainActivity.java
@@ -0,0 +1,190 @@
+package io.flutter.splash_screen_kitchen_sink;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import androidx.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.android.FlutterView;
+import io.flutter.embedding.android.SplashScreen;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.embedding.engine.dart.DartExecutor;
+import io.flutter.plugin.common.BasicMessageChannel;
+import io.flutter.plugin.common.StringCodec;
+import io.flutter.view.FlutterMain;
+
+public class MainActivity extends FlutterActivity {
+  private static final String TAG = "MainActivity";
+
+  private static FlutterEngine flutterEngine;
+
+  static {
+    // Explicitly activates Debug logging for the Flutter Android embedding.
+    io.flutter.Log.setLogLevel(Log.DEBUG);
+  }
+
+  // Sends a JSON-serialized log of test events from Android to Flutter.
+  private BasicMessageChannel<String> testChannel;
+  // Log of splash events that is updated, serialized, and sent to Flutter.
+  private SplashTestLog splashTestLog;
+
+  /**
+   * We explicitly provide a {@code FlutterEngine} so that every rotation does not create a
+   * new FlutterEngine. Creating a new FlutterEngine on every orientation would cause the
+   * splash experience to restart upon every orientation change, which is not what we're
+   * interested in verifying in this example app.
+   */
+  @Override
+  public FlutterEngine provideFlutterEngine(Context context) {
+    if (flutterEngine == null) {
+      flutterEngine = new FlutterEngine(context);
+
+      flutterEngine.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(
+          getAssets(),
+          FlutterMain.findAppBundlePath(context),
+          "main"
+      ));
+
+      // Setup the channel that sends splash test log updates from Android to Flutter.
+      testChannel = new BasicMessageChannel<>(
+          flutterEngine.getDartExecutor(),
+          "testChannel",
+          StringCodec.INSTANCE
+      );
+
+      // Initialize the splash test log that accumulates events.
+      splashTestLog = new SplashTestLog();
+
+      // Send initial splash test log.
+      updateLogAndSendToFlutter();
+
+      // List for any layout change, look for splash test updates, and if
+      // there are any, add them to the log and send them to Flutter.
+      getWindow().getDecorView().getRootView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+        @Override
+        public void onGlobalLayout() {
+          updateLogAndSendToFlutter();
+        }
+      });
+    }
+    return flutterEngine;
+  }
+
+  private void updateLogAndSendToFlutter() {
+    // Look for the existence of a FlutterView and the existence of a
+    // splash screen View on top of it.
+    View flutterView = findViewByType(FlutterView.class);
+    boolean isSplashAvailable = false;
+    if (flutterView != null) {
+      ViewGroup flutterViewParent = (ViewGroup) flutterView.getParent();
+      isSplashAvailable = flutterViewParent.getChildCount() > 1;
+    }
+
+    // Update the splash test log.
+    splashTestLog.update(flutterView != null, isSplashAvailable);
+
+    // Send the latest version of the splash test log to Flutter.
+    testChannel.send(splashTestLog.serialize());
+  }
+
+  /**
+   * Finds an Android {@code View} in this {@code Activity}'s {@code View} hierarchy
+   * that matches the given {@code viewType}.
+   *
+   * This method searches the {@code View} hierarchy breadth-first.
+   */
+  private View findViewByType(Class<? extends View> viewType) {
+    View selectedView = getWindow().getDecorView().getRootView();//findViewById(0x01020002);
+    List<View> viewQueue = new ArrayList<>();
+
+    while (selectedView != null && !selectedView.getClass().equals(viewType)) {
+      if (selectedView instanceof ViewGroup) {
+        ViewGroup selectedViewGroup = (ViewGroup) selectedView;
+        for (int i = 0; i < selectedViewGroup.getChildCount(); ++i) {
+          viewQueue.add(selectedViewGroup.getChildAt(i));
+        }
+      }
+
+      if (!viewQueue.isEmpty()) {
+        selectedView = viewQueue.remove(0);
+      } else {
+        selectedView = null;
+      }
+    }
+
+    return selectedView;
+  }
+
+  @Override
+  @Nullable
+  public SplashScreen provideSplashScreen() {
+    return new FlutterZoomSplashScreen();
+  }
+
+  /**
+   * Log of splash UI changes that is used to verify the correctness of
+   * splash behavior.
+   */
+  private static class SplashTestLog {
+    private List<TestState> eventLog = new ArrayList<>();
+
+    SplashTestLog() {
+      eventLog.add(TestState.WAITING_FOR_LAYOUT);
+    }
+
+    void update(boolean isFlutterViewAvailable, boolean isSplashAvailable) {
+      TestState newTestState = TestState.WAITING_FOR_LAYOUT;
+      if (isFlutterViewAvailable) {
+        newTestState = isSplashAvailable ? TestState.SPLASH_SHOWING : TestState.SPLASH_NOT_SHOWING;
+      }
+
+      if (newTestState != eventLog.get(eventLog.size() - 1)) {
+        eventLog.add(newTestState);
+      }
+    }
+
+    String serialize() {
+      return "{\"events\":[" + serializeEvents() + "]}";
+    }
+
+    private String serializeEvents() {
+      StringBuilder stringBuilder = new StringBuilder();
+      for (int i = 0; i < eventLog.size(); ++i) {
+        stringBuilder.append(serializeEvent(eventLog.get(i)));
+        if (i < (eventLog.size() - 1)) {
+          stringBuilder.append(",");
+        }
+      }
+      return stringBuilder.toString();
+    }
+
+    private String serializeEvent(TestState event) {
+      switch (event) {
+        case WAITING_FOR_LAYOUT:
+          return "\"waiting_for_layout\"";
+        case SPLASH_SHOWING:
+          return "\"splash_showing\"";
+        case SPLASH_NOT_SHOWING:
+          return "\"splash_not_showing\"";
+        default:
+          throw new IllegalStateException("Received non-existent TestState.");
+      }
+    }
+  }
+
+  /**
+   * States of splash display in this test project.
+   */
+  private enum TestState {
+    WAITING_FOR_LAYOUT,
+    SPLASH_SHOWING,
+    SPLASH_NOT_SHOWING;
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable-land/launch_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable-land/launch_background.xml
new file mode 100644
index 0000000..884d00c
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable-land/launch_background.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/flutter_splash_screen"
+            />
+    </item>
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/launch_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..975922d
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+
+    <!-- You can insert your own image assets here -->
+    <item>
+        <bitmap
+            android:gravity="fill"
+            android:src="@mipmap/flutter_splash_screen"
+            />
+    </item>
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/normal_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/normal_background.xml
new file mode 100644
index 0000000..5782842
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/normal_background.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/splash_screen.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/splash_screen.xml
new file mode 100644
index 0000000..f71b51c
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/drawable/splash_screen.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- You can insert your own image assets here -->
+    <item>
+        <bitmap
+            android:gravity="fill_horizontal|fill_vertical"
+            android:src="@mipmap/flutter_splash_screen"
+            />
+    </item>
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/values/styles.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..b710ac7
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">@drawable/normal_background</item>
+    </style>
+</resources>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/profile/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..3c723cc
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_kitchen_sink">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/build.gradle
new file mode 100644
index 0000000..bb8a303
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/build.gradle
@@ -0,0 +1,29 @@
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.2.1'
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle.properties b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..2819f02
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/settings.gradle b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/settings.gradle
new file mode 100644
index 0000000..5a2f14f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/android/settings.gradle
@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
+}
+
+plugins.each { name, path ->
+    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+    include ":$name"
+    project(":$name").projectDir = pluginDirectory
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/lib/main.dart b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/lib/main.dart
new file mode 100644
index 0000000..5c6edd3
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/lib/main.dart
@@ -0,0 +1,114 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+import 'package:flutter/material.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+  // This widget is the root of your application.
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        // This is the theme of your application.
+        //
+        // Try running your application with "flutter run". You'll see the
+        // application has a blue toolbar. Then, without quitting the app, try
+        // changing the primarySwatch below to Colors.green and then invoke
+        // "hot reload" (press "r" in the console where you ran "flutter run",
+        // or simply save your changes to "hot reload" in a Flutter IDE).
+        // Notice that the counter didn't reset back to zero; the application
+        // is not restarted.
+        primarySwatch: Colors.blue,
+      ),
+      home: const MyHomePage(title: 'Flutter Demo Home Page'),
+    );
+  }
+}
+
+class MyHomePage extends StatefulWidget {
+  const MyHomePage({Key key, this.title}) : super(key: key);
+
+  // This widget is the home page of your application. It is stateful, meaning
+  // that it has a State object (defined below) that contains fields that affect
+  // how it looks.
+
+  // This class is the configuration for the state. It holds the values (in this
+  // case the title) provided by the parent (in this case the App widget) and
+  // used by the build method of the State. Fields in a Widget subclass are
+  // always marked "final".
+
+  final String title;
+
+  @override
+  _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  int _counter = 0;
+
+  void _incrementCounter() {
+    setState(() {
+      // This call to setState tells the Flutter framework that something has
+      // changed in this State, which causes it to rerun the build method below
+      // so that the display can reflect the updated values. If we changed
+      // _counter without calling setState(), then the build method would not be
+      // called again, and so nothing would appear to happen.
+      _counter++;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    // This method is rerun every time setState is called, for instance as done
+    // by the _incrementCounter method above.
+    //
+    // The Flutter framework has been optimized to make rerunning build methods
+    // fast, so that you can just rebuild anything that needs updating rather
+    // than having to individually change instances of widgets.
+    return Scaffold(
+      appBar: AppBar(
+        // Here we take the value from the MyHomePage object that was created by
+        // the App.build method, and use it to set our appbar title.
+        title: Text(widget.title),
+      ),
+      body: Center(
+        // Center is a layout widget. It takes a single child and positions it
+        // in the middle of the parent.
+        child: Column(
+          // Column is also layout widget. It takes a list of children and
+          // arranges them vertically. By default, it sizes itself to fit its
+          // children horizontally, and tries to be as tall as its parent.
+          //
+          // Invoke "debug painting" (press "p" in the console, choose the
+          // "Toggle Debug Paint" action from the Flutter Inspector in Android
+          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
+          // to see the wireframe for each widget.
+          //
+          // Column has various properties to control how it sizes itself and
+          // how it positions its children. Here we use mainAxisAlignment to
+          // center the children vertically; the main axis here is the vertical
+          // axis because Columns are vertical (the cross axis would be
+          // horizontal).
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            const Text(
+              'You have pushed the button this many times:',
+            ),
+            Text(
+              '$_counter',
+              style: Theme.of(context).textTheme.display1,
+            ),
+          ],
+        ),
+      ),
+      floatingActionButton: FloatingActionButton(
+        onPressed: _incrementCounter,
+        tooltip: 'Increment',
+        child: Icon(Icons.add),
+      ), // This trailing comma makes auto-formatting nicer for build methods.
+    );
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml
new file mode 100644
index 0000000..ec3cb22
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/pubspec.yaml
@@ -0,0 +1,132 @@
+name: splash_screen_kitchen_sink
+description: A new Flutter application.
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.1.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: 0.1.2
+
+  collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  typed_data: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  vector_math: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+  flutter_driver:
+    sdk: flutter
+  test: 1.6.3
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+
+  analyzer: 0.36.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  args: 1.5.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  async: 2.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  boolean_selector: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  csslib: 0.16.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  file: 5.0.8+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.19 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  html: 0.14.0+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http: 0.12.0+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http_multi_server: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  intl: 0.15.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  json_rpc_2: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.19 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf: 0.7.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_web_socket: 0.2.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stream_channel: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  test_api: 0.2.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  test_core: 0.2.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  vm_service_client: 0.2.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  watcher: 0.9.7+12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  web_socket_channel: 1.0.14 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  yaml: 2.1.16 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #  - images/a_dot_burr.jpeg
+  #  - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware.
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
+
+# PUBSPEC CHECKSUM: e85f
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test/widget_test.dart b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test/widget_test.dart
new file mode 100644
index 0000000..7b13525
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:splash_screen_kitchen_sink/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main.dart b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main.dart
new file mode 100644
index 0000000..b939220
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main.dart
@@ -0,0 +1,54 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+import 'dart:async';
+
+import 'package:flutter_driver/driver_extension.dart';
+import 'package:flutter/services.dart';
+import 'package:splash_screen_kitchen_sink/main.dart' as app;
+
+Completer<String> dataHandlerCompleter;
+final List<String> appToHostMessageQueue = <String>[];
+
+/// How this test works:
+/// 1. Android's UI changes as the app starts up.
+/// 2. Android sends messages to this Flutter app about those UI changes.
+/// 3. This Flutter app forwards those messages from the app to the host
+///    machine running the driver test.
+/// 4. The driver test evaluates the UI change events to determine if the
+///    behavior is expected or unexpected and then passes or fails the test.
+void main() {
+  enableFlutterDriverExtension(handler: respondToHostRequestForSplashLog);
+
+  createTestChannelBetweenAndroidAndFlutter();
+
+  app.main();
+}
+
+Future<String> respondToHostRequestForSplashLog(String _) {
+  if (appToHostMessageQueue.isNotEmpty) {
+    return Future<String>.value(appToHostMessageQueue.removeAt(0));
+  } else {
+    dataHandlerCompleter = Completer<String>();
+    return dataHandlerCompleter.future;
+  }
+}
+
+void createTestChannelBetweenAndroidAndFlutter() {
+  // Channel used for Android to send Flutter changes to the splash display.
+  final BasicMessageChannel<String> testChannel = BasicMessageChannel<String>(
+      'testChannel',
+      const StringCodec()
+  );
+
+  // Every splash display change message that we receive from Android is either
+  // immediately sent to the host driver test, or queued up to be sent to the
+  // host driver test at the next opportunity.
+  testChannel.setMessageHandler((String message) async {
+    appToHostMessageQueue.add(message);
+    if (dataHandlerCompleter != null) {
+      dataHandlerCompleter.complete(appToHostMessageQueue.removeAt(0));
+    }
+    return '';
+  });
+}
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main_test.dart b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main_test.dart
new file mode 100644
index 0000000..c97b12b
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/test_driver/main_test.dart
@@ -0,0 +1,77 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
+
+void main() {
+  group('end-to-end test', () {
+    FlutterDriver driver;
+
+    setUpAll(() async {
+      driver = await FlutterDriver.connect();
+    });
+
+    tearDownAll(() async {
+      await driver?.close();
+    });
+
+    test('Flutter experience eventually appears', () async {
+      final SerializableFinder fabFinder = find.byTooltip('Increment');
+
+      // Ensure that the Flutter experience eventually becomes visible.
+      // We combined two verifications for this purpose:
+      //
+      // 1. We verify that we can find the expected FAB, and
+      //
+      // 2. We verify that Android thinks the splash screen has been removed.
+      await driver.waitFor(fabFinder);
+
+      await _waitForSplashToDisappear(driver).timeout(
+        const Duration(seconds: 10),
+        onTimeout: () {
+          throw Exception('Splash screen never disappeared.');
+        },
+      );
+    });
+  });
+}
+
+Future<void> _waitForSplashToDisappear(FlutterDriver driver) async {
+  bool waitingForSplashToDisappear = true;
+
+  while (waitingForSplashToDisappear) {
+    final String response = await driver.requestData('splash_test_log',);
+
+    final Map<String, dynamic> splashTestLog = jsonDecode(response);
+    final List<dynamic> events = splashTestLog['events'];
+    if (events.length == 3) {
+      expect(
+          events[0],
+          equals('waiting_for_layout'),
+          reason: 'Expected first splash event to be '
+              '"waiting_for_layout" but it was "${events[0]}"',
+      );
+      expect(
+          events[1],
+          equals('splash_showing'),
+          reason: 'Expected second splash event to be '
+              '"splash_showing" but it was "${events[1]}"',
+      );
+      expect(
+          events[2],
+          equals('splash_not_showing'),
+          reason: 'Expected third splash event to be '
+              '"splash_not_showing" but it was "${events[2]}"',
+      );
+      waitingForSplashToDisappear = false;
+    } else if (events.length > 3) {
+      throw Exception('Expected 3 splash test events but received '
+          '${events.length} events: $events');
+    }
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore
new file mode 100644
index 0000000..ac4a906
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore
@@ -0,0 +1,72 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.metadata b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.metadata
new file mode 100644
index 0000000..693ab4f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 87a4fb567bcd3db87eb49f80d13e8ef95cfaa21e
+  channel: unknown
+
+project_type: app
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/README.md b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/README.md
new file mode 100644
index 0000000..bd7b494
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/README.md
@@ -0,0 +1,7 @@
+# Splash Demo: Never ending splash animation
+
+This project is an example of a splash screen that displays an animation indefinitely.
+
+A never ending animation is provided as a demo so that developers can manually verify that 
+orientation changes and other UI destruction processes do not cause issues with Flutter's splash 
+system for Android. 
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/build.gradle
new file mode 100644
index 0000000..c50db13
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/build.gradle
@@ -0,0 +1,65 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion 28
+
+    lintOptions {
+        disable 'InvalidPackage'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "io.flutter.splash_screen_load_rotate"
+        minSdkVersion 16
+        targetSdkVersion 28
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation 'androidx.fragment:fragment:1.1.0-beta01'
+    implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0-alpha01'
+    implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0-alpha01'
+
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/debug/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..75b88d6
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_load_rotate">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f42bdad
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_load_rotate">
+
+    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
+         calls FlutterMain.startInitialization(this); in its onCreate method.
+         In most cases you can leave this as-is, but you if you want to provide
+         additional functionality it is fine to subclass or reimplement
+         FlutterApplication and put your custom class here. -->
+    <application
+        android:name="io.flutter.app.FlutterApplication"
+        android:label="splash_screen_load_rotate"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <meta-data
+                android:name="io.flutter.embedding.android.SplashScreenDrawable"
+                android:resource="@drawable/launch_background" />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/MainActivity.java b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/MainActivity.java
new file mode 100644
index 0000000..bf95489
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/MainActivity.java
@@ -0,0 +1,38 @@
+package io.flutter.splash_screen_load_rotate;
+
+import android.content.Context;
+
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.android.SplashScreen;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.embedding.engine.dart.DartExecutor;
+import io.flutter.view.FlutterMain;
+
+public class MainActivity extends FlutterActivity {
+  private static FlutterEngine flutterEngine;
+
+  /**
+   * We explicitly provide a {@code FlutterEngine} so that every rotation does not create a
+   * new FlutterEngine. Creating a new FlutterEngine on every orientation would cause the
+   * splash experience to restart upon every orientation change, which is not what we're
+   * interested in verifying in this example app.
+   */
+  @Override
+  public FlutterEngine provideFlutterEngine(Context context) {
+    if (flutterEngine == null) {
+      flutterEngine = new FlutterEngine(context);
+
+      flutterEngine.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(
+          getAssets(),
+          FlutterMain.findAppBundlePath(context),
+          "main"
+      ));
+    }
+    return flutterEngine;
+  }
+
+  @Override
+  public SplashScreen provideSplashScreen() {
+    return new SplashScreenThatNeverEnds();
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/NeverEndingSplashView.java b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/NeverEndingSplashView.java
new file mode 100644
index 0000000..487d51d
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/NeverEndingSplashView.java
@@ -0,0 +1,110 @@
+package io.flutter.splash_screen_load_rotate;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class NeverEndingSplashView extends FrameLayout {
+  private static final String TAG = "NeverEndingSplashView";
+
+  private static final float ANIMATION_SLIDE_DISTANCE = 800;
+  private static final int ANIMATION_TIME_IN_MILLIS = 5000;
+
+  private final View animatedThing;
+  private float destinationTranslationY = 0;
+  private ViewPropertyAnimator animator;
+
+  private final Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
+    @SuppressLint("NewApi")
+    @Override
+    public void onAnimationEnd(Animator animation) {
+      // Remove all animation listeners to avoid memory leaks.
+      animation.removeAllListeners();
+
+      // Start the next animation by reversing direction.
+      if (destinationTranslationY < 0) {
+        animateTheThing(ANIMATION_SLIDE_DISTANCE / 2);
+      } else {
+        animateTheThing(-ANIMATION_SLIDE_DISTANCE / 2);
+      }
+    }
+
+    @SuppressLint("NewApi")
+    @Override
+    public void onAnimationCancel(Animator animation) {
+      // Remove all animation listeners to avoid memory leaks.
+      animation.removeAllListeners();
+    }
+  };
+
+  @SuppressLint("NewApi")
+  public NeverEndingSplashView(Context context) {
+    super(context);
+    // Give the UI a yellow background to prove that this splash screen view takes up
+    // all available space.
+    setBackgroundColor(Color.YELLOW);
+
+    // Create and display a little square that slides up and down.
+    animatedThing = new View(context);
+    animatedThing.setBackgroundColor(Color.BLACK);
+    addView(animatedThing, new FrameLayout.LayoutParams(100, 100, Gravity.CENTER));
+
+    // Start the animation immediately.
+    animateTheThing(ANIMATION_SLIDE_DISTANCE / 2);
+  }
+
+  @SuppressLint("NewApi")
+  private void animateTheThing(float destinationTranslationY) {
+    // Save the destination translation Y so that we can save our state, if needed.
+    this.destinationTranslationY = destinationTranslationY;
+
+    animator = animatedThing
+        .animate()
+        .translationY(destinationTranslationY)
+        .setDuration(Math.round(ANIMATION_TIME_IN_MILLIS * Math.abs((destinationTranslationY - animatedThing.getTranslationY()) / ANIMATION_SLIDE_DISTANCE)))
+        .setInterpolator(new AccelerateDecelerateInterpolator())
+        .setListener(animatorListener);
+    animator.start();
+  }
+
+  @SuppressLint("NewApi")
+  @Override
+  protected void onDetachedFromWindow() {
+    if (animator != null) {
+      // Cancel our animation to avoid leaks.
+      animator.cancel();
+    }
+    super.onDetachedFromWindow();
+  }
+
+  @Nullable
+  public Bundle saveSplashState() {
+    Log.d(TAG, "Saving splash state.");
+    Bundle state = new Bundle();
+    state.putFloat("currentTranslationY", animatedThing.getTranslationY());
+    state.putFloat("destinationTranslationY", destinationTranslationY);
+    return state;
+  }
+
+  public void restoreSplashState(@Nullable Bundle bundle) {
+    Log.d(TAG, "Restoring splash state: " + bundle);
+    if (bundle != null) {
+      this.destinationTranslationY = bundle.getFloat("destinationTranslationY");
+      this.animatedThing.setTranslationY(bundle.getFloat("currentTranslationY"));
+      animateTheThing(destinationTranslationY);
+    } else {
+      Log.d(TAG, "No state provided.");
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/SplashScreenThatNeverEnds.java b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/SplashScreenThatNeverEnds.java
new file mode 100644
index 0000000..35e34cc
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/java/io/flutter/splash_screen_load_rotate/SplashScreenThatNeverEnds.java
@@ -0,0 +1,55 @@
+package io.flutter.splash_screen_load_rotate;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import io.flutter.embedding.android.SplashScreen;
+
+public class SplashScreenThatNeverEnds implements SplashScreen {
+  private NeverEndingSplashView splashView;
+
+  @Nullable
+  public View createSplashView(@NonNull Context context, @Nullable Bundle bundle) {
+    if (splashView == null) {
+      splashView = new NeverEndingSplashView(context);
+      splashView.restoreSplashState(bundle);
+    }
+    return splashView;
+  }
+
+  public void transitionToFlutter(Runnable onTransitionComplete) {
+    // Do nothing. Never ends.
+  }
+
+  /**
+   * Informs Flutter that we are capable of restoring a transition that was previously
+   * in progress.
+   * <p>
+   * A splash transition can be interrupted by configuration changes or other OS operations.
+   * <p>
+   * If we were to return false here, then an orientation change would skip the rest of
+   * the transition and jump directly to the Flutter UI.
+   */
+  @Override
+  public boolean doesSplashViewRememberItsTransition() {
+    return true;
+  }
+
+  /**
+   * Saves the state of our {@code splashView} so that we can restore the animation
+   * state when we are recreated after a config change or other recreation event.
+   */
+  @Override
+  @Nullable
+  public Bundle saveSplashScreenState() {
+    if (splashView != null) {
+      return splashView.saveSplashState();
+    } else {
+      return null;
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/drawable/launch_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..af1c53e
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <shape android:shape="rectangle">
+            <solid android:color="#FFFF00" />
+        </shape>
+    </item>
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/ids.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/ids.xml
new file mode 100644
index 0000000..9cf305a
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item type="id" name="splash_screen" />
+</resources>
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/styles.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..00fa441
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             Flutter draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+</resources>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/profile/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..75b88d6
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_load_rotate">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/build.gradle
new file mode 100644
index 0000000..bb8a303
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/build.gradle
@@ -0,0 +1,29 @@
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.2.1'
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle.properties b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..2819f02
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/settings.gradle b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/settings.gradle
new file mode 100644
index 0000000..5a2f14f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/android/settings.gradle
@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
+}
+
+plugins.each { name, path ->
+    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+    include ":$name"
+    project(":$name").projectDir = pluginDirectory
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/lib/main.dart b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/lib/main.dart
new file mode 100644
index 0000000..7342a11
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/lib/main.dart
@@ -0,0 +1,111 @@
+import 'package:flutter/material.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+  // This widget is the root of your application.
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        // This is the theme of your application.
+        //
+        // Try running your application with "flutter run". You'll see the
+        // application has a blue toolbar. Then, without quitting the app, try
+        // changing the primarySwatch below to Colors.green and then invoke
+        // "hot reload" (press "r" in the console where you ran "flutter run",
+        // or simply save your changes to "hot reload" in a Flutter IDE).
+        // Notice that the counter didn't reset back to zero; the application
+        // is not restarted.
+        primarySwatch: Colors.blue,
+      ),
+      home: const MyHomePage(title: 'Flutter Demo Home Page'),
+    );
+  }
+}
+
+class MyHomePage extends StatefulWidget {
+  const MyHomePage({Key key, this.title}) : super(key: key);
+
+  // This widget is the home page of your application. It is stateful, meaning
+  // that it has a State object (defined below) that contains fields that affect
+  // how it looks.
+
+  // This class is the configuration for the state. It holds the values (in this
+  // case the title) provided by the parent (in this case the App widget) and
+  // used by the build method of the State. Fields in a Widget subclass are
+  // always marked "final".
+
+  final String title;
+
+  @override
+  _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  int _counter = 0;
+
+  void _incrementCounter() {
+    setState(() {
+      // This call to setState tells the Flutter framework that something has
+      // changed in this State, which causes it to rerun the build method below
+      // so that the display can reflect the updated values. If we changed
+      // _counter without calling setState(), then the build method would not be
+      // called again, and so nothing would appear to happen.
+      _counter++;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    // This method is rerun every time setState is called, for instance as done
+    // by the _incrementCounter method above.
+    //
+    // The Flutter framework has been optimized to make rerunning build methods
+    // fast, so that you can just rebuild anything that needs updating rather
+    // than having to individually change instances of widgets.
+    return Scaffold(
+      appBar: AppBar(
+        // Here we take the value from the MyHomePage object that was created by
+        // the App.build method, and use it to set our appbar title.
+        title: Text(widget.title),
+      ),
+      body: Center(
+        // Center is a layout widget. It takes a single child and positions it
+        // in the middle of the parent.
+        child: Column(
+          // Column is also layout widget. It takes a list of children and
+          // arranges them vertically. By default, it sizes itself to fit its
+          // children horizontally, and tries to be as tall as its parent.
+          //
+          // Invoke "debug painting" (press "p" in the console, choose the
+          // "Toggle Debug Paint" action from the Flutter Inspector in Android
+          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
+          // to see the wireframe for each widget.
+          //
+          // Column has various properties to control how it sizes itself and
+          // how it positions its children. Here we use mainAxisAlignment to
+          // center the children vertically; the main axis here is the vertical
+          // axis because Columns are vertical (the cross axis would be
+          // horizontal).
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            const Text(
+              'You have pushed the button this many times:',
+            ),
+            Text(
+              '$_counter',
+              style: Theme.of(context).textTheme.display1,
+            ),
+          ],
+        ),
+      ),
+      floatingActionButton: FloatingActionButton(
+        onPressed: _incrementCounter,
+        tooltip: 'Increment',
+        child: const Icon(Icons.add),
+      ), // This trailing comma makes auto-formatting nicer for build methods.
+    );
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/pubspec.yaml b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/pubspec.yaml
new file mode 100644
index 0000000..bb6cdce
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/pubspec.yaml
@@ -0,0 +1,93 @@
+name: splash_screen_load_rotate
+description: A new Flutter application.
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.1.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: 0.1.2
+
+  collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  typed_data: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  vector_math: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+
+  async: 2.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  boolean_selector: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stream_channel: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  test_api: 0.2.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #  - images/a_dot_burr.jpeg
+  #  - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware.
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
+
+# PUBSPEC CHECKSUM: e860
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/test/widget_test.dart b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/test/widget_test.dart
new file mode 100644
index 0000000..d0efff8
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:splash_screen_load_rotate/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore
new file mode 100644
index 0000000..ac4a906
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore
@@ -0,0 +1,72 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Android related
+**/android/**/gradle-wrapper.jar
+**/android/.gradle
+**/android/captures/
+**/android/gradlew
+**/android/gradlew.bat
+**/android/local.properties
+**/android/**/GeneratedPluginRegistrant.java
+
+# iOS/XCode related
+**/ios/**/*.mode1v3
+**/ios/**/*.mode2v3
+**/ios/**/*.moved-aside
+**/ios/**/*.pbxuser
+**/ios/**/*.perspectivev3
+**/ios/**/*sync/
+**/ios/**/.sconsign.dblite
+**/ios/**/.tags*
+**/ios/**/.vagrant/
+**/ios/**/DerivedData/
+**/ios/**/Icon?
+**/ios/**/Pods/
+**/ios/**/.symlinks/
+**/ios/**/profile
+**/ios/**/xcuserdata
+**/ios/.generated/
+**/ios/Flutter/App.framework
+**/ios/Flutter/Flutter.framework
+**/ios/Flutter/Generated.xcconfig
+**/ios/Flutter/app.flx
+**/ios/Flutter/app.zip
+**/ios/Flutter/flutter_assets/
+**/ios/ServiceDefinitions.json
+**/ios/Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!**/ios/**/default.mode1v3
+!**/ios/**/default.mode2v3
+!**/ios/**/default.pbxuser
+!**/ios/**/default.perspectivev3
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.metadata b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.metadata
new file mode 100644
index 0000000..693ab4f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 87a4fb567bcd3db87eb49f80d13e8ef95cfaa21e
+  channel: unknown
+
+project_type: app
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/README.md b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/README.md
new file mode 100644
index 0000000..def6d00
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/README.md
@@ -0,0 +1,7 @@
+# Splash Demo: Long transition animation
+
+This project is an example of a splash screen that fades very slowly to the Flutter UI.
+
+A slow transition is provided as a demo so that developers can manually verify that orientation 
+changes and other UI destruction processes do not cause issues with Flutter's splash system for
+Android. 
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/build.gradle
new file mode 100644
index 0000000..ea8e9ea
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/build.gradle
@@ -0,0 +1,65 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+    localPropertiesFile.withReader('UTF-8') { reader ->
+        localProperties.load(reader)
+    }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+    flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+    flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion 28
+
+    lintOptions {
+        disable 'InvalidPackage'
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "io.flutter.splash_screen_trans_rotate"
+        minSdkVersion 16
+        targetSdkVersion 28
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            // TODO: Add your own signing config for the release build.
+            // Signing with the debug keys for now, so `flutter run --release` works.
+            signingConfig signingConfigs.debug
+        }
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation 'androidx.fragment:fragment:1.1.0-beta01'
+    implementation 'androidx.lifecycle:lifecycle-runtime:2.2.0-alpha01'
+    implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0-alpha01'
+
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/debug/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..05a9cbd
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_trans_rotate">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9f1ba01
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_trans_rotate">
+
+    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
+         calls FlutterMain.startInitialization(this); in its onCreate method.
+         In most cases you can leave this as-is, but you if you want to provide
+         additional functionality it is fine to subclass or reimplement
+         FlutterApplication and put your custom class here. -->
+    <application
+        android:name="io.flutter.app.FlutterApplication"
+        android:label="splash_screen_trans_rotate"
+        android:icon="@mipmap/ic_launcher">
+        <activity
+            android:name=".MainActivity"
+            android:launchMode="singleTop"
+            android:theme="@style/LaunchTheme"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+            <meta-data
+                android:name="io.flutter.embedding.android.SplashScreenDrawable"
+                android:resource="@drawable/launch_background"
+                />
+            <meta-data
+                android:name="io.flutter.embedding.android.NormalTheme"
+                android:resource="@style/NormalTheme"
+                />
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/MainActivity.java b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/MainActivity.java
new file mode 100644
index 0000000..039ec62
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/MainActivity.java
@@ -0,0 +1,47 @@
+package io.flutter.splash_screen_trans_rotate;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.android.SplashScreen;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.embedding.engine.dart.DartExecutor;
+import io.flutter.view.FlutterMain;
+
+public class MainActivity extends FlutterActivity {
+  private static FlutterEngine flutterEngine;
+
+  static {
+    // Explicitly activates Debug logging for the Flutter Android embedding.
+    io.flutter.Log.setLogLevel(Log.DEBUG);
+  }
+
+  /**
+   * We explicitly provide a {@code FlutterEngine} so that every rotation does not create a
+   * new FlutterEngine. Creating a new FlutterEngine on every orientation would cause the
+   * splash experience to restart upon every orientation change, which is not what we're
+   * interested in verifying in this example app.
+   */
+  @Override
+  public FlutterEngine provideFlutterEngine(Context context) {
+    if (flutterEngine == null) {
+      flutterEngine = new FlutterEngine(context);
+
+      flutterEngine.getDartExecutor().executeDartEntrypoint(new DartExecutor.DartEntrypoint(
+          getAssets(),
+          FlutterMain.findAppBundlePath(context),
+          "main"
+      ));
+    }
+    return flutterEngine;
+  }
+
+  @Override
+  @Nullable
+  public SplashScreen provideSplashScreen() {
+    return new VeryLongTransitionSplashScreen();
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashScreen.java b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashScreen.java
new file mode 100644
index 0000000..e94a3f6
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashScreen.java
@@ -0,0 +1,64 @@
+package io.flutter.splash_screen_trans_rotate;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import io.flutter.embedding.android.SplashScreen;
+
+/**
+ * {@code SplashScreen} that displays a yellow splash screen {@code View}, which slowly fades
+ * out when Flutter is ready.
+ * <p>
+ * See {@link VeryLongTransitionSplashView} for visual details.
+ */
+public class VeryLongTransitionSplashScreen implements SplashScreen {
+  private VeryLongTransitionSplashView splashView;
+
+  @Override
+  public View createSplashView(@NonNull Context context, @Nullable Bundle savedInstanceState) {
+    splashView = new VeryLongTransitionSplashView(context);
+    splashView.restoreSplashState(savedInstanceState);
+    return splashView;
+  }
+
+  @Override
+  public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
+    if (splashView != null) {
+      splashView.transitionToFlutter(onTransitionComplete);
+    } else {
+      onTransitionComplete.run();
+    }
+  }
+
+  /**
+   * Informs Flutter that we are capable of restoring a transition that was previously
+   * in progress.
+   * <p>
+   * A splash transition can be interrupted by configuration changes or other OS operations.
+   * <p>
+   * If we were to return false here, then an orientation change would skip the rest of
+   * the transition and jump directly to the Flutter UI.
+   */
+  @Override
+  public boolean doesSplashViewRememberItsTransition() {
+    return true;
+  }
+
+  /**
+   * Saves the state of our {@code splashView} so that we can restore the long fade transition
+   * when we are recreated after a config change or other recreation event.
+   */
+  @Override
+  @Nullable
+  public Bundle saveSplashScreenState() {
+    if (splashView != null) {
+      return splashView.saveSplashState();
+    } else {
+      return null;
+    }
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashView.java b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashView.java
new file mode 100644
index 0000000..b0dd824
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/java/io/flutter/splash_screen_trans_rotate/VeryLongTransitionSplashView.java
@@ -0,0 +1,125 @@
+package io.flutter.splash_screen_trans_rotate;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ViewPropertyAnimator;
+import android.widget.FrameLayout;
+import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
+
+/**
+ * {@code View} that appears entirely yellow and slowly fades away, upon request.
+ * <p>
+ * Call {@link #transitionToFlutter(Runnable)} to begin fading away.
+ * <p>
+ * Call {@link #saveSplashState()} to save the current state of this splash {@code View},
+ * e.g., the current state of the fade transition.
+ * <p>
+ * Call {@link #restoreSplashState(Bundle)} to restore a previous state of this splash
+ * {@code View}, e.g., the previous state of an interrupted fade transition.
+ */
+public class VeryLongTransitionSplashView extends FrameLayout {
+  private static final String TAG = "VeryLongTransitionSplashView";
+
+  private static final int ANIMATION_TIME_IN_MILLIS = 10000;
+
+  private float transitionPercentWhenAnimationStarted = 0.0f;
+  private float totalTransitionPercent = 0.0f;
+  private Runnable onTransitionComplete;
+  private ViewPropertyAnimator fadeAnimator;
+
+  private final ValueAnimator.AnimatorUpdateListener animatorUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
+    @Override
+    public void onAnimationUpdate(ValueAnimator animation) {
+      // We have to represent transition percent as a starting value + the fraction of the
+      // running animation. This is because there is no way to start an Animator and inform
+      // it that it should already be X percent complete.
+      totalTransitionPercent = transitionPercentWhenAnimationStarted
+          + (animation.getAnimatedFraction() * (1.0f - transitionPercentWhenAnimationStarted));
+    }
+  };
+
+  private final Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
+    @Override
+    public void onAnimationEnd(Animator animation) {
+      // Remove all animation listeners to avoid memory leaks.
+      animation.removeAllListeners();
+
+      // Notify listener that we're done transitioning.
+      if (onTransitionComplete != null) {
+        onTransitionComplete.run();
+      }
+    }
+
+    @Override
+    public void onAnimationCancel(Animator animation) {
+      // Remove all animation listeners to avoid memory leaks.
+      animation.removeAllListeners();
+    }
+  };
+
+  public VeryLongTransitionSplashView(Context context) {
+    super(context);
+
+    // Give the UI a yellow background to prove that this splash screen view takes up
+    // all available space.
+    setBackgroundColor(Color.YELLOW);
+  }
+
+  /**
+   * Begins fading out.
+   * <p>
+   * If a previous transition state was restored, this method will begin fading out from the
+   * previously restored transition percent. See {@link #restoreSplashState(Bundle)}.
+   */
+  public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
+    Log.d(TAG, "Transitioning to flutter.");
+    this.onTransitionComplete = onTransitionComplete;
+
+    fadeAnimator = animate()
+        .alpha(0.0f)
+        .setDuration(Math.round(ANIMATION_TIME_IN_MILLIS * (1.0 - totalTransitionPercent)))
+        .setUpdateListener(animatorUpdateListener)
+        .setListener(animatorListener);
+    fadeAnimator.start();
+  }
+
+  @Override
+  protected void onDetachedFromWindow() {
+    if (fadeAnimator != null) {
+      // Cancel our animator to avoid leaks.
+      fadeAnimator.cancel();
+    }
+    super.onDetachedFromWindow();
+  }
+
+  @Nullable
+  public Bundle saveSplashState() {
+    Log.d(TAG, "Saving splash state.");
+    if (totalTransitionPercent > 0.0f && totalTransitionPercent < 1.0f) {
+      Bundle state = new Bundle();
+      state.putFloat("totalTransitionPercent", totalTransitionPercent);
+      Log.d(TAG, String.format("Transition percent: %.2f", totalTransitionPercent));
+      return state;
+    } else {
+      Log.d(TAG, "No transition to save.");
+      return null;
+    }
+  }
+
+  public void restoreSplashState(@Nullable Bundle bundle) {
+    Log.d(TAG, "Restoring splash state: " + bundle);
+    if (bundle != null) {
+      transitionPercentWhenAnimationStarted = bundle.getFloat("totalTransitionPercent");
+      setAlpha(1.0f - transitionPercentWhenAnimationStarted);
+      Log.d(TAG, String.format("State restored with transition percent: %.2f", transitionPercentWhenAnimationStarted));
+    } else {
+      Log.d(TAG, "No state provided.");
+    }
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/launch_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..dd65c19
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/yellow" />
+
+    <!-- You can insert your own image assets here -->
+    <!-- <item>
+        <bitmap
+            android:gravity="center"
+            android:src="@mipmap/launch_image" />
+    </item> -->
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/normal_background.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/normal_background.xml
new file mode 100644
index 0000000..5782842
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/drawable/normal_background.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/white" />
+</layer-list>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/colors.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..c7e52a1
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item type="color" name="yellow">#FFFFFF00</item>
+</resources>
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/ids.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/ids.xml
new file mode 100644
index 0000000..9cf305a
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <item type="id" name="splash_screen" />
+</resources>
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/styles.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..2032af9
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <!-- Show a splash screen on the activity. Automatically removed when
+             Flutter draws its first frame -->
+        <item name="android:windowBackground">@drawable/launch_background</item>
+    </style>
+
+    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+        <item name="android:windowBackground">@drawable/normal_background</item>
+    </style>
+</resources>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/profile/AndroidManifest.xml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..05a9cbd
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.splash_screen_trans_rotate">
+    <!-- Flutter needs it to communicate with the running application
+         to allow setting breakpoints, to provide hot reload, etc.
+    -->
+    <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/build.gradle b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/build.gradle
new file mode 100644
index 0000000..bb8a303
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/build.gradle
@@ -0,0 +1,29 @@
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.2.1'
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+    project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+    project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle.properties b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..2819f02
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/settings.gradle b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/settings.gradle
new file mode 100644
index 0000000..5a2f14f
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/android/settings.gradle
@@ -0,0 +1,15 @@
+include ':app'
+
+def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
+
+def plugins = new Properties()
+def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
+if (pluginsFile.exists()) {
+    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
+}
+
+plugins.each { name, path ->
+    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
+    include ":$name"
+    project(":$name").projectDir = pluginDirectory
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/lib/main.dart b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/lib/main.dart
new file mode 100644
index 0000000..7342a11
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/lib/main.dart
@@ -0,0 +1,111 @@
+import 'package:flutter/material.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+  // This widget is the root of your application.
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        // This is the theme of your application.
+        //
+        // Try running your application with "flutter run". You'll see the
+        // application has a blue toolbar. Then, without quitting the app, try
+        // changing the primarySwatch below to Colors.green and then invoke
+        // "hot reload" (press "r" in the console where you ran "flutter run",
+        // or simply save your changes to "hot reload" in a Flutter IDE).
+        // Notice that the counter didn't reset back to zero; the application
+        // is not restarted.
+        primarySwatch: Colors.blue,
+      ),
+      home: const MyHomePage(title: 'Flutter Demo Home Page'),
+    );
+  }
+}
+
+class MyHomePage extends StatefulWidget {
+  const MyHomePage({Key key, this.title}) : super(key: key);
+
+  // This widget is the home page of your application. It is stateful, meaning
+  // that it has a State object (defined below) that contains fields that affect
+  // how it looks.
+
+  // This class is the configuration for the state. It holds the values (in this
+  // case the title) provided by the parent (in this case the App widget) and
+  // used by the build method of the State. Fields in a Widget subclass are
+  // always marked "final".
+
+  final String title;
+
+  @override
+  _MyHomePageState createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  int _counter = 0;
+
+  void _incrementCounter() {
+    setState(() {
+      // This call to setState tells the Flutter framework that something has
+      // changed in this State, which causes it to rerun the build method below
+      // so that the display can reflect the updated values. If we changed
+      // _counter without calling setState(), then the build method would not be
+      // called again, and so nothing would appear to happen.
+      _counter++;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    // This method is rerun every time setState is called, for instance as done
+    // by the _incrementCounter method above.
+    //
+    // The Flutter framework has been optimized to make rerunning build methods
+    // fast, so that you can just rebuild anything that needs updating rather
+    // than having to individually change instances of widgets.
+    return Scaffold(
+      appBar: AppBar(
+        // Here we take the value from the MyHomePage object that was created by
+        // the App.build method, and use it to set our appbar title.
+        title: Text(widget.title),
+      ),
+      body: Center(
+        // Center is a layout widget. It takes a single child and positions it
+        // in the middle of the parent.
+        child: Column(
+          // Column is also layout widget. It takes a list of children and
+          // arranges them vertically. By default, it sizes itself to fit its
+          // children horizontally, and tries to be as tall as its parent.
+          //
+          // Invoke "debug painting" (press "p" in the console, choose the
+          // "Toggle Debug Paint" action from the Flutter Inspector in Android
+          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
+          // to see the wireframe for each widget.
+          //
+          // Column has various properties to control how it sizes itself and
+          // how it positions its children. Here we use mainAxisAlignment to
+          // center the children vertically; the main axis here is the vertical
+          // axis because Columns are vertical (the cross axis would be
+          // horizontal).
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            const Text(
+              'You have pushed the button this many times:',
+            ),
+            Text(
+              '$_counter',
+              style: Theme.of(context).textTheme.display1,
+            ),
+          ],
+        ),
+      ),
+      floatingActionButton: FloatingActionButton(
+        onPressed: _incrementCounter,
+        tooltip: 'Increment',
+        child: const Icon(Icons.add),
+      ), // This trailing comma makes auto-formatting nicer for build methods.
+    );
+  }
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml
new file mode 100644
index 0000000..ddedfef
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/pubspec.yaml
@@ -0,0 +1,132 @@
+name: splash_screen_trans_rotate
+description: A new Flutter application.
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.1.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: 0.1.2
+
+  collection: 1.14.11 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  typed_data: 1.1.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  vector_math: 2.0.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+  flutter_driver:
+    sdk: flutter
+  test: 1.6.3
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+
+  analyzer: 0.36.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  args: 1.5.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  async: 2.3.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  boolean_selector: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  charcode: 1.1.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  convert: 2.1.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  crypto: 2.0.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  csslib: 0.16.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  file: 5.0.8+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  front_end: 0.1.19 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  glob: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  html: 0.14.0+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http: 0.12.0+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http_multi_server: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  http_parser: 3.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  intl: 0.15.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  io: 0.3.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  js: 0.6.1+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  json_rpc_2: 2.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  kernel: 0.3.19 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  pub_semver: 1.4.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf: 0.7.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  shelf_web_socket: 0.2.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_map_stack_trace: 1.1.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_maps: 0.10.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  source_span: 1.5.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stack_trace: 1.9.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  stream_channel: 2.0.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  string_scanner: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  term_glyph: 1.1.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  test_api: 0.2.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  test_core: 0.2.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  vm_service_client: 0.2.6+2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  watcher: 0.9.7+12 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  web_socket_channel: 1.0.14 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  yaml: 2.1.16 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #  - images/a_dot_burr.jpeg
+  #  - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware.
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
+
+# PUBSPEC CHECKSUM: e85f
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test/widget_test.dart b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test/widget_test.dart
new file mode 100644
index 0000000..79b3ab3
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:splash_screen_trans_rotate/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main.dart b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main.dart
new file mode 100644
index 0000000..cc92f2b
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main.dart
@@ -0,0 +1,7 @@
+import 'package:flutter_driver/driver_extension.dart';
+import 'package:splash_screen_trans_rotate/main.dart' as app;
+
+void main() {
+  enableFlutterDriverExtension();
+  app.main();
+}
\ No newline at end of file
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main_test.dart b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main_test.dart
new file mode 100644
index 0000000..c124a42
--- /dev/null
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/test_driver/main_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_driver/flutter_driver.dart';
+
+import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
+
+void main() {
+  group('end-to-end test', () {
+    FlutterDriver driver;
+
+    setUpAll(() async {
+      driver = await FlutterDriver.connect();
+    });
+
+    tearDownAll(() async {
+      await driver?.close();
+    });
+
+    test('Flutter experience eventually appears', () async {
+      final SerializableFinder fabFinder = find.byTooltip('Increment');
+
+      // Ensure that the Flutter experience eventually becomes visible.
+      await driver.waitFor(fabFinder);
+    });
+  });
+}
diff --git a/dev/integration_tests/android_views/pubspec.yaml b/dev/integration_tests/android_views/pubspec.yaml
index 03add69..2a75d9a 100644
--- a/dev/integration_tests/android_views/pubspec.yaml
+++ b/dev/integration_tests/android_views/pubspec.yaml
@@ -55,7 +55,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -76,4 +76,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 0581
+# PUBSPEC CHECKSUM: 1682
diff --git a/dev/integration_tests/channels/pubspec.yaml b/dev/integration_tests/channels/pubspec.yaml
index 7dd3195..d3923d5 100644
--- a/dev/integration_tests/channels/pubspec.yaml
+++ b/dev/integration_tests/channels/pubspec.yaml
@@ -37,7 +37,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/codegen/pubspec.yaml b/dev/integration_tests/codegen/pubspec.yaml
index 343472c..92c457d 100644
--- a/dev/integration_tests/codegen/pubspec.yaml
+++ b/dev/integration_tests/codegen/pubspec.yaml
@@ -50,7 +50,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -74,4 +74,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/external_ui/pubspec.yaml b/dev/integration_tests/external_ui/pubspec.yaml
index db2570b..3d834d1 100644
--- a/dev/integration_tests/external_ui/pubspec.yaml
+++ b/dev/integration_tests/external_ui/pubspec.yaml
@@ -37,7 +37,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/flavors/pubspec.yaml b/dev/integration_tests/flavors/pubspec.yaml
index e0f874b..5483223 100644
--- a/dev/integration_tests/flavors/pubspec.yaml
+++ b/dev/integration_tests/flavors/pubspec.yaml
@@ -37,7 +37,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/image_loading/pubspec.yaml b/dev/integration_tests/image_loading/pubspec.yaml
index accfdbf..8f0fd3c 100644
--- a/dev/integration_tests/image_loading/pubspec.yaml
+++ b/dev/integration_tests/image_loading/pubspec.yaml
@@ -30,7 +30,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -60,4 +60,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: f583
+# PUBSPEC CHECKSUM: c484
diff --git a/dev/integration_tests/platform_interaction/pubspec.yaml b/dev/integration_tests/platform_interaction/pubspec.yaml
index c49e474..6af7eb7 100644
--- a/dev/integration_tests/platform_interaction/pubspec.yaml
+++ b/dev/integration_tests/platform_interaction/pubspec.yaml
@@ -37,7 +37,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -67,4 +67,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: b1ce
+# PUBSPEC CHECKSUM: 80cf
diff --git a/dev/integration_tests/ui/pubspec.yaml b/dev/integration_tests/ui/pubspec.yaml
index d792a83..80f9046 100644
--- a/dev/integration_tests/ui/pubspec.yaml
+++ b/dev/integration_tests/ui/pubspec.yaml
@@ -39,7 +39,7 @@
   meta: 1.1.7 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -77,4 +77,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: a113
+# PUBSPEC CHECKSUM: c214
diff --git a/dev/snippets/pubspec.yaml b/dev/snippets/pubspec.yaml
index 41015fe..081dd40 100644
--- a/dev/snippets/pubspec.yaml
+++ b/dev/snippets/pubspec.yaml
@@ -53,7 +53,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pool: 1.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf: 0.7.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -98,4 +98,4 @@
   vm_service_client: 0.2.6 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   web_socket_channel: 1.0.9 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
-# PUBSPEC CHECKSUM: f492
+# PUBSPEC CHECKSUM: bd93
diff --git a/examples/catalog/pubspec.yaml b/examples/catalog/pubspec.yaml
index c6a3036..190acf4 100644
--- a/examples/catalog/pubspec.yaml
+++ b/examples/catalog/pubspec.yaml
@@ -45,7 +45,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -73,4 +73,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 65b9
+# PUBSPEC CHECKSUM: 4eba
diff --git a/examples/flutter_gallery/pubspec.yaml b/examples/flutter_gallery/pubspec.yaml
index 64045bed..58fcd94 100644
--- a/examples/flutter_gallery/pubspec.yaml
+++ b/examples/flutter_gallery/pubspec.yaml
@@ -59,7 +59,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   pedantic: 1.8.0+1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -254,4 +254,4 @@
       - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Regular.ttf
       - asset: packages/flutter_gallery_assets/fonts/merriweather/Merriweather-Light.ttf
 
-# PUBSPEC CHECKSUM: 8185
+# PUBSPEC CHECKSUM: 4586
diff --git a/examples/platform_channel/pubspec.yaml b/examples/platform_channel/pubspec.yaml
index 41f0a96..d1a2333 100644
--- a/examples/platform_channel/pubspec.yaml
+++ b/examples/platform_channel/pubspec.yaml
@@ -43,7 +43,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,4 +72,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 65b9
+# PUBSPEC CHECKSUM: 4eba
diff --git a/examples/platform_channel_swift/pubspec.yaml b/examples/platform_channel_swift/pubspec.yaml
index 53c33cd..b3764e1 100644
--- a/examples/platform_channel_swift/pubspec.yaml
+++ b/examples/platform_channel_swift/pubspec.yaml
@@ -43,7 +43,7 @@
   matcher: 0.12.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_config: 1.0.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   package_resolver: 1.0.10 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   path: 1.6.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
@@ -72,4 +72,4 @@
 flutter:
   uses-material-design: true
 
-# PUBSPEC CHECKSUM: 65b9
+# PUBSPEC CHECKSUM: 4eba
diff --git a/packages/flutter_tools/lib/src/commands/update_packages.dart b/packages/flutter_tools/lib/src/commands/update_packages.dart
index 1ab8257..893cd96 100644
--- a/packages/flutter_tools/lib/src/commands/update_packages.dart
+++ b/packages/flutter_tools/lib/src/commands/update_packages.dart
@@ -24,7 +24,8 @@
   'flutter_gallery_assets': '0.1.9+2', // See //examples/flutter_gallery/pubspec.yaml
   'test': '1.6.3',     //  | Tests are timing out at 1.6.4 https://github.com/flutter/flutter/issues/33823
   'test_api': '0.2.5', //  |
-  'test_core': '0.2.5' //  |
+  'test_core': '0.2.5', //  |
+  'build_runner': '1.6.1' // TODO(jonahwilliams): allow newer versions
 };
 
 class UpdatePackagesCommand extends FlutterCommand {
diff --git a/packages/flutter_tools/pubspec.yaml b/packages/flutter_tools/pubspec.yaml
index 0c58efa..de771fa 100644
--- a/packages/flutter_tools/pubspec.yaml
+++ b/packages/flutter_tools/pubspec.yaml
@@ -13,7 +13,7 @@
   args: 1.5.2
   bsdiff: 0.1.0
   completion: 0.2.1+1
-  coverage: 0.13.1
+  coverage: 0.13.2
   crypto: 2.0.6
   file: 5.0.8+1
   http: 0.12.0+2
@@ -33,7 +33,7 @@
   usage: 3.4.1
   vm_service_client: 0.2.6+2
   web_socket_channel: 1.0.14
-  webkit_inspection_protocol: 0.4.2
+  webkit_inspection_protocol: 0.5.0
   xml: 3.5.0
   yaml: 2.1.16
   flutter_goldens_client:
@@ -51,7 +51,7 @@
   dart_style: 1.2.9
   code_builder: 3.2.0
   build: 1.1.5
-  build_modules: 2.3.0
+  build_modules: 2.3.1
   build_daemon: 1.1.0
   build_web_compilers: 2.1.4
 
@@ -111,7 +111,7 @@
 
   mime: 0.9.6+3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   multi_server_socket: 1.0.2 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
-  node_preamble: 1.4.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  node_preamble: 1.4.5 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_packages_handler: 1.0.4 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
   shelf_static: 0.2.8 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
 
@@ -119,4 +119,4 @@
   # Exclude this package from the hosted API docs.
   nodoc: true
 
-# PUBSPEC CHECKSUM: 5030
+# PUBSPEC CHECKSUM: 4832