[ci] Enable Android emulator-based tests (#4494)

Adds emulators to the Android platform test tasks, and enable both native integration tests and `flutter test` Dart integration tests. This finally gives us presubmit coverage of Android integration tests for non-team-member PRs, as well as giving us a path to reducing the dependency on FTL for all of our Android testing.

Currently this uses Android 13 emulators; we could expand this to a set of legacy version emulator tests in the future once this is in place.

Some specific notes:
- Camera and Google Maps tests are currently excluded, so that we can enable everything else while we work on the blockers for those.
- `shared_preferences` was missing its debug entitlement, which prevented the debug service from running, and thus broke `flutter test`; we'd just never noticed because FTL tests don't need that mechanism to work.
- IAP was using `test` instead of `testWidget`, which we only check for in `drive-examples`, so hadn't noticed.

Fixes https://github.com/flutter/flutter/issues/93810
diff --git a/.ci.yaml b/.ci.yaml
index 7b4b7a0..10500e8 100644
--- a/.ci.yaml
+++ b/.ci.yaml
@@ -310,6 +310,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 0 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_2 master
     recipe: packages/packages
@@ -319,6 +323,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 1 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_3 master
     recipe: packages/packages
@@ -328,6 +336,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 2 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_4 master
     recipe: packages/packages
@@ -337,6 +349,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 3 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_5 master
     recipe: packages/packages
@@ -346,6 +362,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 4 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_6 master
     recipe: packages/packages
@@ -355,6 +375,10 @@
       channel: master
       version_file: flutter_master.version
       package_sharding: "--shardIndex 5 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_1 stable
     recipe: packages/packages
@@ -365,6 +389,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 0 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_2 stable
     recipe: packages/packages
@@ -375,6 +403,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 1 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_3 stable
     recipe: packages/packages
@@ -385,6 +417,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 2 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_4 stable
     recipe: packages/packages
@@ -395,6 +431,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 3 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_5 stable
     recipe: packages/packages
@@ -405,6 +445,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 4 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   - name: Linux_android android_platform_tests_shard_6 stable
     recipe: packages/packages
@@ -415,6 +459,10 @@
       channel: stable
       version_file: flutter_stable.version
       package_sharding: "--shardIndex 5 --shardCount 6"
+      dependencies: >-
+        [
+          {"dependency": "android_virtual_device", "version": "33"}
+        ]
 
   ### Web tasks ###
   - name: Linux_web web_build_all_packages master
diff --git a/.ci/targets/android_platform_tests.yaml b/.ci/targets/android_platform_tests.yaml
index 70ca7b1..7ee1767 100644
--- a/.ci/targets/android_platform_tests.yaml
+++ b/.ci/targets/android_platform_tests.yaml
@@ -19,12 +19,9 @@
   - name: native unit tests
     script: script/tool_runner.sh
     args: ["native-test", "--android", "--no-integration", "--exclude=script/configs/exclude_native_unit_android.yaml"]
-  # TODO(stuartmorgan): Enable these once
-  # https://github.com/flutter/flutter/issues/120736 is implemented.
-  # See also https://github.com/flutter/flutter/issues/114373
-  #- name: native integration tests
-  #  script: script/tool_runner.sh
-  #  args: ["native-test", "--android", "--no-unit"]
-  #- name: drive examples
-  #  script: script/tool_runner.sh
-  #  args: ["drive-examples", "--android", "--exclude=script/configs/exclude_integration_android.yaml"]
+  - name: native integration tests
+    script: script/tool_runner.sh
+    args: ["native-test", "--android", "--no-unit"]
+  - name: drive examples
+    script: script/tool_runner.sh
+    args: ["drive-examples", "--android", "--exclude=script/configs/exclude_integration_android.yaml,script/configs/exclude_integration_android_emulator.yaml"]
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart
index ecf43d2..568becd 100644
--- a/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart
+++ b/packages/in_app_purchase/in_app_purchase_android/example/integration_test/in_app_purchase_test.dart
@@ -30,7 +30,8 @@
       billingClient = BillingClient((PurchasesResultWrapper _) {});
     });
 
