Reverse dependency between services and scheduler (#54212)

diff --git a/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart b/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart
index 12a5530..37dcdd3 100644
--- a/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart
+++ b/dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart
@@ -736,8 +736,8 @@
 class _RecordingWidgetsBinding extends BindingBase
     with
         GestureBinding,
-        ServicesBinding,
         SchedulerBinding,
+        ServicesBinding,
         PaintingBinding,
         SemanticsBinding,
         RendererBinding,
diff --git a/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart b/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart
index 173ba34..5d6b5a6 100644
--- a/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart
+++ b/dev/integration_tests/ios_add2app_life_cycle/flutterapp/lib/main.dart
@@ -5,7 +5,7 @@
 import 'dart:ui' as ui;
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
-import 'package:flutter/scheduler.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter/foundation.dart';
 import 'package:collection/collection.dart';
 
@@ -48,7 +48,7 @@
     super.initState();
     WidgetsBinding.instance.addObserver(this);
     _actualLifeCycleSequence =  <AppLifecycleState>[
-      SchedulerBinding.instance.lifecycleState
+      ServicesBinding.instance.lifecycleState
     ];
   }
 
diff --git a/packages/flutter/lib/src/foundation/binding.dart b/packages/flutter/lib/src/foundation/binding.dart
index 957f859..126c77a 100644
--- a/packages/flutter/lib/src/foundation/binding.dart
+++ b/packages/flutter/lib/src/foundation/binding.dart
@@ -6,7 +6,7 @@
 import 'dart:convert' show json;
 import 'dart:developer' as developer;
 import 'dart:io' show exit;
-import 'dart:ui' as ui show saveCompilationTrace, Window, window;
+import 'dart:ui' as ui show AppLifecycleState, saveCompilationTrace, Window, window;
 // Before adding any more dart:ui imports, please read the README.
 
 import 'package:meta/meta.dart';
@@ -552,6 +552,29 @@
     });
   }
 
+  // TODO(goderbauer): Remove the next two members after the service/scheduler dependencies
+  //  have been turned around.
+
+  /// Whether the application is visible, and if so, whether it is currently
+  /// interactive.
+  ///
+  /// This is set by [handleAppLifecycleStateChanged] when the
+  /// [SystemChannels.lifecycle] notification is dispatched.
+  ///
+  /// The preferred way to watch for changes to this value is using
+  /// [WidgetsBindingObserver.didChangeAppLifecycleState].
+  ui.AppLifecycleState get lifecycleState => null;
+
+  /// Called when the application lifecycle state changes.
+  ///
+  /// Notifies all the observers using
+  /// [WidgetsBindingObserver.didChangeAppLifecycleState].
+  ///
+  /// This method exposes notifications from [SystemChannels.lifecycle].
+  @protected
+  @mustCallSuper
+  void handleAppLifecycleStateChanged(ui.AppLifecycleState state) { }
+
   @override
   String toString() => '<${objectRuntimeType(this, 'BindingBase')}>';
 }
diff --git a/packages/flutter/lib/src/rendering/binding.dart b/packages/flutter/lib/src/rendering/binding.dart
index 97d49a8..49ea361 100644
--- a/packages/flutter/lib/src/rendering/binding.dart
+++ b/packages/flutter/lib/src/rendering/binding.dart
@@ -467,7 +467,7 @@
 /// rendering layer directly. If you are writing to a higher-level
 /// library, such as the Flutter Widgets library, then you would use
 /// that layer's binding.
