Expose enable-experiment in Flutter drive (#66311)

diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart
index 8d3517b..2515f94 100644
--- a/packages/flutter_tools/lib/executable.dart
+++ b/packages/flutter_tools/lib/executable.dart
@@ -93,7 +93,7 @@
     DevicesCommand(),
     DoctorCommand(verbose: verbose),
     DowngradeCommand(),
-    DriveCommand(),
+    DriveCommand(verboseHelp: verboseHelp),
     EmulatorsCommand(),
     FormatCommand(),
     GenerateCommand(),
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index b086b0e..6e2b638 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -50,9 +50,11 @@
 /// successful the exit code will be `0`. Otherwise, you will see a non-zero
 /// exit code.
 class DriveCommand extends RunCommandBase {
-  DriveCommand() {
+  DriveCommand({
+    bool verboseHelp = false,
+  }) {
     requiresPubspecYaml();
-
+    addEnableExperimentation(hide: !verboseHelp);
     argParser
       ..addFlag('keep-app-running',
         defaultsTo: null,
@@ -322,7 +324,18 @@
     }
 
     try {
-      await testRunner(<String>[testFile], environment);
+      await testRunner(
+        <String>[
+          if (buildInfo.dartExperiments.isNotEmpty)
+            '--enable-experiment=${buildInfo.dartExperiments.join(',')}',
+          if (buildInfo.nullSafetyMode == NullSafetyMode.sound)
+            '--sound-null-safety',
+          if (buildInfo.nullSafetyMode == NullSafetyMode.unsound)
+            '--no-sound-null-safety',
+          testFile,
+        ],
+        environment,
+      );
     } on Exception catch (error, stackTrace) {
       if (error is ToolExit) {
         rethrow;
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
index e0242ad..d3689c0 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart
@@ -205,7 +205,7 @@
         return LaunchResult.succeeded();
       });
       testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
-        expect(testArgs, <String>[testFile]);
+        expect(testArgs, <String>['--no-sound-null-safety', testFile]);
         // VM_SERVICE_URL is not set by drive command arguments
         expect(environment, <String, String>{
           'VM_SERVICE_URL': 'null',
@@ -273,6 +273,90 @@
       ProcessManager: () => FakeProcessManager.any(),
     });
 
+    testUsingContext('enable experiment', () async {
+      final MockAndroidDevice mockDevice = MockAndroidDevice();
+      applyDdsMocks(mockDevice);
+      testDeviceManager.addDevice(mockDevice);
+
+      final String testApp = globals.fs.path.join(tempDir.path, 'test', 'e2e.dart');
+      final String testFile = globals.fs.path.join(tempDir.path, 'test_driver', 'e2e_test.dart');
+
+      appStarter = expectAsync2((DriveCommand command, Uri webUri) async {
+        return LaunchResult.succeeded();
+      });
+      testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
+        expect(
+          testArgs,
+          <String>[
+            '--enable-experiment=experiment1,experiment2',
+            '--no-sound-null-safety',
+            testFile,
+          ]
+        );
+      });
+      appStopper = expectAsync1((DriveCommand command) async {
+        return true;
+      });
+
+      final MemoryFileSystem memFs = fs;
+      await memFs.file(testApp).writeAsString('main() {}');
+      await memFs.file(testFile).writeAsString('main() {}');
+
+      final List<String> args = <String>[
+        'drive',
+        '--target=$testApp',
+        '--no-pub',
+        '--enable-experiment=experiment1',
+        '--enable-experiment=experiment2',
+      ];
+      await createTestCommandRunner(command).run(args);
+      expect(testLogger.errorText, isEmpty);
+    }, overrides: <Type, Generator>{
+      FileSystem: () => fs,
+      ProcessManager: () => FakeProcessManager.any(),
+    });
+
+    testUsingContext('sound null safety', () async {
+      final MockAndroidDevice mockDevice = MockAndroidDevice();
+      applyDdsMocks(mockDevice);
+      testDeviceManager.addDevice(mockDevice);
+
+      final String testApp = globals.fs.path.join(tempDir.path, 'test', 'e2e.dart');
+      final String testFile = globals.fs.path.join(tempDir.path, 'test_driver', 'e2e_test.dart');
+
+      appStarter = expectAsync2((DriveCommand command, Uri webUri) async {
+        return LaunchResult.succeeded();
+      });
+      testRunner = expectAsync2((List<String> testArgs, Map<String, String> environment) async {
+        expect(
+          testArgs,
+          <String>[
+            '--sound-null-safety',
+            testFile,
+          ]
+        );
+      });
+      appStopper = expectAsync1((DriveCommand command) async {
+        return true;
+      });
+
+      final MemoryFileSystem memFs = fs;
+      await memFs.file(testApp).writeAsString('main() {}');
+      await memFs.file(testFile).writeAsString('main() {}');
+
+      final List<String> args = <String>[
+        'drive',
+        '--target=$testApp',
+        '--no-pub',
+        '--sound-null-safety',
+      ];
+      await createTestCommandRunner(command).run(args);
+      expect(testLogger.errorText, isEmpty);
+    }, overrides: <Type, Generator>{
+      FileSystem: () => fs,
+      ProcessManager: () => FakeProcessManager.any(),
+    });
+
     group('findTargetDevice', () {
       testUsingContext('uses specified device', () async {
         testDeviceManager.specifiedDeviceId = '123';