Set plugin template minimum iOS version to 11.0 (#122625)

Set plugin template minimum iOS version to 11.0
diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart
index ccb8330..d6ec816 100644
--- a/dev/devicelab/lib/tasks/plugin_tests.dart
+++ b/dev/devicelab/lib/tasks/plugin_tests.dart
@@ -346,7 +346,7 @@
       throw TaskResult.failure('podspec file missing at ${podspec.path}');
     }
     final String versionString = target == 'ios'
-        ? "s.platform = :ios, '9.0'"
+        ? "s.platform = :ios, '11.0'"
         : "s.platform = :osx, '10.11'";
     String podspecContent = podspec.readAsStringSync();
     if (!podspecContent.contains(versionString)) {
diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart
index cde0e98..c8dba57 100644
--- a/packages/flutter_tools/lib/src/commands/create_base.dart
+++ b/packages/flutter_tools/lib/src/commands/create_base.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:meta/meta.dart';
-import 'package:pub_semver/pub_semver.dart';
 import 'package:uuid/uuid.dart';
 
 import '../android/android.dart' as android_common;
@@ -381,12 +380,6 @@
     // https://developer.gnome.org/gio/stable/GApplication.html#g-application-id-is-valid
     final String linuxIdentifier = androidIdentifier;
 
-    // TODO(dacoharkes): Replace with hardcoded version in template when Flutter 2.11 is released.
-    final Version ffiPluginStableRelease = Version(2, 11, 0);
-    final String minFrameworkVersionFfiPlugin = Version.parse(globals.flutterVersion.frameworkVersion) < ffiPluginStableRelease
-        ? globals.flutterVersion.frameworkVersion
-        : ffiPluginStableRelease.toString();
-
     return <String, Object?>{
       'organization': organization,
       'projectName': projectName,
@@ -416,7 +409,6 @@
       'iosDevelopmentTeam': iosDevelopmentTeam ?? '',
       'flutterRevision': globals.flutterVersion.frameworkRevision,
       'flutterChannel': globals.flutterVersion.channel,
-      'minFrameworkVersionFfiPlugin': minFrameworkVersionFfiPlugin,
       'ios': ios,
       'android': android,
       'web': web,
diff --git a/packages/flutter_tools/templates/plugin/ios-objc.tmpl/projectName.podspec.tmpl b/packages/flutter_tools/templates/plugin/ios-objc.tmpl/projectName.podspec.tmpl
index 6f0a53c..e44da71 100644
--- a/packages/flutter_tools/templates/plugin/ios-objc.tmpl/projectName.podspec.tmpl
+++ b/packages/flutter_tools/templates/plugin/ios-objc.tmpl/projectName.podspec.tmpl
@@ -16,7 +16,7 @@
   s.source_files = 'Classes/**/*'
   s.public_header_files = 'Classes/**/*.h'
   s.dependency 'Flutter'
-  s.platform = :ios, '9.0'
+  s.platform = :ios, '11.0'
 
   # Flutter.framework does not contain a i386 slice.
   s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
diff --git a/packages/flutter_tools/templates/plugin/ios-swift.tmpl/projectName.podspec.tmpl b/packages/flutter_tools/templates/plugin/ios-swift.tmpl/projectName.podspec.tmpl
index 1760c3f..bbdb51c 100644
--- a/packages/flutter_tools/templates/plugin/ios-swift.tmpl/projectName.podspec.tmpl
+++ b/packages/flutter_tools/templates/plugin/ios-swift.tmpl/projectName.podspec.tmpl
@@ -15,7 +15,7 @@
   s.source           = { :path => '.' }
   s.source_files = 'Classes/**/*'
   s.dependency 'Flutter'
-  s.platform = :ios, '9.0'
+  s.platform = :ios, '11.0'
 
   # Flutter.framework does not contain a i386 slice.
   s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
diff --git a/packages/flutter_tools/templates/plugin_ffi/ios.tmpl/projectName.podspec.tmpl b/packages/flutter_tools/templates/plugin_ffi/ios.tmpl/projectName.podspec.tmpl
index b914d85..7a5c304 100644
--- a/packages/flutter_tools/templates/plugin_ffi/ios.tmpl/projectName.podspec.tmpl
+++ b/packages/flutter_tools/templates/plugin_ffi/ios.tmpl/projectName.podspec.tmpl
@@ -20,7 +20,7 @@
   s.source           = { :path => '.' }
   s.source_files = 'Classes/**/*'
   s.dependency 'Flutter'
-  s.platform = :ios, '9.0'
+  s.platform = :ios, '11.0'
 
   # Flutter.framework does not contain a i386 slice.
   s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
diff --git a/packages/flutter_tools/templates/plugin_shared/pubspec.yaml.tmpl b/packages/flutter_tools/templates/plugin_shared/pubspec.yaml.tmpl
index df5ad09..8641c2f 100644
--- a/packages/flutter_tools/templates/plugin_shared/pubspec.yaml.tmpl
+++ b/packages/flutter_tools/templates/plugin_shared/pubspec.yaml.tmpl
@@ -5,12 +5,7 @@
 
 environment:
   sdk: {{dartSdkVersionBounds}}
-{{#withPlatformChannelPluginHook}}
-  flutter: ">=2.5.0"
-{{/withPlatformChannelPluginHook}}
-{{#withFfiPluginHook}}
-  flutter: ">={{minFrameworkVersionFfiPlugin}}"
-{{/withFfiPluginHook}}
+  flutter: ">=3.3.0"
 
 dependencies:
   flutter:
diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
index e07f1a5..3d8568e 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
@@ -2762,7 +2762,7 @@
     Logger: () => logger,
   });
 
-  testUsingContext('newly created plugin has min flutter sdk version as 2.5.0', () async {
+  testUsingContext('newly created plugin has min flutter sdk version as 3.3.0', () async {
     Cache.flutterRoot = '../..';
 
     final CreateCommand command = CreateCommand();
@@ -2771,8 +2771,54 @@
     final String rawPubspec = await projectDir.childFile('pubspec.yaml').readAsString();
     final Pubspec pubspec = Pubspec.parse(rawPubspec);
     final Map<String, VersionConstraint?> env = pubspec.environment!;
-    expect(env['flutter']!.allows(Version(2, 5, 0)), true);
-    expect(env['flutter']!.allows(Version(2, 4, 9)), false);
+    expect(env['flutter']!.allows(Version(3, 3, 0)), true);
+    expect(env['flutter']!.allows(Version(3, 2, 9)), false);
+  });
+
+  testUsingContext('newly created iOS plugins has min iOS version of 11.0', () async {
+    Cache.flutterRoot = '../..';
+    final String flutterToolsAbsolutePath = globals.fs.path.join(
+      Cache.flutterRoot!,
+      'packages',
+      'flutter_tools',
+    );
+    final List<String> iosPluginTemplates = <String>[
+      globals.fs.path.join(
+        flutterToolsAbsolutePath,
+        'templates',
+        'plugin',
+        'ios-objc.tmpl',
+        'projectName.podspec.tmpl',
+      ),
+      globals.fs.path.join(
+        flutterToolsAbsolutePath,
+        'templates',
+        'plugin',
+        'ios-swift.tmpl',
+        'projectName.podspec.tmpl',
+      ),
+      globals.fs.path.join(
+        flutterToolsAbsolutePath,
+        'templates',
+        'plugin_ffi',
+        'ios.tmpl',
+        'projectName.podspec.tmpl',
+      ),
+    ];
+
+    for (final String templatePath in iosPluginTemplates) {
+      final String rawTemplate = globals.fs.file(templatePath).readAsStringSync();
+      expect(rawTemplate, contains("s.platform = :ios, '11.0'"));
+    }
+
+    final CreateCommand command = CreateCommand();
+    final CommandRunner<void> runner = createTestCommandRunner(command);
+    await runner.run(<String>['create', '--no-pub', '--template=plugin', '--platform=ios', projectDir.path]);
+
+    expect(projectDir.childDirectory('ios').childFile('flutter_project.podspec'),
+        exists);
+    final String rawPodSpec = await projectDir.childDirectory('ios').childFile('flutter_project.podspec').readAsString();
+    expect(rawPodSpec, contains("s.platform = :ios, '11.0'"));
   });
 
   testUsingContext('default app uses flutter default versions', () async {
diff --git a/packages/integration_test/ios/Classes/IntegrationTestPlugin.m b/packages/integration_test/ios/Classes/IntegrationTestPlugin.m
index a8a80b6..fc2dc54 100644
--- a/packages/integration_test/ios/Classes/IntegrationTestPlugin.m
+++ b/packages/integration_test/ios/Classes/IntegrationTestPlugin.m
@@ -88,18 +88,11 @@
   CGRect screenshotBounds = window.bounds;
   UIImage *image;
 
-  if (@available(iOS 10, *)) {
-    UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithBounds:screenshotBounds];
+  UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithBounds:screenshotBounds];
 
-    image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
-      [window drawViewHierarchyInRect:screenshotBounds afterScreenUpdates:YES];
-    }];
-  } else {
-    UIGraphicsBeginImageContextWithOptions(screenshotBounds.size, NO, UIScreen.mainScreen.scale);
+  image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *rendererContext) {
     [window drawViewHierarchyInRect:screenshotBounds afterScreenUpdates:YES];
-    image = UIGraphicsGetImageFromCurrentImageContext();
-    UIGraphicsEndImageContext();
-  }
+  }];
 
   return image;
 }
diff --git a/packages/integration_test/ios/integration_test.podspec b/packages/integration_test/ios/integration_test.podspec
index 39f9dbf..0a67820 100644
--- a/packages/integration_test/ios/integration_test.podspec
+++ b/packages/integration_test/ios/integration_test.podspec
@@ -20,6 +20,6 @@
   s.dependency 'Flutter'
   s.ios.framework  = 'UIKit'
 
-  s.platform = :ios, '9.0'
+  s.platform = :ios, '11.0'
   s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
 end