-class RenderingFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, SemanticsBinding, PaintingBinding, RendererBinding {
+class RenderingFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, SemanticsBinding, PaintingBinding, RendererBinding {
   /// Creates a binding for the rendering layer.
   ///
   /// The `root` render box is attached directly to the [renderView] and is
diff --git a/packages/flutter/lib/src/scheduler/binding.dart b/packages/flutter/lib/src/scheduler/binding.dart
index 394c57f..3e64cfb 100644
--- a/packages/flutter/lib/src/scheduler/binding.dart
+++ b/packages/flutter/lib/src/scheduler/binding.dart
@@ -9,7 +9,6 @@
 
 import 'package:collection/collection.dart' show PriorityQueue, HeapPriorityQueue;
 import 'package:flutter/foundation.dart';
-import 'package:flutter/services.dart';
 
 import 'debug.dart';
 import 'priority.dart';
@@ -197,13 +196,11 @@
 /// * Non-rendering tasks, to be run between frames. These are given a
 ///   priority and are executed in priority order according to a
 ///   [schedulingStrategy].
-mixin SchedulerBinding on BindingBase, ServicesBinding {
+mixin SchedulerBinding on BindingBase {
   @override
   void initInstances() {
     super.initInstances();
     _instance = this;
-    SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
-    readInitialLifecycleStateFromNativeWindow();
 
     if (!kReleaseMode) {
       int frameNumber = 0;
@@ -302,35 +299,19 @@
   ///
   /// The preferred way to watch for changes to this value is using
   /// [WidgetsBindingObserver.didChangeAppLifecycleState].
+  @override
   AppLifecycleState get lifecycleState => _lifecycleState;
   AppLifecycleState _lifecycleState;
 
-  /// Initializes the [lifecycleState] with the [initialLifecycleState] from the
-  /// window.
-  ///
-  /// Once the [lifecycleState] is populated through any means (including this
-  /// method), this method will do nothing. This is because the
-  /// [initialLifecycleState] may already be stale and it no longer makes sense
-  /// to use the initial state at dart vm startup as the current state anymore.
-  ///
-  /// The latest state should be obtained by subscribing to
-  /// [WidgetsBindingObserver.didChangeAppLifecycleState].
-  @protected
-  void readInitialLifecycleStateFromNativeWindow() {
-    if (_lifecycleState == null && _parseAppLifecycleMessage(window.initialLifecycleState) != null) {
-      _handleLifecycleMessage(window.initialLifecycleState);
-    }
-  }
-
   /// Called when the application lifecycle state changes.
   ///
   /// Notifies all the observers using
   /// [WidgetsBindingObserver.didChangeAppLifecycleState].
   ///
   /// This method exposes notifications from [SystemChannels.lifecycle].
-  @protected
-  @mustCallSuper
+  @override
   void handleAppLifecycleStateChanged(AppLifecycleState state) {
+    super.handleAppLifecycleStateChanged(state);
     assert(state != null);
     _lifecycleState = state;
     switch (state) {
@@ -345,25 +326,6 @@
     }
   }
 
-  Future<String> _handleLifecycleMessage(String message) async {
-    handleAppLifecycleStateChanged(_parseAppLifecycleMessage(message));
-    return null;
-  }
-
-  static AppLifecycleState _parseAppLifecycleMessage(String message) {
-    switch (message) {
-      case 'AppLifecycleState.paused':
-        return AppLifecycleState.paused;
-      case 'AppLifecycleState.resumed':
-        return AppLifecycleState.resumed;
-      case 'AppLifecycleState.inactive':
-        return AppLifecycleState.inactive;
-      case 'AppLifecycleState.detached':
-        return AppLifecycleState.detached;
-    }
-    return null;
-  }
-
   /// The strategy to use when deciding whether to run a task or not.
   ///
   /// Defaults to [defaultSchedulingStrategy].
diff --git a/packages/flutter/lib/src/services/binding.dart b/packages/flutter/lib/src/services/binding.dart
index 0c4ceed..8c8a8ef 100644
--- a/packages/flutter/lib/src/services/binding.dart
+++ b/packages/flutter/lib/src/services/binding.dart
@@ -7,6 +7,7 @@
 import 'dart:ui' as ui;
 
 import 'package:flutter/foundation.dart';
+import 'package:flutter/scheduler.dart';
 
 import 'asset_bundle.dart';
 import 'binary_messenger.dart';
@@ -27,6 +28,8 @@
     window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
     initLicenses();
     SystemChannels.system.setMessageHandler(handleSystemMessage);
+    SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
+    readInitialLifecycleStateFromNativeWindow();
   }
 
   /// The current [ServicesBinding], if one has been created.
@@ -162,6 +165,48 @@
   void evict(String asset) {
     rootBundle.evict(asset);
   }
+
+  // App life cycle
+
+  /// Initializes the [lifecycleState] with the [initialLifecycleState] from the
+  /// window.
+  ///
+  /// Once the [lifecycleState] is populated through any means (including this
+  /// method), this method will do nothing. This is because the
+  /// [initialLifecycleState] may already be stale and it no longer makes sense
+  /// to use the initial state at dart vm startup as the current state anymore.
+  ///
+  /// The latest state should be obtained by subscribing to
+  /// [WidgetsBindingObserver.didChangeAppLifecycleState].
+  @protected
+  void readInitialLifecycleStateFromNativeWindow() {
+    if (lifecycleState != null) {
+      return;
+    }
+    final AppLifecycleState state = _parseAppLifecycleMessage(window.initialLifecycleState);
+    if (state != null) {
+      handleAppLifecycleStateChanged(state);
+    }
+  }
+
+  Future<String> _handleLifecycleMessage(String message) async {
+    handleAppLifecycleStateChanged(_parseAppLifecycleMessage(message));
+    return null;
+  }
+
+  static AppLifecycleState _parseAppLifecycleMessage(String message) {
+    switch (message) {
+      case 'AppLifecycleState.paused':
+        return AppLifecycleState.paused;
+      case 'AppLifecycleState.resumed':
+        return AppLifecycleState.resumed;
+      case 'AppLifecycleState.inactive':
+        return AppLifecycleState.inactive;
+      case 'AppLifecycleState.detached':
+        return AppLifecycleState.detached;
+    }
+    return null;
+  }
 }
 
 /// The default implementation of [BinaryMessenger].
diff --git a/packages/flutter/lib/src/widgets/binding.dart b/packages/flutter/lib/src/widgets/binding.dart
index a8f0183..f73504d 100644
--- a/packages/flutter/lib/src/widgets/binding.dart
+++ b/packages/flutter/lib/src/widgets/binding.dart
@@ -1166,7 +1166,7 @@
 /// A concrete binding for applications based on the Widgets framework.
 ///
 /// This is the glue that binds the framework to the Flutter engine.
-class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
+class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
 
   /// Returns an instance of the [WidgetsBinding], creating and
   /// initializing it if necessary. If one is created, it will be a
diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart
index e0221ea..e68dd6a 100644
--- a/packages/flutter/test/foundation/service_extensions_test.dart
+++ b/packages/flutter/test/foundation/service_extensions_test.dart
@@ -16,9 +16,9 @@
 import '../flutter_test_alternative.dart';
 
 class TestServiceExtensionsBinding extends BindingBase
-  with ServicesBinding,
+  with SchedulerBinding,
+       ServicesBinding,
        GestureBinding,
-       SchedulerBinding,
        PaintingBinding,
        SemanticsBinding,
        RendererBinding,
diff --git a/packages/flutter/test/painting/binding_test.dart b/packages/flutter/test/painting/binding_test.dart
index 74b5515..e0b8106 100644
--- a/packages/flutter/test/painting/binding_test.dart
+++ b/packages/flutter/test/painting/binding_test.dart
@@ -5,6 +5,7 @@
 import 'dart:ui' as ui;
 
 import 'package:flutter/foundation.dart';
+import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:flutter/widgets.dart';
@@ -85,9 +86,15 @@
 
   @override
   ui.Window get window => throw UnimplementedError();
+
+  @override
+  ui.AppLifecycleState get lifecycleState => null;
+
+  @override
+  void handleAppLifecycleStateChanged(ui.AppLifecycleState state) { }
 }
 
-class TestPaintingBinding extends TestBindingBase with ServicesBinding, PaintingBinding {
+class TestPaintingBinding extends TestBindingBase with SchedulerBinding, ServicesBinding, PaintingBinding {
 
   @override
   final FakeImageCache imageCache = FakeImageCache();
diff --git a/packages/flutter/test/painting/painting_utils.dart b/packages/flutter/test/painting/painting_utils.dart
index 9968bad..abcb717 100644
--- a/packages/flutter/test/painting/painting_utils.dart
+++ b/packages/flutter/test/painting/painting_utils.dart
@@ -7,9 +7,10 @@
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/painting.dart';
+import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
 
-class PaintingBindingSpy extends BindingBase with ServicesBinding, PaintingBinding {
+class PaintingBindingSpy extends BindingBase with SchedulerBinding, ServicesBinding, PaintingBinding {
   int counter = 0;
   int get instantiateImageCodecCalledCount => counter;
 
diff --git a/packages/flutter/test/rendering/mouse_tracking_test.dart b/packages/flutter/test/rendering/mouse_tracking_test.dart
index 95753d1..89d0b05 100644
--- a/packages/flutter/test/rendering/mouse_tracking_test.dart
+++ b/packages/flutter/test/rendering/mouse_tracking_test.dart
@@ -17,7 +17,7 @@
 typedef HandleEventCallback = void Function(PointerEvent event);
 
 class _TestGestureFlutterBinding extends BindingBase
-    with ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, RendererBinding {
+    with SchedulerBinding, ServicesBinding, GestureBinding, SemanticsBinding, RendererBinding {
   @override
   void initInstances() {
     super.initInstances();
diff --git a/packages/flutter/test/rendering/rendering_tester.dart b/packages/flutter/test/rendering/rendering_tester.dart
index dd94dfb..289c1b2 100644
--- a/packages/flutter/test/rendering/rendering_tester.dart
+++ b/packages/flutter/test/rendering/rendering_tester.dart
@@ -12,7 +12,7 @@
 export 'package:flutter/foundation.dart' show FlutterError, FlutterErrorDetails;
 export 'package:flutter_test/flutter_test.dart' show EnginePhase;
 
-class TestRenderingFlutterBinding extends BindingBase with ServicesBinding, GestureBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding {
+class TestRenderingFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding {
   /// Creates a binding for testing rendering library functionality.
   ///
   /// If [onErrors] is not null, it is called if [FlutterError] caught any errors
diff --git a/packages/flutter/test/scheduler/animation_test.dart b/packages/flutter/test/scheduler/animation_test.dart
index 1518e8b..441f888 100644
--- a/packages/flutter/test/scheduler/animation_test.dart
+++ b/packages/flutter/test/scheduler/animation_test.dart
@@ -10,7 +10,7 @@
 
 import 'scheduler_tester.dart';
 
-class TestSchedulerBinding extends BindingBase with ServicesBinding, SchedulerBinding { }
+class TestSchedulerBinding extends BindingBase with SchedulerBinding, ServicesBinding { }
 
 void main() {
   final SchedulerBinding scheduler = TestSchedulerBinding();
diff --git a/packages/flutter/test/scheduler/scheduler_test.dart b/packages/flutter/test/scheduler/scheduler_test.dart
index f7a4f19..729590f 100644
--- a/packages/flutter/test/scheduler/scheduler_test.dart
+++ b/packages/flutter/test/scheduler/scheduler_test.dart
@@ -12,7 +12,7 @@
 import '../flutter_test_alternative.dart';
 import 'scheduler_tester.dart';
 
-class TestSchedulerBinding extends BindingBase with ServicesBinding, SchedulerBinding {
+class TestSchedulerBinding extends BindingBase with SchedulerBinding, ServicesBinding {
   final Map<String, List<Map<String, dynamic>>> eventsDispatched = <String, List<Map<String, dynamic>>>{};
 
   @override
diff --git a/packages/flutter/test/services/channel_buffers_test.dart b/packages/flutter/test/services/channel_buffers_test.dart
index 4d2358a..b0e00b2 100644
--- a/packages/flutter/test/services/channel_buffers_test.dart
+++ b/packages/flutter/test/services/channel_buffers_test.dart
@@ -9,10 +9,11 @@
 import 'dart:typed_data';
 import 'dart:ui' as ui;
 import 'package:flutter/foundation.dart';
+import 'package:flutter/scheduler.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 
-class TestChannelBuffersFlutterBinding extends BindingBase with ServicesBinding {
+class TestChannelBuffersFlutterBinding extends BindingBase with SchedulerBinding, ServicesBinding {
 }
 
 void main() {
diff --git a/packages/flutter/test/scheduler/lifecycle_test.dart b/packages/flutter/test/services/lifecycle_test.dart
similarity index 81%
rename from packages/flutter/test/scheduler/lifecycle_test.dart
rename to packages/flutter/test/services/lifecycle_test.dart
index f5d5094..a09b982 100644
--- a/packages/flutter/test/scheduler/lifecycle_test.dart
+++ b/packages/flutter/test/services/lifecycle_test.dart
@@ -3,13 +3,13 @@
 // found in the LICENSE file.
 
 import 'package:flutter_test/flutter_test.dart';
-import 'package:flutter/scheduler.dart';
+import 'package:flutter/services.dart';
 
 void main() {
   testWidgets('initialLifecycleState is used to init state paused', (WidgetTester tester) async {
     // The lifecycleState is null initially in tests as there is no
     // initialLifecycleState.
-    expect(SchedulerBinding.instance.lifecycleState, equals(null));
+    expect(ServicesBinding.instance.lifecycleState, equals(null));
     // Mock the Window to provide paused as the AppLifecycleState
     final TestWidgetsFlutterBinding binding = tester.binding;
     // Use paused as the initial state.
@@ -18,6 +18,6 @@
 
     // The lifecycleState should now be the state we passed above,
     // even though no lifecycle event was fired from the platform.
-    expect(SchedulerBinding.instance.lifecycleState.toString(), equals('AppLifecycleState.paused'));
+    expect(ServicesBinding.instance.lifecycleState.toString(), equals('AppLifecycleState.paused'));
   });
 }
diff --git a/packages/flutter_driver/lib/src/extension/extension.dart b/packages/flutter_driver/lib/src/extension/extension.dart
index 6fefc2e..c7bbdcf 100644
--- a/packages/flutter_driver/lib/src/extension/extension.dart
+++ b/packages/flutter_driver/lib/src/extension/extension.dart
@@ -42,7 +42,7 @@
 /// eventually completes to a string response.
 typedef DataHandler = Future<String> Function(String message);
 
-class _DriverBinding extends BindingBase with ServicesBinding, SchedulerBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
+class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
   _DriverBinding(this._handler, this._silenceErrors);
 
   final DataHandler _handler;
diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
index 7bf83aa..cfabbcb 100644
--- a/packages/flutter_test/lib/src/binding.dart
+++ b/packages/flutter_test/lib/src/binding.dart
@@ -155,8 +155,8 @@
 /// `HttpClient` to the code making the call, so that it can appropriately mock
 /// or fake responses.
 abstract class TestWidgetsFlutterBinding extends BindingBase
-  with ServicesBinding,
-       SchedulerBinding,
+  with SchedulerBinding,
+       ServicesBinding,
        GestureBinding,
        SemanticsBinding,
        RendererBinding,