-    test('BillingClient.acknowledgePurchase', () async {
+    testWidgets('BillingClient.acknowledgePurchase',
+        (WidgetTester tester) async {
       try {
         await billingClient.acknowledgePurchase('purchaseToken');
       } on MissingPluginException {
@@ -38,7 +39,7 @@
       }
     });
 
-    test('BillingClient.consumeAsync', () async {
+    testWidgets('BillingClient.consumeAsync', (WidgetTester tester) async {
       try {
         await billingClient.consumeAsync('purchaseToken');
       } on MissingPluginException {
@@ -46,7 +47,7 @@
       }
     });
 
-    test('BillingClient.endConnection', () async {
+    testWidgets('BillingClient.endConnection', (WidgetTester tester) async {
       try {
         await billingClient.endConnection();
       } on MissingPluginException {
@@ -54,7 +55,8 @@
       }
     });
 
-    test('BillingClient.isFeatureSupported', () async {
+    testWidgets('BillingClient.isFeatureSupported',
+        (WidgetTester tester) async {
       try {
         await billingClient
             .isFeatureSupported(BillingClientFeature.productDetails);
@@ -63,7 +65,7 @@
       }
     });
 
-    test('BillingClient.isReady', () async {
+    testWidgets('BillingClient.isReady', (WidgetTester tester) async {
       try {
         await billingClient.isReady();
       } on MissingPluginException {
@@ -71,7 +73,7 @@
       }
     });
 
-    test('BillingClient.launchBillingFlow', () async {
+    testWidgets('BillingClient.launchBillingFlow', (WidgetTester tester) async {
       try {
         await billingClient.launchBillingFlow(product: 'product');
       } on MissingPluginException {
@@ -84,7 +86,8 @@
       }
     });
 
-    test('BillingClient.queryProductDetails', () async {
+    testWidgets('BillingClient.queryProductDetails',
+        (WidgetTester tester) async {
       try {
         await billingClient
             .queryProductDetails(productList: <ProductWrapper>[]);
@@ -99,7 +102,8 @@
       }
     });
 
-    test('BillingClient.queryPurchaseHistory', () async {
+    testWidgets('BillingClient.queryPurchaseHistory',
+        (WidgetTester tester) async {
       try {
         await billingClient.queryPurchaseHistory(ProductType.inapp);
       } on MissingPluginException {
@@ -107,7 +111,7 @@
       }
     });
 
-    test('BillingClient.queryPurchases', () async {
+    testWidgets('BillingClient.queryPurchases', (WidgetTester tester) async {
       try {
         await billingClient.queryPurchases(ProductType.inapp);
       } on MissingPluginException {
@@ -115,7 +119,7 @@
       }
     });
 
-    test('BillingClient.startConnection', () async {
+    testWidgets('BillingClient.startConnection', (WidgetTester tester) async {
       try {
         await billingClient.startConnection(
             onBillingServiceDisconnected: () {});
diff --git a/packages/shared_preferences/shared_preferences/CHANGELOG.md b/packages/shared_preferences/shared_preferences/CHANGELOG.md
index 05e575f..af6872d 100644
--- a/packages/shared_preferences/shared_preferences/CHANGELOG.md
+++ b/packages/shared_preferences/shared_preferences/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## NEXT
 
+* Fixes the example app to be debuggable on Android.
 * Deletes deprecated splash screen meta-data element.
 
 ## 2.2.0
diff --git a/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml b/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..d60d6f6
--- /dev/null
+++ b/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.flutter.plugins.sharedpreferencesexample">
+    <!-- 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/script/configs/exclude_integration_android_emulator.yaml b/script/configs/exclude_integration_android_emulator.yaml
new file mode 100644
index 0000000..bcb8c4f
--- /dev/null
+++ b/script/configs/exclude_integration_android_emulator.yaml
@@ -0,0 +1,8 @@
+# Hangs due to permission issue, see https://github.com/flutter/flutter/issues/130987
+# TODO(stuartmorgan): Remove once the permission issue is addressed.
+- camera/camera
+- camera_android
+- camera_android_camerax
+# Frequent flaky failures, see https://github.com/flutter/flutter/issues/130986
+# TODO(stuartmorgan): Remove once the flake is fixed.
+- google_maps_flutter_android