Flutter 1.22.0-12.2.pre Framework cherrypicks (#66500)

* Deprecate VelocityTracker default constructor and added VelocityTracker.withKind constructor (#66043)

* [flutter_tools] fix failure to create ansi spinner if download needs to be retried (#65797)

* Listen to Debug VM stream to get Stdout logs from VMService (#66310)

* Update cherry picked engine

Co-authored-by: Jonah Williams <jonahwilliams@google.com>
Co-authored-by: Jenn Magder <magder@google.com>
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index e25960a..9b3d6ec 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-4654fc6cf6416daae78eac2c211ad84c46e21625
+f763b5b9b936872bc6c84b4395286ce684e3b431
diff --git a/dev/benchmarks/microbenchmarks/lib/gestures/velocity_tracker_bench.dart b/dev/benchmarks/microbenchmarks/lib/gestures/velocity_tracker_bench.dart
index 2287aca..ebb6630 100644
--- a/dev/benchmarks/microbenchmarks/lib/gestures/velocity_tracker_bench.dart
+++ b/dev/benchmarks/microbenchmarks/lib/gestures/velocity_tracker_bench.dart
@@ -20,7 +20,7 @@
   assert(false, "Don't run benchmarks in checked mode! Use 'flutter run --release'.");
   final BenchmarkResultPrinter printer = BenchmarkResultPrinter();
   final List<TrackerBenchmark> benchmarks = <TrackerBenchmark>[
-    TrackerBenchmark(name: 'velocity_tracker_iteration', tracker: VelocityTracker(PointerDeviceKind.touch)),
+    TrackerBenchmark(name: 'velocity_tracker_iteration', tracker: VelocityTracker.withKind(PointerDeviceKind.touch)),
     TrackerBenchmark(name: 'velocity_tracker_iteration_ios_fling', tracker: IOSScrollViewFlingVelocityTracker(PointerDeviceKind.touch)),
   ];
   final Stopwatch watch = Stopwatch();
diff --git a/packages/flutter/lib/src/gestures/long_press.dart b/packages/flutter/lib/src/gestures/long_press.dart
index c37b1ed..300de65 100644
--- a/packages/flutter/lib/src/gestures/long_press.dart
+++ b/packages/flutter/lib/src/gestures/long_press.dart
@@ -376,7 +376,7 @@
   void handlePrimaryPointer(PointerEvent event) {
     if (!event.synthesized) {
       if (event is PointerDownEvent) {
-        _velocityTracker = VelocityTracker(event.kind);
+        _velocityTracker = VelocityTracker.withKind(event.kind);
         _velocityTracker!.addPosition(event.timeStamp, event.localPosition);
       }
       if (event is PointerMoveEvent) {
diff --git a/packages/flutter/lib/src/gestures/monodrag.dart b/packages/flutter/lib/src/gestures/monodrag.dart
index 829a665..602fff7 100644
--- a/packages/flutter/lib/src/gestures/monodrag.dart
+++ b/packages/flutter/lib/src/gestures/monodrag.dart
@@ -69,7 +69,7 @@
   }) : assert(dragStartBehavior != null),
        super(debugOwner: debugOwner, kind: kind);
 
-  static VelocityTracker _defaultBuilder(PointerEvent event) => VelocityTracker(event.kind);
+  static VelocityTracker _defaultBuilder(PointerEvent event) => VelocityTracker.withKind(event.kind);
   /// Configure the behavior of offsets sent to [onStart].
   ///
   /// If set to [DragStartBehavior.start], the [onStart] callback will be called
diff --git a/packages/flutter/lib/src/gestures/multidrag.dart b/packages/flutter/lib/src/gestures/multidrag.dart
index 91b1e32..4c347f3 100644
--- a/packages/flutter/lib/src/gestures/multidrag.dart
+++ b/packages/flutter/lib/src/gestures/multidrag.dart
@@ -30,7 +30,7 @@
   /// The [initialPosition] argument must not be null.
   MultiDragPointerState(this.initialPosition, this.kind)
     : assert(initialPosition != null),
-      _velocityTracker = VelocityTracker(kind);
+      _velocityTracker = VelocityTracker.withKind(kind);
 
   /// The global coordinates of the pointer when the pointer contacted the screen.
   final Offset initialPosition;
diff --git a/packages/flutter/lib/src/gestures/scale.dart b/packages/flutter/lib/src/gestures/scale.dart
index ab517d0..b75b439 100644
--- a/packages/flutter/lib/src/gestures/scale.dart
+++ b/packages/flutter/lib/src/gestures/scale.dart
@@ -286,7 +286,7 @@
   @override
   void addAllowedPointer(PointerEvent event) {
     startTrackingPointer(event.pointer, event.transform);
-    _velocityTrackers[event.pointer] = VelocityTracker(event.kind);
+    _velocityTrackers[event.pointer] = VelocityTracker.withKind(event.kind);
     if (_state == _ScaleState.ready) {
       _state = _ScaleState.possible;
       _initialSpan = 0.0;
diff --git a/packages/flutter/lib/src/gestures/velocity_tracker.dart b/packages/flutter/lib/src/gestures/velocity_tracker.dart
index d898d2b..6739fff 100644
--- a/packages/flutter/lib/src/gestures/velocity_tracker.dart
+++ b/packages/flutter/lib/src/gestures/velocity_tracker.dart
@@ -149,7 +149,14 @@
 /// have been received.
 class VelocityTracker {
   /// Create a new velocity tracker for a pointer [kind].
-  VelocityTracker(this.kind);
+  @Deprecated(
+    'Use VelocityTracker.withKind and provide the PointerDeviceKind associated with the gesture being tracked. '
+    'This feature was deprecated after v1.22.0-12.1.pre.'
+  )
+  VelocityTracker([this.kind = PointerDeviceKind.touch]);
+
+  /// Create a new velocity tracker for a pointer [kind].
+  VelocityTracker.withKind(this.kind);
 
   static const int _assumePointerMoveStoppedMilliseconds = 40;
   static const int _historySize = 20;
@@ -281,7 +288,7 @@
 ///   the iOS method that reports the fling velocity when the touch is released.
 class IOSScrollViewFlingVelocityTracker extends VelocityTracker {
   /// Create a new IOSScrollViewFlingVelocityTracker.
-  IOSScrollViewFlingVelocityTracker(PointerDeviceKind kind) : super(kind);
+  IOSScrollViewFlingVelocityTracker(PointerDeviceKind kind) : super.withKind(kind);
 
   /// The velocity estimation uses at most 4 `_PointAtTime` samples. The extra
   /// samples are there to make the `VelocityEstimate.offset` sufficiently large
diff --git a/packages/flutter/lib/src/widgets/scroll_configuration.dart b/packages/flutter/lib/src/widgets/scroll_configuration.dart
index e3465e1..408fdd4 100644
--- a/packages/flutter/lib/src/widgets/scroll_configuration.dart
+++ b/packages/flutter/lib/src/widgets/scroll_configuration.dart
@@ -78,7 +78,7 @@
       case TargetPlatform.fuchsia:
       case TargetPlatform.linux:
       case TargetPlatform.windows:
-        return (PointerEvent event) => VelocityTracker(event.kind);
+        return (PointerEvent event) => VelocityTracker.withKind(event.kind);
     }
     assert(false);
     return (PointerEvent event) => VelocityTracker(event.kind);
diff --git a/packages/flutter/test/gestures/velocity_tracker_test.dart b/packages/flutter/test/gestures/velocity_tracker_test.dart
index afb27d5..e18d946 100644
--- a/packages/flutter/test/gestures/velocity_tracker_test.dart
+++ b/packages/flutter/test/gestures/velocity_tracker_test.dart
@@ -38,7 +38,7 @@
   ];
 
   test('Velocity tracker gives expected results', () {
-    final VelocityTracker tracker = VelocityTracker(PointerDeviceKind.touch);
+    final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
     int i = 0;
     for (final PointerEvent event in velocityEventData) {
       if (event is PointerDownEvent || event is PointerMoveEvent)
@@ -64,7 +64,7 @@
 
   test('Interrupted velocity estimation', () {
     // Regression test for https://github.com/flutter/flutter/pull/7510
-    final VelocityTracker tracker = VelocityTracker(PointerDeviceKind.touch);
+    final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
     for (final PointerEvent event in interruptedVelocityEventData) {
       if (event is PointerDownEvent || event is PointerMoveEvent)
         tracker.addPosition(event.timeStamp, event.position);
@@ -75,7 +75,7 @@
   });
 
   test('No data velocity estimation', () {
-    final VelocityTracker tracker = VelocityTracker(PointerDeviceKind.touch);
+    final VelocityTracker tracker = VelocityTracker.withKind(PointerDeviceKind.touch);
     expect(tracker.getVelocity(), Velocity.zero);
   });
 
diff --git a/packages/flutter/test/widgets/range_maintaining_scroll_physics_test.dart b/packages/flutter/test/widgets/range_maintaining_scroll_physics_test.dart
index 9578739..6be992c 100644
--- a/packages/flutter/test/widgets/range_maintaining_scroll_physics_test.dart
+++ b/packages/flutter/test/widgets/range_maintaining_scroll_physics_test.dart
@@ -310,7 +310,7 @@
 
   @override
   GestureVelocityTrackerBuilder velocityTrackerBuilder(BuildContext context) {
-    return (PointerEvent event) => VelocityTracker(event.kind);
+    return (PointerEvent event) => VelocityTracker.withKind(event.kind);
   }
 
   @override
diff --git a/packages/flutter/test/widgets/scroll_behavior_test.dart b/packages/flutter/test/widgets/scroll_behavior_test.dart
index e668bda..126f1af 100644
--- a/packages/flutter/test/widgets/scroll_behavior_test.dart
+++ b/packages/flutter/test/widgets/scroll_behavior_test.dart
@@ -27,7 +27,7 @@
   @override
   GestureVelocityTrackerBuilder velocityTrackerBuilder(BuildContext context) {
       lastCreatedBuilder = flag
-        ? (PointerEvent ev) => VelocityTracker(ev.kind)
+        ? (PointerEvent ev) => VelocityTracker.withKind(ev.kind)
         : (PointerEvent ev) => IOSScrollViewFlingVelocityTracker(ev.kind);
       return lastCreatedBuilder;
   }
diff --git a/packages/flutter_tools/lib/src/base/terminal.dart b/packages/flutter_tools/lib/src/base/terminal.dart
index e0e2b4b..4d329af 100644
--- a/packages/flutter_tools/lib/src/base/terminal.dart
+++ b/packages/flutter_tools/lib/src/base/terminal.dart
@@ -81,7 +81,10 @@
 
 /// The command line terminal, if available.
 abstract class Terminal {
-  factory Terminal.test() = _TestTerminal;
+  /// Create a new test [Terminal].
+  ///
+  /// If not specified, [supportsColor] defaults to `false`.
+  factory Terminal.test({bool supportsColor}) = _TestTerminal;
 
   /// Whether the current terminal supports color escape codes.
   bool get supportsColor;
@@ -300,6 +303,8 @@
 }
 
 class _TestTerminal implements Terminal {
+  _TestTerminal({this.supportsColor = false});
+
   @override
   bool usesTerminalUi;
 
@@ -329,7 +334,7 @@
   set singleCharMode(bool value) { }
 
   @override
-  bool get supportsColor => false;
+  final bool supportsColor;
 
   @override
   bool get supportsEmoji => false;
diff --git a/packages/flutter_tools/lib/src/cache.dart b/packages/flutter_tools/lib/src/cache.dart
index db3f6f9..a35d8f8 100644
--- a/packages/flutter_tools/lib/src/cache.dart
+++ b/packages/flutter_tools/lib/src/cache.dart
@@ -1466,13 +1466,14 @@
   ) async {
     final String downloadPath = flattenNameSubdirs(url, _fileSystem);
     final File tempFile = _createDownloadFile(downloadPath);
-    final Status status = _logger.startProgress(
-      message,
-      timeout: null, // This will take a variable amount of time based on network connectivity.
-    );
+    Status status;
     int retries = _kRetryCount;
 
     while (retries > 0) {
+      status = _logger.startProgress(
+        message,
+        timeout: null, // This will take a variable amount of time based on network connectivity.
+      );
       try {
         _ensureExists(tempFile.parent);
         final IOSink ioSink = tempFile.openWrite();
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index 6e5266c..190824b 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -10,6 +10,7 @@
 import 'package:vm_service/vm_service.dart' as vm_service;
 
 import '../application_package.dart';
+import '../base/common.dart';
 import '../base/file_system.dart';
 import '../base/io.dart';
 import '../base/logger.dart';
@@ -670,6 +671,10 @@
       return;
     }
     try {
+      // The VM service will not publish logging events unless the debug stream is being listened to.
+      // Listen to this stream as a side effect.
+      unawaited(connectedVmService.streamListen('Debug'));
+
       await Future.wait(<Future<void>>[
         connectedVmService.streamListen(vm_service.EventStreams.kStdout),
         connectedVmService.streamListen(vm_service.EventStreams.kStderr),
diff --git a/packages/flutter_tools/test/general.shard/artifact_updater_test.dart b/packages/flutter_tools/test/general.shard/artifact_updater_test.dart
index a86cdbd..b6f7c49 100644
--- a/packages/flutter_tools/test/general.shard/artifact_updater_test.dart
+++ b/packages/flutter_tools/test/general.shard/artifact_updater_test.dart
@@ -10,10 +10,12 @@
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
 import 'package:flutter_tools/src/base/platform.dart';
+import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:mockito/mockito.dart';
 
 import '../src/common.dart';
+import '../src/mocks.dart';
 
 final Platform testPlatform = FakePlatform(environment: <String, String>{});
 
@@ -41,6 +43,34 @@
     expect(fileSystem.file('out/test'), exists);
   });
 
+  testWithoutContext('ArtifactUpdater will restart the status ticker if it needs to retry the download', () async {
+    final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils();
+    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
+    final Logger logger = StdoutLogger(
+      terminal: Terminal.test(supportsColor: true),
+      stdio: MockStdio(),
+      outputPreferences: OutputPreferences.test(),
+      timeoutConfiguration: const TimeoutConfiguration(),
+    );
+    final ArtifactUpdater artifactUpdater = ArtifactUpdater(
+      fileSystem: fileSystem,
+      logger: logger,
+      operatingSystemUtils: operatingSystemUtils,
+      platform: testPlatform,
+      httpClient: MockHttpClient()..exceptionOnFirstRun = true,
+      tempStorage: fileSystem.currentDirectory.childDirectory('temp')
+        ..createSync(),
+    );
+
+    await artifactUpdater.downloadZipArchive(
+      'test message',
+      Uri.parse('http:///test.zip'),
+      fileSystem.currentDirectory.childDirectory('out'),
+    );
+
+    expect(fileSystem.file('out/test'), exists);
+  });
+
   testWithoutContext('ArtifactUpdater will re-attempt on a non-200 response', () async {
     final MockOperatingSystemUtils operatingSystemUtils = MockOperatingSystemUtils();
     final MemoryFileSystem fileSystem = MemoryFileSystem.test();
@@ -249,10 +279,15 @@
 class MockHttpClient extends Mock implements HttpClient {
   int attempts = 0;
   bool argumentError = false;
+  bool exceptionOnFirstRun = false;
   final MockHttpClientRequest testRequest = MockHttpClientRequest();
 
   @override
   Future<HttpClientRequest> getUrl(Uri url) async {
+    if (exceptionOnFirstRun && attempts == 0) {
+      attempts += 1;
+      throw Exception();
+    }
     attempts += 1;
     if (argumentError) {
       throw ArgumentError();
diff --git a/packages/flutter_tools/test/general.shard/ios/ios_device_logger_test.dart b/packages/flutter_tools/test/general.shard/ios/ios_device_logger_test.dart
index bd95e87..f1ff16c 100644
--- a/packages/flutter_tools/test/general.shard/ios/ios_device_logger_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/ios_device_logger_test.dart
@@ -189,6 +189,7 @@
       equals('  This is a message '),
       equals('  And this is an error '),
     ]));
+    verify(vmService.streamListen('Debug'));
   });
 }