Add embedding as API dependency instead of compile only dependency (#41142)

diff --git a/dev/bots/firebase_testlab.sh b/dev/bots/firebase_testlab.sh
index 14be500..41e29f0 100755
--- a/dev/bots/firebase_testlab.sh
+++ b/dev/bots/firebase_testlab.sh
@@ -1,13 +1,17 @@
 #!/bin/bash
 
+# The tests to run on Firebase Test Lab.
+# Currently, the test consists on building an Android App Bundle and ensuring
+# that the app doesn't crash upon startup.
+tests=(
+  "dev/integration_tests/release_smoke_test"
+  "dev/integration_tests/abstract_method_smoke_test"
+)
+
 set -e
 
 GIT_REVISION=$(git rev-parse HEAD)
 
-pushd dev/integration_tests/release_smoke_test
-
-../../../bin/flutter build appbundle --target-platform android-arm,android-arm64
-
 # New contributors will not have permissions to run this test - they won't be
 # able to access the service account information. We should just mark the test
 # as passed - it will run fine on post submit, where it will still catch
@@ -22,21 +26,29 @@
 gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json
 gcloud --quiet config set project flutter-infra
 
-# Firebase Test Lab tests are currently known to be failing with
-# "Firebase Test Lab infrastructure failure: Error during preprocessing"
-# Remove "|| exit 0" once the failures are resolved
-# https://github.com/flutter/flutter/issues/36501
+function test_app_bundle() {
+  pushd "$@"
+  ../../../bin/flutter build appbundle --target-platform android-arm,android-arm64
 
-# Run the test.
-gcloud firebase test android run --type robo \
-  --app build/app/outputs/bundle/release/app.aab \
-  --timeout 2m \
-  --results-bucket=gs://flutter_firebase_testlab \
-  --results-dir=release_smoke_test/$GIT_REVISION/$CIRRUS_BUILD_ID || exit 0
+  # Firebase Test Lab tests are currently known to be failing with
+  # "Firebase Test Lab infrastructure failure: Error during preprocessing"
+  # Remove "|| exit 0" once the failures are resolved
+  # https://github.com/flutter/flutter/issues/36501
 
-# Check logcat for "E/flutter" - if it's there, something's wrong.
-gsutil cp gs://flutter_firebase_testlab/release_smoke_test/$GIT_REVISION/$CIRRUS_BUILD_ID/walleye-26-en-portrait/logcat /tmp/logcat
-! grep "E/flutter" /tmp/logcat || false
-grep "I/flutter" /tmp/logcat
+  # Run the test.
+  gcloud firebase test android run --type robo \
+    --app build/app/outputs/bundle/release/app.aab \
+    --timeout 2m \
+    --results-bucket=gs://flutter_firebase_testlab \
+    --results-dir="$@"/"$GIT_REVISION"/"$CIRRUS_BUILD_ID" || exit 0
 
-popd
+    # Check logcat for "E/flutter" - if it's there, something's wrong.
+    gsutil cp gs://flutter_firebase_testlab/"$@"/"$GIT_REVISION"/"$CIRRUS_BUILD_ID"/walleye-26-en-portrait/logcat /tmp/logcat
+    ! grep "E/flutter" /tmp/logcat || false
+    grep "I/flutter" /tmp/logcat
+    popd
+}
+
+for test in ${tests[*]}; do
+  test_app_bundle $test
+done
diff --git a/dev/integration_tests/abstract_method_smoke_test/android/app/build.gradle b/dev/integration_tests/abstract_method_smoke_test/android/app/build.gradle
new file mode 100644
index 0000000..ed57ad7
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/app/build.gradle
@@ -0,0 +1,71 @@
+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 plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+    compileSdkVersion 29
+
+    sourceSets {
+        main.java.srcDirs += 'src/main/kotlin'
+    }
+
+    lintOptions {
+        disable 'InvalidPackage'
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+
+    defaultConfig {
+        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+        applicationId "com.example.abstract_method_smoke_test"
+        minSdkVersion 21
+        targetSdkVersion 29
+        versionCode flutterVersionCode.toInteger()
+        versionName flutterVersionName
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            signingConfig signingConfigs.debug
+        }
+    }
+
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+}
+
+flutter {
+    source '../..'
+}
+
+dependencies {
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/dev/integration_tests/abstract_method_smoke_test/android/app/src/debug/AndroidManifest.xml b/dev/integration_tests/abstract_method_smoke_test/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..122c170
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.abstract_method_smoke_test">
+    <!-- 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/abstract_method_smoke_test/android/app/src/main/AndroidManifest.xml b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..87652c5
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.abstract_method_smoke_test">
+
+    <!-- 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="abstract_method_smoke_test">
+        <meta-data
+            android:name="com.google.android.geo.API_KEY"
+            android:value="YOUR KEY HERE"/>
+        <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="stateVisible|adjustResize">
+            <!-- This keeps the window background of the activity showing
+                 until Flutter renders its first frame. It can be removed if
+                 there is no splash screen (such as the default splash screen
+                 defined in @style/LaunchTheme). -->
+            <meta-data
+                android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
+                android:value="true" />
+            <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/abstract_method_smoke_test/android/app/src/main/kotlin/com/example/abstract_method_smoke_test/MainActivity.kt b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/kotlin/com/example/abstract_method_smoke_test/MainActivity.kt
new file mode 100644
index 0000000..4b7eeb7
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/kotlin/com/example/abstract_method_smoke_test/MainActivity.kt
@@ -0,0 +1,19 @@
+package com.example.abstract_method_smoke_test
+
+import android.content.Context
+import android.os.Bundle
+import android.view.inputmethod.InputMethodManager
+import io.flutter.app.FlutterActivity
+import io.flutter.plugins.GeneratedPluginRegistrant
+
+class MainActivity: FlutterActivity() {
+  override fun onCreate(savedInstanceState: Bundle?) {
+    super.onCreate(savedInstanceState)
+    GeneratedPluginRegistrant.registerWith(this)
+
+    // Triggers the Android keyboard, which causes the resize of the Flutter view.
+    // https://github.com/flutter/flutter/issues/40126
+    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
+  }
+}
diff --git a/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/res/drawable/launch_background.xml b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/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="@android:color/white" />
+
+    <!-- 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/abstract_method_smoke_test/android/app/src/main/res/values/styles.xml b/dev/integration_tests/abstract_method_smoke_test/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..00fa441
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/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/abstract_method_smoke_test/android/app/src/profile/AndroidManifest.xml b/dev/integration_tests/abstract_method_smoke_test/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..122c170
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.abstract_method_smoke_test">
+    <!-- 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/abstract_method_smoke_test/android/build.gradle b/dev/integration_tests/abstract_method_smoke_test/android/build.gradle
new file mode 100644
index 0000000..3100ad2
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+    ext.kotlin_version = '1.3.50'
+    repositories {
+        google()
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.5.0'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+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/abstract_method_smoke_test/android/gradle.properties b/dev/integration_tests/abstract_method_smoke_test/android/gradle.properties
new file mode 100644
index 0000000..d2032bc
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/android/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.jvmargs=-Xmx1536M
+android.enableJetifier=true
+android.useAndroidX=true
+android.enableR8=true
diff --git a/dev/integration_tests/abstract_method_smoke_test/android/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/abstract_method_smoke_test/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9ec7236
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/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-5.6.1-all.zip
diff --git a/dev/integration_tests/abstract_method_smoke_test/android/settings.gradle b/dev/integration_tests/abstract_method_smoke_test/android/settings.gradle
new file mode 100644
index 0000000..5a2f14f
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/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/abstract_method_smoke_test/lib/main.dart b/dev/integration_tests/abstract_method_smoke_test/lib/main.dart
new file mode 100644
index 0000000..9720d8f
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/lib/main.dart
@@ -0,0 +1,61 @@
+import 'package:flutter/material.dart';
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        primarySwatch: Colors.blue,
+      ),
+      home: HomePage(),
+    );
+  }
+}
+
+class HomePage extends StatefulWidget {
+  @override
+  _HomePage createState() => _HomePage();
+}
+
+class _HomePage extends State<HomePage> {
+  @override
+  void initState() {
+    super.initState();
+
+    // Trigger the second route.
+    // https://github.com/flutter/flutter/issues/40126
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
+      Navigator.of(context).push(
+          MaterialPageRoute<void>(builder: (_) => SecondPage()));
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return const Scaffold();
+  }
+}
+
+class SecondPage extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+      body: Column(
+        children: <Widget>[
+          TextFormField(),
+          const Expanded(
+            child: GoogleMap(
+              initialCameraPosition: CameraPosition(
+                target: LatLng(0, 0)
+              ),
+            ),
+          ),
+        ],
+      ),
+    );
+  }
+}
\ No newline at end of file
diff --git a/dev/integration_tests/abstract_method_smoke_test/pubspec.yaml b/dev/integration_tests/abstract_method_smoke_test/pubspec.yaml
new file mode 100644
index 0000000..cc95e73
--- /dev/null
+++ b/dev/integration_tests/abstract_method_smoke_test/pubspec.yaml
@@ -0,0 +1,47 @@
+name: abstract_method_smoke_test
+description: A new Flutter project.
+
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.1.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  google_maps_flutter: 0.5.21+4
+
+  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
+
+  archive: 2.0.10 # 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.1.3 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  image: 2.1.4 # 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.4 # 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"
+  petitparser: 2.4.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+  quiver: 2.0.5 # 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.5 # 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"
+  xml: 3.5.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
+
+flutter:
+  uses-material-design: true
+
+# PUBSPEC CHECKSUM: 3231
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle
index 606d3a3..bbc1c8e 100644
--- a/packages/flutter_tools/gradle/flutter.gradle
+++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -332,9 +332,11 @@
         }
         Closure addEmbeddingCompileOnlyDependency = { buildType ->
             String flutterBuildMode = buildModeFor(buildType)
-            // Add the embedding as a compile only dependency to the plugin.
+            // In AGP 3.5, the embedding must be added as an API implementation,
+            // so java8 features are desugared against the runtime classpath.
+            // For more, see https://github.com/flutter/flutter/issues/40126
             if (flutterJar) {
-                addCompileOnlyDependency(
+                addApiDependencies(
                     pluginProject,
                     buildType.name,
                     project.files {
@@ -343,7 +345,7 @@
                 )
                 return
             }
-            addCompileOnlyDependency(
+            addApiDependencies(
                 pluginProject,
                 buildType.name,
                 "io.flutter:flutter_embedding_$flutterBuildMode:1.0.0-$engineVersion",