// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'dart:ui';
/// @docImport 'package:flutter/animation.dart';
/// @docImport 'package:flutter/material.dart';
/// @docImport 'package:flutter_test/flutter_test.dart';
///
/// @docImport 'adapter.dart';
/// @docImport 'app_lifecycle_listener.dart';
/// @docImport 'basic.dart';
/// @docImport 'focus_scope.dart';
/// @docImport 'media_query.dart';
/// @docImport 'navigator.dart';
/// @docImport 'pop_scope.dart';
library;

import 'dart:async';
import 'dart:developer' as developer;
import 'dart:ui'
    show
        AccessibilityFeatures,
        AppExitResponse,
        AppLifecycleState,
        FrameTiming,
        Locale,
        PlatformDispatcher,
        TimingsCallback,
        ViewFocusEvent;

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';

import '../foundation/_features.dart';
import '_accessibility_evaluations.dart';
import '_window.dart';
import 'app.dart';
import 'debug.dart';
import 'focus_manager.dart';
import 'framework.dart';
import 'platform_menu_bar.dart';
import 'router.dart';
import 'service_extensions.dart';
import 'view.dart';
import 'widget_inspector.dart';

export 'dart:ui' show AppLifecycleState, Locale;

// Examples can assume:
// late FlutterView myFlutterView;
// class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) => const Placeholder(); }

/// Interface for classes that register with the Widgets layer binding.
///
/// This can be used by any class, not just widgets. It provides an interface
/// which is used by [WidgetsBinding.addObserver] and
/// [WidgetsBinding.removeObserver] to notify objects of changes in the
/// environment, such as changes to the device metrics or accessibility
/// settings. It is used to implement features such as [MediaQuery].
///
/// This class can be extended directly, or mixed in, to get default behaviors
/// for all of the handlers. Alternatively it can be used with the
/// `implements` keyword, in which case all the handlers must be implemented
/// (and the analyzer will list those that have been omitted).
///
/// To start receiving notifications, call `WidgetsBinding.instance.addObserver`
/// with a reference to the object implementing the [WidgetsBindingObserver]
/// interface. To avoid memory leaks, call
/// `WidgetsBinding.instance.removeObserver` to unregister the object when it
/// reaches the end of its lifecycle.
///
/// {@tool dartpad}
/// This sample shows how to implement parts of the [State] and
/// [WidgetsBindingObserver] protocols necessary to react to application
/// lifecycle messages. See [didChangeAppLifecycleState].
///
/// To respond to other notifications, replace the [didChangeAppLifecycleState]
/// method in this example with other methods from this class.
///
/// ** See code in examples/api/lib/widgets/binding/widget_binding_observer.0.dart **
/// {@end-tool}
abstract mixin class WidgetsBindingObserver {
  /// Called when the system tells the app to pop the current route, such as
  /// after a system back button press or back gesture.
  ///
  /// Observers are notified in registration order until one returns
  /// true. If none return true, the application quits.
  ///
  /// Observers are expected to return true if they were able to
  /// handle the notification, for example by closing an active dialog
  /// box, and false otherwise. The [WidgetsApp] widget uses this
  /// mechanism to notify the [Navigator] widget that it should pop
  /// its current route if possible.
  ///
  /// This method exposes the `popRoute` notification from
  /// [SystemChannels.navigation].
  ///
  /// {@macro flutter.widgets.AndroidPredictiveBack}
  Future<bool> didPopRoute() => Future<bool>.value(false);

  /// Called at the start of a predictive back gesture.
  ///
  /// Observers are notified in registration order until one returns true or all
  /// observers have been notified. If an observer returns true then that
  /// observer, and only that observer, will be notified of subsequent events in
  /// this same gesture (for example [handleUpdateBackGestureProgress], etc.).
  ///
  /// Observers are expected to return true if they were able to handle the
  /// notification, for example by starting a predictive back animation, and
  /// false otherwise. [PredictiveBackPageTransitionsBuilder] uses this
  /// mechanism to listen for predictive back gestures.
  ///
  /// If all observers indicate they are not handling this back gesture by
  /// returning false, then a navigation pop will result when
  /// [handleCommitBackGesture] is called, as in a non-predictive system back
  /// gesture.
  ///
  /// Currently, this is only used on Android devices that support the
  /// predictive back feature.
  bool handleStartBackGesture(PredictiveBackEvent backEvent) => false;

  /// Called when a predictive back gesture moves.
  ///
  /// The observer which was notified of this gesture's [handleStartBackGesture]
  /// is the same observer notified for this.
  ///
  /// Currently, this is only used on Android devices that support the
  /// predictive back feature.
  void handleUpdateBackGestureProgress(PredictiveBackEvent backEvent) {}

  /// Called when a predictive back gesture is finished successfully, indicating
  /// that the current route should be popped.
  ///
  /// The observer which was notified of this gesture's [handleStartBackGesture]
  /// is the same observer notified for this. If there is none, then a
  /// navigation pop will result, as in a non-predictive system back gesture.
  ///
  /// Currently, this is only used on Android devices that support the
  /// predictive back feature.
  void handleCommitBackGesture() {}

  /// Called when a predictive back gesture is canceled, indicating that no
  /// navigation should occur.
  ///
  /// The observer which was notified of this gesture's [handleStartBackGesture]
  /// is the same observer notified for this.
  ///
  /// Currently, this is only used on Android devices that support the
  /// predictive back feature.
  void handleCancelBackGesture() {}

  /// Called when the user taps the status bar on iOS, to scroll a scroll
  /// view to the top.
  ///
  /// This event should usually only be handled by at most one scroll view, so
  /// implementer(s) of this callback must coordinate to determine the most
  /// suitable scroll view for handling this event.
  ///
  /// This callback is only called on iOS. The default implementation provided by
  /// [WidgetsBindingObserver] does nothing.
  ///
  /// See also:
  ///
  ///  * [Scaffold] and [CupertinoPageScaffold] which use this callback to implement
  ///    iOS scroll-to-top.
  void handleStatusBarTap() {}

  /// Called when the host tells the application to push a new route onto the
  /// navigator.
  ///
  /// Observers are expected to return true if they were able to
  /// handle the notification. Observers are notified in registration
  /// order until one returns true.
  ///
  /// This method exposes the `pushRoute` notification from
  /// [SystemChannels.navigation].
  @Deprecated(
    'Use didPushRouteInformation instead. '
    'This feature was deprecated after v3.8.0-14.0.pre.',
  )
  Future<bool> didPushRoute(String route) => Future<bool>.value(false);

  /// Called when the host tells the application to push a new
  /// [RouteInformation] and a restoration state onto the router.
  ///
  /// Observers are expected to return true if they were able to
  /// handle the notification. Observers are notified in registration
  /// order until one returns true.
  ///
  /// This method exposes the `pushRouteInformation` notification from
  /// [SystemChannels.navigation].
  ///
  /// The default implementation is to call the [didPushRoute] directly with the
  /// string constructed from [RouteInformation.uri]'s path and query parameters.
  // TODO(chunhtai): remove the default implementation once `didPushRoute` is
  // removed.
  Future<bool> didPushRouteInformation(RouteInformation routeInformation) {
    final Uri uri = routeInformation.uri;
    return didPushRoute(
      Uri.decodeComponent(
        Uri(
          path: uri.path.isEmpty ? '/' : uri.path,
          queryParameters: uri.queryParametersAll.isEmpty ? null : uri.queryParametersAll,
          fragment: uri.fragment.isEmpty ? null : uri.fragment,
        ).toString(),
      ),
    );
  }

  /// Called when the application's dimensions change. For example,
  /// when a phone is rotated.
  ///
  /// This method exposes notifications from
  /// [dart:ui.PlatformDispatcher.onMetricsChanged].
  ///
  /// {@tool snippet}
  ///
  /// This [StatefulWidget] implements the parts of the [State] and
  /// [WidgetsBindingObserver] protocols necessary to react when the device is
  /// rotated (or otherwise changes dimensions).
  ///
  /// ```dart
  /// class MetricsReactor extends StatefulWidget {
  ///   const MetricsReactor({ super.key });
  ///
  ///   @override
  ///   State<MetricsReactor> createState() => _MetricsReactorState();
  /// }
  ///
  /// class _MetricsReactorState extends State<MetricsReactor> with WidgetsBindingObserver {
  ///   late Size _lastSize;
  ///
  ///   @override
  ///   void initState() {
  ///     super.initState();
  ///     WidgetsBinding.instance.addObserver(this);
  ///   }
  ///
  ///   @override
  ///   void didChangeDependencies() {
  ///     super.didChangeDependencies();
  ///     // [View.of] exposes the view from `WidgetsBinding.instance.platformDispatcher.views`
  ///     // into which this widget is drawn.
  ///     _lastSize = View.of(context).physicalSize;
  ///   }
  ///
  ///   @override
  ///   void dispose() {
  ///     WidgetsBinding.instance.removeObserver(this);
  ///     super.dispose();
  ///   }
  ///
  ///   @override
  ///   void didChangeMetrics() {
  ///     setState(() { _lastSize = View.of(context).physicalSize; });
  ///   }
  ///
  ///   @override
  ///   Widget build(BuildContext context) {
  ///     return Text('Current size: $_lastSize');
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// In general, this is unnecessary as the layout system takes care of
  /// automatically recomputing the application geometry when the application
  /// size changes.
  ///
  /// See also:
  ///
  ///  * [MediaQuery.sizeOf], which provides a similar service with less
  ///    boilerplate.
  void didChangeMetrics() {}

  /// Called when the platform's text scale factor changes.
  ///
  /// This typically happens as the result of the user changing system
  /// preferences, and it should affect all of the text sizes in the
  /// application.
  ///
  /// This method exposes notifications from
  /// [dart:ui.PlatformDispatcher.onTextScaleFactorChanged].
  ///
  /// {@tool snippet}
  ///
  /// ```dart
  /// class TextScaleFactorReactor extends StatefulWidget {
  ///   const TextScaleFactorReactor({super.key});
  ///
  ///   @override
  ///   State<TextScaleFactorReactor> createState() => _TextScaleFactorReactorState();
  /// }
  ///
  /// class _TextScaleFactorReactorState extends State<TextScaleFactorReactor>
  ///     with WidgetsBindingObserver {
  ///   double _lastTextScaleFactor =
  ///       WidgetsBinding.instance.platformDispatcher.textScaleFactor;
  ///
  ///   @override
  ///   void initState() {
  ///     super.initState();
  ///     WidgetsBinding.instance.addObserver(this);
  ///   }
  ///
  ///   @override
  ///   void dispose() {
  ///     WidgetsBinding.instance.removeObserver(this);
  ///     super.dispose();
  ///   }
  ///
  ///   @override
  ///   void didChangeTextScaleFactor() {
  ///     setState(() {
  ///       _lastTextScaleFactor =
  ///           WidgetsBinding.instance.platformDispatcher.textScaleFactor;
  ///     });
  ///   }
  ///
  ///   @override
  ///   Widget build(BuildContext context) {
  ///     return Text('Current scale factor: $_lastTextScaleFactor');
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  ///
  /// See also:
  ///
  ///  * [MediaQuery.textScaleFactorOf], which provides a similar service with less
  ///    boilerplate.
  void didChangeTextScaleFactor() {}

  /// Called when the platform brightness changes.
  ///
  /// This method exposes notifications from
  /// [dart:ui.PlatformDispatcher.onPlatformBrightnessChanged].
  ///
  /// See also:
  ///
  /// * [MediaQuery.platformBrightnessOf], which provides a similar service with
  ///   less boilerplate.
  void didChangePlatformBrightness() {}

  /// Called when the system tells the app that the user's locale has
  /// changed. For example, if the user changes the system language
  /// settings.
  ///
  /// This method exposes notifications from
  /// [dart:ui.PlatformDispatcher.onLocaleChanged].
  void didChangeLocales(List<Locale>? locales) {}

  /// Called when the system puts the app in the background or returns
  /// the app to the foreground.
  ///
  /// An example of implementing this method is provided in the class-level
  /// documentation for the [WidgetsBindingObserver] class.
  ///
  /// This method exposes notifications from [SystemChannels.lifecycle].
  ///
  /// See also:
  ///
  ///  * [AppLifecycleListener], an alternative API for responding to
  ///    application lifecycle changes.
  void didChangeAppLifecycleState(AppLifecycleState state) {}

  /// Called whenever the [PlatformDispatcher] receives a notification that the
  /// focus state on a view has changed.
  ///
  /// The [event] contains the view ID for the view that changed its focus
  /// state.
  ///
  /// The view ID of the [FlutterView] in which a particular [BuildContext]
  /// resides can be retrieved with `View.of(context).viewId`, so that it may be
  /// compared with the view ID in the `event` to see if the event pertains to
  /// the given context.
  void didChangeViewFocus(ViewFocusEvent event) {}

  /// Called when a request is received from the system to exit the application.
  ///
  /// If any observer responds with [AppExitResponse.cancel], it will cancel the
  /// exit. All observers will be asked before exiting.
  ///
  /// {@macro flutter.services.binding.ServicesBinding.requestAppExit}
  ///
  /// See also:
  ///
  /// * [ServicesBinding.exitApplication] for a function to call that will request
  ///   that the application exits.
  Future<AppExitResponse> didRequestAppExit() async {
    return AppExitResponse.exit;
  }

  /// Called when the system is running low on memory.
  ///
  /// This method exposes the `memoryPressure` notification from
  /// [SystemChannels.system].
  void didHaveMemoryPressure() {}

  /// Called when the system changes the set of currently active accessibility
  /// features.
  ///
  /// This method exposes notifications from
  /// [dart:ui.PlatformDispatcher.onAccessibilityFeaturesChanged].
  void didChangeAccessibilityFeatures() {}
}

/// The glue between the widgets layer and the Flutter engine.
///
/// The [WidgetsBinding] manages a single [Element] tree rooted at [rootElement].
/// Calling [runApp] (which indirectly calls [attachRootWidget]) bootstraps that
/// element tree.
///
/// ## Relationship to render trees
///
/// Multiple render trees may be associated with the element tree. Those are
/// managed by the underlying [RendererBinding].
///
/// The element tree is segmented into two types of zones: rendering zones and
/// non-rendering zones.
///
/// A rendering zone is a part of the element tree that is backed by a render
/// tree and it describes the pixels that are drawn on screen. For elements in
/// this zone, [Element.renderObject] never returns null because the elements
/// are all associated with [RenderObject]s. Almost all widgets can be placed in
/// a rendering zone; notable exceptions are the [View] widget, [ViewCollection]
/// widget, and [RootWidget].
///
/// A non-rendering zone is a part of the element tree that is not backed by a
/// render tree. For elements in this zone, [Element.renderObject] returns null
/// because the elements are not associated with any [RenderObject]s. Only
/// widgets that do not produce a [RenderObject] can be used in this zone
/// because there is no render tree to attach the render object to. In other
/// words, [RenderObjectWidget]s cannot be used in this zone. Typically, one
/// would find [InheritedWidget]s, [View]s, and [ViewCollection]s in this zone
/// to inject data across rendering zones into the tree and to organize the
/// rendering zones (and by extension their associated render trees) into a
/// unified element tree.
///
/// The root of the element tree at [rootElement] starts a non-rendering zone.
/// Within a non-rendering zone, the [View] widget is used to start a rendering
/// zone by bootstrapping a render tree. Within a rendering zone, the
/// [ViewAnchor] can be used to start a new non-rendering zone.
///
// TODO(goderbauer): Include an example graph showcasing the different zones.
///
/// To figure out if an element is in a rendering zone it may walk up the tree
/// calling [Element.debugExpectsRenderObjectForSlot] on its ancestors. If it
/// reaches an element that returns false, it is in a non-rendering zone. If it
/// reaches a [RenderObjectElement] ancestor it is in a rendering zone.
mixin WidgetsBinding
    on
        BindingBase,
        ServicesBinding,
        SchedulerBinding,
        GestureBinding,
        RendererBinding,
        SemanticsBinding {
  @override
  void initInstances() {
    super.initInstances();
    _instance = this;

    assert(() {
      _debugAddStackFilters();
      return true;
    }());

    // Initialization of [_buildOwner] has to be done after
    // [super.initInstances] is called, as it requires [ServicesBinding] to
    // properly setup the [defaultBinaryMessenger] instance.
    _buildOwner = BuildOwner();
    buildOwner!.onBuildScheduled = _handleBuildScheduled;
    platformDispatcher.onLocaleChanged = handleLocaleChanged;
    SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
    SystemChannels.backGesture.setMethodCallHandler(_handleBackGestureInvocation);
    SystemChannels.statusBar.setMethodCallHandler(_handleStatusBarActions);
    assert(() {
      FlutterErrorDetails.propertiesTransformers.add(debugTransformDebugCreator);
      return true;
    }());
    platformMenuDelegate = DefaultPlatformMenuDelegate();
    _windowingOwner = createDefaultWindowingOwner();
  }

  /// The current [WidgetsBinding], if one has been created.
  ///
  /// Provides access to the features exposed by this mixin. The binding must
  /// be initialized before using this getter; this is typically done by calling
  /// [runApp] or [WidgetsFlutterBinding.ensureInitialized].
  static WidgetsBinding get instance => BindingBase.checkInstance(_instance);
  static WidgetsBinding? _instance;

  /// If true, forces the widget inspector to be visible.
  ///
  /// Overrides the `debugShowWidgetInspector` value set in [WidgetsApp].
  ///
  /// Used by the `debugShowWidgetInspector` debugging extension.
  ///
  /// The inspector allows the selection of a location on your device or emulator
  /// and view what widgets and render objects associated with it. An outline of
  /// the selected widget and some summary information is shown on device and
  /// more detailed information is shown in the IDE or DevTools.
  bool get debugShowWidgetInspectorOverride {
    return debugShowWidgetInspectorOverrideNotifier.value;
  }

  set debugShowWidgetInspectorOverride(bool value) {
    debugShowWidgetInspectorOverrideNotifier.value = value;
  }

  /// Notifier for [debugShowWidgetInspectorOverride].
  ValueNotifier<bool> get debugShowWidgetInspectorOverrideNotifier =>
      _debugShowWidgetInspectorOverrideNotifierObject ??= ValueNotifier<bool>(false);
  ValueNotifier<bool>? _debugShowWidgetInspectorOverrideNotifierObject;

  /// The notifier for whether or not taps on the device are treated as widget
  /// selections when the widget inspector is enabled.
  ///
  /// - If true, taps in the app are intercepted by the widget inspector.
  /// - If false, taps in the app are not intercepted by the widget inspector.
  ValueNotifier<bool> get debugWidgetInspectorSelectionOnTapEnabled =>
      _debugWidgetInspectorSelectionOnTapEnabledNotifierObject ??= ValueNotifier<bool>(true);
  ValueNotifier<bool>? _debugWidgetInspectorSelectionOnTapEnabledNotifierObject;

  /// If true, [WidgetInspector] will not be automatically injected into the
  /// widget tree.
  ///
  /// This overrides the behavior where [WidgetInspector] is added to the
  /// widget tree created by [WidgetsApp] when the `debugShowWidgetInspector`
  /// value is set in [WidgetsApp] or [debugShowWidgetInspectorOverride] is set
  /// to true.
  ///
  /// Used by tools that want more control over which widgets can be selected
  /// and highlighted by the widget inspector by manually injecting instances of
  /// [WidgetInspector].
  bool get debugExcludeRootWidgetInspector => _debugExcludeRootWidgetInspector;

  set debugExcludeRootWidgetInspector(bool value) {
    _debugExcludeRootWidgetInspector = value;
  }

  bool _debugExcludeRootWidgetInspector = false;

  @visibleForTesting
  @override
  void resetInternalState() {
    // ignore: invalid_use_of_visible_for_testing_member, https://github.com/dart-lang/sdk/issues/41998
    super.resetInternalState();
    _debugShowWidgetInspectorOverrideNotifierObject?.dispose();
    _debugShowWidgetInspectorOverrideNotifierObject = null;
    _debugWidgetInspectorSelectionOnTapEnabledNotifierObject?.dispose();
    _debugWidgetInspectorSelectionOnTapEnabledNotifierObject = null;
  }

  void _debugAddStackFilters() {
    const elementInflateWidget = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'Element',
      method: 'inflateWidget',
    );
    const elementUpdateChild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'Element',
      method: 'updateChild',
    );
    const elementRebuild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'Element',
      method: 'rebuild',
    );
    const componentElementPerformRebuild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'ComponentElement',
      method: 'performRebuild',
    );
    const componentElementFirstBuild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'ComponentElement',
      method: '_firstBuild',
    );
    const componentElementMount = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'ComponentElement',
      method: 'mount',
    );
    const statefulElementFirstBuild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'StatefulElement',
      method: '_firstBuild',
    );
    const singleChildMount = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'SingleChildRenderObjectElement',
      method: 'mount',
    );
    const statefulElementRebuild = PartialStackFrame(
      package: 'package:flutter/src/widgets/framework.dart',
      className: 'StatefulElement',
      method: 'performRebuild',
    );

    const replacementString = '...     Normal element mounting';

    // ComponentElement variations
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[
          elementInflateWidget,
          elementUpdateChild,
          componentElementPerformRebuild,
          elementRebuild,
          componentElementFirstBuild,
          componentElementMount,
        ],
        replacement: replacementString,
      ),
    );
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[
          elementUpdateChild,
          componentElementPerformRebuild,
          elementRebuild,
          componentElementFirstBuild,
          componentElementMount,
        ],
        replacement: replacementString,
      ),
    );

    // StatefulElement variations
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[
          elementInflateWidget,
          elementUpdateChild,
          componentElementPerformRebuild,
          statefulElementRebuild,
          elementRebuild,
          componentElementFirstBuild,
          statefulElementFirstBuild,
          componentElementMount,
        ],
        replacement: replacementString,
      ),
    );
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[
          elementUpdateChild,
          componentElementPerformRebuild,
          statefulElementRebuild,
          elementRebuild,
          componentElementFirstBuild,
          statefulElementFirstBuild,
          componentElementMount,
        ],
        replacement: replacementString,
      ),
    );

    // SingleChildRenderObjectElement variations
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[elementInflateWidget, elementUpdateChild, singleChildMount],
        replacement: replacementString,
      ),
    );
    FlutterError.addDefaultStackFilter(
      const RepetitiveStackFrameFilter(
        frames: <PartialStackFrame>[elementUpdateChild, singleChildMount],
        replacement: replacementString,
      ),
    );
  }

  @override
  void initServiceExtensions() {
    super.initServiceExtensions();

    if (!kReleaseMode) {
      registerServiceExtension(
        name: WidgetsServiceExtensions.debugDumpApp.name,
        callback: (Map<String, String> parameters) async {
          final String data = _debugDumpAppString();
          return <String, Object>{'data': data};
        },
      );

      registerServiceExtension(
        name: WidgetsServiceExtensions.debugDumpFocusTree.name,
        callback: (Map<String, String> parameters) async {
          final String data = focusManager.toStringDeep();
          return <String, Object>{'data': data};
        },
      );

      if (!kIsWeb) {
        registerBoolServiceExtension(
          name: WidgetsServiceExtensions.showPerformanceOverlay.name,
          getter: () => Future<bool>.value(WidgetsApp.showPerformanceOverlayOverride),
          setter: (bool value) {
            if (WidgetsApp.showPerformanceOverlayOverride == value) {
              return Future<void>.value();
            }
            WidgetsApp.showPerformanceOverlayOverride = value;
            return _forceRebuild();
          },
        );
      }

      registerServiceExtension(
        name: WidgetsServiceExtensions.didSendFirstFrameEvent.name,
        callback: (_) async {
          return <String, dynamic>{
            // This is defined to return a STRING, not a boolean.
            // Devtools, the Intellij plugin, and the flutter tool all depend
            // on it returning a string and not a boolean.
            'enabled': _needToReportFirstFrame ? 'false' : 'true',
          };
        },
      );

      registerServiceExtension(
        name: WidgetsServiceExtensions.didSendFirstFrameRasterizedEvent.name,
        callback: (_) async {
          return <String, dynamic>{
            // This is defined to return a STRING, not a boolean.
            // Devtools, the Intellij plugin, and the flutter tool all depend
            // on it returning a string and not a boolean.
            'enabled': firstFrameRasterized ? 'true' : 'false',
          };
        },
      );

      // Expose the ability to send Widget rebuilds as [Timeline] events.
      registerBoolServiceExtension(
        name: WidgetsServiceExtensions.profileWidgetBuilds.name,
        getter: () async => debugProfileBuildsEnabled,
        setter: (bool value) async {
          debugProfileBuildsEnabled = value;
        },
      );
      registerBoolServiceExtension(
        name: WidgetsServiceExtensions.profileUserWidgetBuilds.name,
        getter: () async => debugProfileBuildsEnabledUserWidgets,
        setter: (bool value) async {
          debugProfileBuildsEnabledUserWidgets = value;
        },
      );

      registerServiceExtension(
        name: WidgetsServiceExtensions.accessibilityEvaluations.name,
        callback: (Map<String, String> parameters) async {
          final String? type = parameters['type'];
          if (type == null) {
            throw Exception('type parameter is required');
          }

          switch (type) {
            case 'MinimumTextContrastEvaluation':
              if (parameters case {
                'minNormalTextContrastRatio': final String minNormalTextContrastRatio,
                'minLargeTextContrastRatio': final String minLargeTextContrastRatio,
              }) {
                final EvaluationResult result = await MinimumTextContrastEvaluation(
                  minNormalTextContrastRatio: double.parse(minNormalTextContrastRatio),
                  minLargeTextContrastRatio: double.parse(minLargeTextContrastRatio),
                ).evaluate(this);
                return _formatEvaluationResult(result.violations);
              }
              throw Exception('Invalid arguments');
            case 'MinimumTapTargetEvaluation':
              if (parameters case {'targetSize': final String targetSize}) {
                final EvaluationResult result = await MinimumTapTargetEvaluation(
                  size: Size.square(double.parse(targetSize)),
                ).evaluate(this);
                return _formatEvaluationResult(result.violations);
              }
              throw Exception('Invalid arguments');
            case 'LabeledTapTargetEvaluation':
              final EvaluationResult result = await const LabeledTapTargetEvaluation().evaluate(
                this,
              );
              return _formatEvaluationResult(result.violations);
            default:
              throw Exception('unknown type: $type');
          }
        },
      );
    }

    assert(() {
      registerBoolServiceExtension(
        name: WidgetsServiceExtensions.debugAllowBanner.name,
        getter: () => Future<bool>.value(WidgetsApp.debugAllowBannerOverride),
        setter: (bool value) {
          if (WidgetsApp.debugAllowBannerOverride == value) {
            return Future<void>.value();
          }
          WidgetsApp.debugAllowBannerOverride = value;
          return _forceRebuild();
        },
      );

      WidgetInspectorService.instance.initServiceExtensions(registerServiceExtension);

      return true;
    }());
  }

  Map<String, List<Map<String, String>>> _formatEvaluationResult(List<Violation> violations) {
    return <String, List<Map<String, String>>>{
      'result': violations.map((Violation violation) {
        return <String, String>{
          'nodeId': violation.node.id.toString(),
          'message': violation.reason,
        };
      }).toList(),
    };
  }

  Future<void> _forceRebuild() {
    if (rootElement != null) {
      buildOwner!.reassemble(rootElement!);
      return endOfFrame;
    }
    return Future<void>.value();
  }

  /// The [BuildOwner] in charge of executing the build pipeline for the
  /// widget tree rooted at this binding.
  BuildOwner? get buildOwner => _buildOwner;
  // Initialization of [_buildOwner] has to be done within the [initInstances]
  // method, as it requires [ServicesBinding] to properly setup the
  // [defaultBinaryMessenger] instance.
  BuildOwner? _buildOwner;

  /// The object in charge of the focus tree.
  ///
  /// Rarely used directly. Instead, consider using [FocusScope.of] to obtain
  /// the [FocusScopeNode] for a given [BuildContext].
  ///
  /// See [FocusManager] for more details.
  FocusManager get focusManager => _buildOwner!.focusManager;

  /// A delegate that communicates with a platform plugin for serializing and
  /// managing platform-rendered menu bars created by [PlatformMenuBar].
  ///
  /// This is set by default to a [DefaultPlatformMenuDelegate] instance in
  /// [initInstances].
  late PlatformMenuDelegate platformMenuDelegate;

  final List<WidgetsBindingObserver> _observers = <WidgetsBindingObserver>[];

  /// Registers the given object as a binding observer. Binding
  /// observers are notified when various application events occur,
  /// for example when the system locale changes. Generally, one
  /// widget in the widget tree registers itself as a binding
  /// observer, and converts the system state into inherited widgets.
  ///
  /// For example, the [WidgetsApp] widget registers as a binding
  /// observer and passes the screen size to a [MediaQuery] widget
  /// each time it is built, which enables other widgets to use the
  /// [MediaQuery.sizeOf] static method and (implicitly) the
  /// [InheritedWidget] mechanism to be notified whenever the screen
  /// size changes (e.g. whenever the screen rotates).
  ///
  /// See also:
  ///
  ///  * [removeObserver], to release the resources reserved by this method.
  ///  * [WidgetsBindingObserver], which has an example of using this method.
  void addObserver(WidgetsBindingObserver observer) => _observers.add(observer);

  /// Unregisters the given observer. This should be used sparingly as
  /// it is relatively expensive (O(N) in the number of registered
  /// observers).
  ///
  /// See also:
  ///
  ///  * [addObserver], for the method that adds observers in the first place.
  ///  * [WidgetsBindingObserver], which has an example of using this method.
  bool removeObserver(WidgetsBindingObserver observer) {
    _backGestureObservers.remove(observer);

    return _observers.remove(observer);
  }

  @override
  Future<AppExitResponse> handleRequestAppExit() async {
    var didCancel = false;
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        if ((await observer.didRequestAppExit()) == AppExitResponse.cancel) {
          didCancel = true;
          // Don't early return. For the case where someone is just using the
          // observer to know when exit happens, we want to call all the
          // observers, even if we already know we're going to cancel.
        }
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didRequestAppExit',
            ),
          ),
        );
      }
    }
    return didCancel ? AppExitResponse.cancel : AppExitResponse.exit;
  }

  @override
  void handleMetricsChanged() {
    super.handleMetricsChanged();
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeMetrics();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeMetrics',
            ),
          ),
        );
      }
    }
  }

  @override
  void handleTextScaleFactorChanged() {
    super.handleTextScaleFactorChanged();
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeTextScaleFactor();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeTextScaleFactor',
            ),
          ),
        );
      }
    }
  }

  @override
  void handlePlatformBrightnessChanged() {
    super.handlePlatformBrightnessChanged();
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangePlatformBrightness();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangePlatformBrightness',
            ),
          ),
        );
      }
    }
  }

  @override
  void handleAccessibilityFeaturesChanged() {
    super.handleAccessibilityFeaturesChanged();
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeAccessibilityFeatures();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeAccessibilityFeatures',
            ),
          ),
        );
      }
    }
  }

  /// Called when the system locale changes.
  ///
  /// Calls [dispatchLocalesChanged] to notify the binding observers.
  ///
  /// See [dart:ui.PlatformDispatcher.onLocaleChanged].
  @protected
  @mustCallSuper
  @visibleForTesting
  void handleLocaleChanged() {
    dispatchLocalesChanged(platformDispatcher.locales);
  }

  /// Notify all the observers that the locale has changed (using
  /// [WidgetsBindingObserver.didChangeLocales]), giving them the
  /// `locales` argument.
  ///
  /// This is called by [handleLocaleChanged] when the
  /// [PlatformDispatcher.onLocaleChanged] notification is received.
  @protected
  @mustCallSuper
  void dispatchLocalesChanged(List<Locale>? locales) {
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeLocales(locales);
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeLocales',
            ),
          ),
        );
      }
    }
  }

  /// Notify all the observers that the active set of [AccessibilityFeatures]
  /// has changed (using [WidgetsBindingObserver.didChangeAccessibilityFeatures]),
  /// giving them the `features` argument.
  ///
  /// This is called by [handleAccessibilityFeaturesChanged] when the
  /// [PlatformDispatcher.onAccessibilityFeaturesChanged] notification is received.
  @protected
  @mustCallSuper
  void dispatchAccessibilityFeaturesChanged() {
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      observer.didChangeAccessibilityFeatures();
    }
  }

  Future<void> _handleStatusBarActions(MethodCall call) async {
    assert(call.method == 'handleScrollToTop');
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.handleStatusBarTap();
      } catch (exception, stack) {
        final details = FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'widgets library',
          context: ErrorDescription('handling status bar action'),
        );
        FlutterError.reportError(details);
        // No error widget possible here since it wouldn't have a view to render into.
      }
    }
  }

  /// Called when the system pops the current route.
  ///
  /// This first notifies the binding observers (using
  /// [WidgetsBindingObserver.didPopRoute]), in registration order, until one
  /// returns true, meaning that it was able to handle the request (e.g. by
  /// closing a dialog box). If none return true, then the application is shut
  /// down by calling [SystemNavigator.pop].
  ///
  /// [WidgetsApp] uses this in conjunction with a [Navigator] to
  /// cause the back button to close dialog boxes, return from modal
  /// pages, and so forth.
  ///
  /// This method exposes the `popRoute` notification from
  /// [SystemChannels.navigation].
  ///
  /// {@template flutter.widgets.AndroidPredictiveBack}
  /// ## Handling backs ahead of time
  ///
  /// Not all system backs will result in a call to this method. Some are
  /// handled entirely by the system without informing the Flutter framework.
  ///
  /// Android API 33+ introduced a feature called predictive back, which allows
  /// the user to peek behind the current app or route during a back gesture and
  /// then decide to cancel or commit the back. Flutter enables or disables this
  /// feature ahead of time, before a back gesture occurs, and back gestures
  /// that trigger predictive back are handled entirely by the system and do not
  /// trigger this method here in the framework.
  ///
  /// By default, the framework communicates when it would like to handle system
  /// back gestures using [SystemNavigator.setFrameworkHandlesBack] in
  /// [WidgetsApp]. This is done automatically based on the status of the
  /// [Navigator] stack and the state of any [PopScope] widgets present.
  /// Developers can manually set this by calling the method directly or by
  /// using [NavigationNotification].
  /// {@endtemplate}
  @protected
  @visibleForTesting
  Future<bool> handlePopRoute() async {
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        if (await observer.didPopRoute()) {
          return true;
        }
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didPopRoute',
            ),
          ),
        );
      }
    }
    SystemNavigator.pop();
    return false;
  }

  // The observers that are currently handling an active predictive back gesture.
  final List<WidgetsBindingObserver> _backGestureObservers = <WidgetsBindingObserver>[];

  bool _handleStartBackGesture(Map<String?, Object?> arguments) {
    _backGestureObservers.clear();
    final backEvent = PredictiveBackEvent.fromMap(arguments);
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        if (observer.handleStartBackGesture(backEvent)) {
          _backGestureObservers.add(observer);
        }
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.handleStartBackGesture',
            ),
          ),
        );
      }
    }
    return _backGestureObservers.isNotEmpty;
  }

  void _handleUpdateBackGestureProgress(Map<String?, Object?> arguments) {
    if (_backGestureObservers.isEmpty) {
      return;
    }

    final backEvent = PredictiveBackEvent.fromMap(arguments);
    for (final WidgetsBindingObserver observer in _backGestureObservers) {
      try {
        observer.handleUpdateBackGestureProgress(backEvent);
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.handleUpdateBackGestureProgress',
            ),
          ),
        );
      }
    }
  }

  Future<void> _handleCommitBackGesture() async {
    if (_backGestureObservers.isEmpty) {
      // If the predictive back was not handled, then the route should be popped
      // like a normal, non-predictive back. For example, this will happen if a
      // back gesture occurs but no predictive back route transition exists to
      // handle it. The back gesture should still cause normal pop even if it
      // doesn't cause a predictive transition.
      await handlePopRoute();
      return;
    }
    for (final WidgetsBindingObserver observer in _backGestureObservers) {
      try {
        observer.handleCommitBackGesture();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.handleCommitBackGesture',
            ),
          ),
        );
      }
    }
  }

  void _handleCancelBackGesture() {
    for (final WidgetsBindingObserver observer in _backGestureObservers) {
      try {
        observer.handleCancelBackGesture();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.handleCancelBackGesture',
            ),
          ),
        );
      }
    }
  }

  /// Called when the host tells the app to push a new route onto the
  /// navigator.
  ///
  /// This notifies the binding observers (using
  /// [WidgetsBindingObserver.didPushRoute]), in registration order, until one
  /// returns true, meaning that it was able to handle the request (e.g. by
  /// opening a dialog box). If none return true, then nothing happens.
  ///
  /// This method exposes the `pushRoute` notification from
  /// [SystemChannels.navigation].
  @protected
  @mustCallSuper
  @visibleForTesting
  Future<bool> handlePushRoute(String route) async {
    final routeInformation = RouteInformation(uri: Uri.parse(route));
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        if (await observer.didPushRouteInformation(routeInformation)) {
          return true;
        }
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didPushRouteInformation',
            ),
          ),
        );
      }
    }
    return false;
  }

  Future<bool> _handlePushRouteInformation(Map<dynamic, dynamic> routeArguments) async {
    final routeInformation = RouteInformation(
      uri: Uri.parse(routeArguments['location'] as String),
      state: routeArguments['state'] as Object?,
    );
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        if (await observer.didPushRouteInformation(routeInformation)) {
          return true;
        }
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didPushRouteInformation',
            ),
          ),
        );
      }
    }
    return false;
  }

  Future<bool> _handleNavigationInvocation(MethodCall methodCall) {
    return switch (methodCall.method) {
      'popRoute' => handlePopRoute(),
      'pushRoute' => handlePushRoute(methodCall.arguments as String),
      'pushRouteInformation' => _handlePushRouteInformation(
        methodCall.arguments as Map<dynamic, dynamic>,
      ),
      // Return false for unhandled method.
      _ => Future<bool>.value(false),
    };
  }

  Future<dynamic> _handleBackGestureInvocation(MethodCall methodCall) async {
    final Map<String?, Object?>? arguments = (methodCall.arguments as Map<Object?, Object?>?)
        ?.cast<String?, Object?>();
    return switch (methodCall.method) {
      'startBackGesture' => _handleStartBackGesture(arguments!),
      'updateBackGestureProgress' => _handleUpdateBackGestureProgress(arguments!),
      'commitBackGesture' => _handleCommitBackGesture(),
      'cancelBackGesture' => _handleCancelBackGesture(),
      _ => throw MissingPluginException(),
    };
  }

  @override
  void handleAppLifecycleStateChanged(AppLifecycleState state) {
    super.handleAppLifecycleStateChanged(state);
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeAppLifecycleState(state);
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeAppLifecycleState',
            ),
          ),
        );
      }
    }
  }

  @override
  void handleViewFocusChanged(ViewFocusEvent event) {
    super.handleViewFocusChanged(event);
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didChangeViewFocus(event);
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didChangeViewFocus',
            ),
          ),
        );
      }
    }
  }

  @override
  void handleMemoryPressure() {
    super.handleMemoryPressure();
    for (final observer in List<WidgetsBindingObserver>.of(_observers)) {
      try {
        observer.didHaveMemoryPressure();
      } catch (exception, stack) {
        FlutterError.reportError(
          FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'widgets library',
            context: ErrorDescription(
              'while dispatching notifications for WidgetsBindingObserver.didHaveMemoryPressure',
            ),
          ),
        );
      }
    }
  }

  bool _needToReportFirstFrame = true;

  final Completer<void> _firstFrameCompleter = Completer<void>();

  /// Whether the Flutter engine has rasterized the first frame.
  ///
  /// Usually, the time that a frame is rasterized is very close to the time that
  /// it gets presented on the display. Specifically, rasterization is the last
  /// expensive phase of a frame that's still in Flutter's control.
  ///
  /// See also:
  ///
  ///  * [waitUntilFirstFrameRasterized], the future when [firstFrameRasterized]
  ///    becomes true.
  bool get firstFrameRasterized => _firstFrameCompleter.isCompleted;

  /// A future that completes when the Flutter engine has rasterized the first
  /// frame.
  ///
  /// Usually, the time that a frame is rasterized is very close to the time that
  /// it gets presented on the display. Specifically, rasterization is the last
  /// expensive phase of a frame that's still in Flutter's control.
  ///
  /// See also:
  ///
  ///  * [firstFrameRasterized], whether this future has completed or not.
  Future<void> get waitUntilFirstFrameRasterized => _firstFrameCompleter.future;

  /// Whether the first frame has finished building.
  ///
  /// This value can also be obtained over the VM service protocol as
  /// `ext.flutter.didSendFirstFrameEvent`.
  ///
  /// See also:
  ///
  ///  * [firstFrameRasterized], whether the first frame has finished rendering.
  bool get debugDidSendFirstFrameEvent => !_needToReportFirstFrame;

  void _handleBuildScheduled() {
    // If we're in the process of building dirty elements, then changes
    // should not trigger a new frame.
    assert(() {
      if (debugBuildingDirtyElements) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('Build scheduled during frame.'),
          ErrorDescription(
            'While the widget tree was being built, laid out, and painted, '
            'a new frame was scheduled to rebuild the widget tree.',
          ),
          ErrorHint(
            'This might be because setState() was called from a layout or '
            'paint callback. '
            'If a change is needed to the widget tree, it should be applied '
            'as the tree is being built. Scheduling a change for the subsequent '
            'frame instead results in an interface that lags behind by one frame. '
            'If this was done to make your build dependent on a size measured at '
            'layout time, consider using a LayoutBuilder, CustomSingleChildLayout, '
            'or CustomMultiChildLayout. If, on the other hand, the one frame delay '
            'is the desired effect, for example because this is an '
            'animation, consider scheduling the frame in a post-frame callback '
            'using SchedulerBinding.addPostFrameCallback or '
            'using an AnimationController to trigger the animation.',
          ),
        ]);
      }
      return true;
    }());
    ensureVisualUpdate();
  }

  /// Whether we are currently in a frame. This is used to verify
  /// that frames are not scheduled redundantly.
  ///
  /// This is public so that test frameworks can change it.
  ///
  /// This flag is not used in release builds.
  @protected
  bool debugBuildingDirtyElements = false;

  /// Pump the build and rendering pipeline to generate a frame.
  ///
  /// This method is called by [handleDrawFrame], which itself is called
  /// automatically by the engine when it is time to lay out and paint a
  /// frame.
  ///
  /// Each frame consists of the following phases:
  ///
  /// 1. The animation phase: The [handleBeginFrame] method, which is registered
  /// with [PlatformDispatcher.onBeginFrame], invokes all the transient frame
  /// callbacks registered with [scheduleFrameCallback], in registration order.
  /// This includes all the [Ticker] instances that are driving
  /// [AnimationController] objects, which means all of the active [Animation]
  /// objects tick at this point.
  ///
  /// 2. Microtasks: After [handleBeginFrame] returns, any microtasks that got
  /// scheduled by transient frame callbacks get to run. This typically includes
  /// callbacks for futures from [Ticker]s and [AnimationController]s that
  /// completed this frame.
  ///
  /// After [handleBeginFrame], [handleDrawFrame], which is registered with
  /// [PlatformDispatcher.onDrawFrame], is called, which invokes all the
  /// persistent frame callbacks, of which the most notable is this method,
  /// [drawFrame], which proceeds as follows:
  ///
  /// 3. The build phase: All the dirty [Element]s in the widget tree are
  /// rebuilt (see [State.build]). See [State.setState] for further details on
  /// marking a widget dirty for building. See [BuildOwner] for more information
  /// on this step.
  ///
  /// 4. The layout phase: All the dirty [RenderObject]s in the system are laid
  /// out (see [RenderObject.performLayout]). See [RenderObject.markNeedsLayout]
  /// for further details on marking an object dirty for layout.
  ///
  /// 5. The compositing bits phase: The compositing bits on any dirty
  /// [RenderObject] objects are updated. See
  /// [RenderObject.markNeedsCompositingBitsUpdate].
  ///
  /// 6. The paint phase: All the dirty [RenderObject]s in the system are
  /// repainted (see [RenderObject.paint]). This generates the [Layer] tree. See
  /// [RenderObject.markNeedsPaint] for further details on marking an object
  /// dirty for paint.
  ///
  /// 7. The compositing phase: The layer tree is turned into a [Scene] and
  /// sent to the GPU.
  ///
  /// 8. The semantics phase: All the dirty [RenderObject]s in the system have
  /// their semantics updated (see [RenderObject.assembleSemanticsNode]). This
  /// generates the [SemanticsNode] tree. See
  /// [RenderObject.markNeedsSemanticsUpdate] for further details on marking an
  /// object dirty for semantics.
  ///
  /// For more details on steps 4-8, see [PipelineOwner].
  ///
  /// 9. The finalization phase in the widgets layer: The widgets tree is
  /// finalized. This causes [State.dispose] to be invoked on any objects that
  /// were removed from the widgets tree this frame. See
  /// [BuildOwner.finalizeTree] for more details.
  ///
  /// 10. The finalization phase in the scheduler layer: After [drawFrame]
  /// returns, [handleDrawFrame] then invokes post-frame callbacks (registered
  /// with [addPostFrameCallback]).
  //
  // When editing the above, also update rendering/binding.dart's copy.
  @override
  void drawFrame() {
    assert(!debugBuildingDirtyElements);
    assert(() {
      debugBuildingDirtyElements = true;
      return true;
    }());

    TimingsCallback? firstFrameCallback;
    var debugFrameWasSentToEngine = false;
    if (_needToReportFirstFrame) {
      assert(!_firstFrameCompleter.isCompleted);

      firstFrameCallback = (List<FrameTiming> timings) {
        assert(debugFrameWasSentToEngine);
        if (!kReleaseMode) {
          // Change the current user tag back to the default tag. At this point,
          // the user tag should be set to "AppStartUp" (originally set in the
          // engine), so we need to change it back to the default tag to mark
          // the end of app start up for CPU profiles.
          developer.UserTag.defaultTag.makeCurrent();
          developer.Timeline.instantSync('Rasterized first useful frame');
          developer.postEvent('Flutter.FirstFrame', <String, dynamic>{});
        }
        SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!);
        firstFrameCallback = null;
        _firstFrameCompleter.complete();
      };
      // Callback is only invoked when FlutterView.render is called. When
      // sendFramesToEngine is set to false during the frame, it will not be
      // called and we need to remove the callback (see below).
      SchedulerBinding.instance.addTimingsCallback(firstFrameCallback!);
    }

    try {
      if (rootElement != null) {
        buildOwner!.buildScope(rootElement!);
      }
      super.drawFrame();
      assert(() {
        debugFrameWasSentToEngine = sendFramesToEngine;
        return true;
      }());
      buildOwner!.finalizeTree();
    } finally {
      assert(() {
        debugBuildingDirtyElements = false;
        return true;
      }());
    }
    if (!kReleaseMode) {
      if (_needToReportFirstFrame && sendFramesToEngine) {
        developer.Timeline.instantSync('Widgets built first useful frame');
      }
    }
    _needToReportFirstFrame = false;
    if (firstFrameCallback != null && !sendFramesToEngine) {
      // This frame is deferred and not the first frame sent to the engine that
      // should be reported.
      _needToReportFirstFrame = true;
      SchedulerBinding.instance.removeTimingsCallback(firstFrameCallback!);
    }
  }

  /// The [Element] that is at the root of the element tree hierarchy.
  ///
  /// This is initialized the first time [runApp] is called.
  Element? get rootElement => _rootElement;
  Element? _rootElement;

  /// Deprecated. Will be removed in a future version of Flutter.
  ///
  /// Use [rootElement] instead.
  @Deprecated(
    'Use rootElement instead. '
    'This feature was deprecated after v3.9.0-16.0.pre.',
  )
  Element? get renderViewElement => rootElement;

  bool _readyToProduceFrames = false;

  @override
  bool get framesEnabled => super.framesEnabled && _readyToProduceFrames;

  /// Used by [runApp] to wrap the provided `rootWidget` in the default [View].
  ///
  /// The [View] determines into what [FlutterView] the app is rendered into.
  /// This is currently [PlatformDispatcher.implicitView] from [platformDispatcher].
  /// This method will throw a [StateError] if the [PlatformDispatcher.implicitView]
  /// is null.
  ///
  /// The `rootWidget` widget provided to this method must not already be
  /// wrapped in a [View].
  Widget wrapWithDefaultView(Widget rootWidget) {
    if (platformDispatcher.implicitView == null) {
      throw StateError(
        'The app requested a view, but the platform did not provide one.\n'
        'This is likely because the app called `runApp` to render its root '
        'widget, which expects the platform to provide a default view to '
        'render into (the "implicit" view).\n'
        'However, the platform likely has multi-view mode enabled, which does '
        'not create this default "implicit" view.\n'
        'Try using `runWidget` instead of `runApp` to start your app.\n'
        '`runWidget` allows you to provide a `View` widget, without requiring '
        'a default view.'
        '${kIsWeb ? "\nSee: https://flutter.dev/to/web-multiview-runwidget" : ""}',
      );
    }

    return View(
      view: platformDispatcher.implicitView!,
      deprecatedDoNotUseWillBeRemovedWithoutNoticePipelineOwner: pipelineOwner,
      deprecatedDoNotUseWillBeRemovedWithoutNoticeRenderView: renderView,
      child: rootWidget,
    );
  }

  /// Schedules a [Timer] for attaching the root widget.
  ///
  /// This is called by [runApp] to configure the widget tree. Consider using
  /// [attachRootWidget] if you want to build the widget tree synchronously.
  @protected
  void scheduleAttachRootWidget(Widget rootWidget) {
    Timer.run(() {
      attachRootWidget(rootWidget);
    });
  }

  /// Takes a widget and attaches it to the [rootElement], creating it if
  /// necessary.
  ///
  /// This is called by [runApp] to configure the widget tree.
  ///
  /// See also:
  ///
  ///  * [RenderObjectToWidgetAdapter.attachToRenderTree], which inflates a
  ///    widget and attaches it to the render tree.
  void attachRootWidget(Widget rootWidget) {
    attachToBuildOwner(RootWidget(debugShortDescription: '[root]', child: rootWidget));
  }

  /// Called by [attachRootWidget] to attach the provided [RootWidget] to the
  /// [buildOwner].
  ///
  /// This creates the [rootElement], if necessary, or re-uses an existing one.
  ///
  /// This method is rarely called directly, but it can be useful in tests to
  /// restore the element tree to a previous version by providing the
  /// [RootWidget] of that version (see [WidgetTester.restartAndRestore] for an
  /// exemplary use case).
  void attachToBuildOwner(RootWidget widget) {
    final isBootstrapFrame = rootElement == null;
    _readyToProduceFrames = true;
    _rootElement = widget.attach(buildOwner!, rootElement as RootElement?);
    if (isBootstrapFrame) {
      SchedulerBinding.instance.ensureVisualUpdate();
    }
  }

  /// Whether the [rootElement] has been initialized.
  ///
  /// This will be false until [runApp] is called (or [WidgetTester.pumpWidget]
  /// is called in the context of a [TestWidgetsFlutterBinding]).
  bool get isRootWidgetAttached => _rootElement != null;

  @override
  Future<void> performReassemble() {
    assert(() {
      WidgetInspectorService.instance.performReassemble();
      return true;
    }());

    if (rootElement != null) {
      buildOwner!.reassemble(rootElement!);
    }
    return super.performReassemble();
  }

  /// Computes the locale the current platform would resolve to.
  ///
  /// This method is meant to be used as part of a
  /// [WidgetsApp.localeListResolutionCallback]. Since this method may return
  /// null, a Flutter/dart algorithm should still be provided as a fallback in
  /// case a native resolved locale cannot be determined or if the native
  /// resolved locale is undesirable.
  ///
  /// This method may return a null [Locale] if the platform does not support
  /// native locale resolution, or if the resolution failed.
  ///
  /// The first `supportedLocale` is treated as the default locale and will be returned
  /// if no better match is found.
  ///
  /// Android and iOS are currently supported.
  ///
  /// On Android, the algorithm described in
  /// https://developer.android.com/guide/topics/resources/multilingual-support
  /// is used to determine the resolved locale. Depending on the android version
  /// of the device, either the modern (>= API 24) or legacy (< API 24) algorithm
  /// will be used.
  ///
  /// On iOS, the result of `preferredLocalizationsFromArray` method of `NSBundle`
  /// is returned. See:
  /// https://developer.apple.com/documentation/foundation/nsbundle/1417249-preferredlocalizationsfromarray?language=objc
  /// for details on the used method.
  ///
  /// iOS treats script code as necessary for a match, so a user preferred locale of
  /// `zh_Hans_CN` will not resolve to a supported locale of `zh_CN`.
  ///
  /// Since implementation may vary by platform and has potential to be heavy,
  /// it is recommended to cache the results of this method if the value is
  /// used multiple times.
  ///
  /// Second-best (and n-best) matching locales should be obtained by calling this
  /// method again with the matched locale of the first call omitted from
  /// `supportedLocales`.
  Locale? computePlatformResolvedLocale(List<Locale> supportedLocales) {
    return platformDispatcher.computePlatformResolvedLocale(supportedLocales);
  }

  /// The [WindowingOwner] is responsible for creating and managing [BaseWindowController]s.
  ///
  /// The default [WindowingOwner] supports macOS, Linux, and Windows.
  ///
  /// A custom [WindowingOwner] can be provided by the setter.
  ///
  /// {@template flutter.widgets.binding.window.experimental}
  /// Do not use this API in production applications or packages published to
  /// pub.dev. Flutter will make breaking changes to this API, even in patch
  /// versions.
  ///
  /// This API throws an [UnsupportedError] error unless Flutter’s windowing
  /// feature is enabled by [isWindowingEnabled].
  ///
  /// See: https://github.com/flutter/flutter/issues/30701.
  /// {@endtemplate}
  @internal
  WindowingOwner get windowingOwner {
    if (!isWindowingEnabled) {
      throw UnsupportedError('''
Windowing APIs are not enabled.

Windowing APIs are currently experimental. Do not use windowing APIs in
production applications or plugins published to pub.dev.

To try experimental windowing APIs:
1. Switch to Flutter's main release channel.
2. Turn on the windowing feature flag.

See: https://github.com/flutter/flutter/issues/30701.
''');
    }
    return _windowingOwner;
  }

  /// Sets the [WindowingOwner].
  ///
  /// The default [WindowingOwner] supports macOS, Linux, and Windows.
  ///
  /// This setter can be used to provide a custom [WindowingOwner].
  ///
  /// {@macro flutter.widgets.binding.window.experimental}
  @internal
  set windowingOwner(WindowingOwner owner) {
    if (!isWindowingEnabled) {
      throw UnsupportedError('''
Windowing APIs are not enabled.

Windowing APIs are currently experimental. Do not use windowing APIs in
production applications or plugins published to pub.dev.

To try experimental windowing APIs:
1. Switch to Flutter's main release channel.
2. Turn on the windowing feature flag.

See: https://github.com/flutter/flutter/issues/30701.
''');
    }
    _windowingOwner = owner;
  }

  late WindowingOwner _windowingOwner;
}

/// Inflate the given widget and attach it to the view.
///
// TODO(goderbauer): Update the paragraph below to include the Window widget once that exists.
/// The [runApp] method renders the provided `app` widget into the
/// [PlatformDispatcher.implicitView] by wrapping it in a [View] widget, which
/// will bootstrap the render tree for the app. Apps that want to control which
/// [FlutterView] they render into can use [runWidget] instead.
///
/// The widget is given constraints during layout that force it to fill the
/// entire view. If you wish to align your widget to one side of the view
/// (e.g., the top), consider using the [Align] widget. If you wish to center
/// your widget, you can also use the [Center] widget.
///
/// Calling [runApp] again will detach the previous root widget from the view
/// and attach the given widget in its place. The new widget tree is compared
/// against the previous widget tree and any differences are applied to the
/// underlying render tree, similar to what happens when a [StatefulWidget]
/// rebuilds after calling [State.setState].
///
/// Initializes the binding using [WidgetsFlutterBinding] if necessary.
///
/// {@template flutter.widgets.runApp.shutdown}
/// ## Application shutdown
///
/// This widget tree is not torn down when the application shuts down, because
/// there is no way to predict when that will happen. For example, a user could
/// physically remove power from their device, or the application could crash
/// unexpectedly, or the malware on the device could forcibly terminate the
/// process.
///
/// Applications are responsible for ensuring that they are well-behaved
/// even in the face of a rapid unscheduled termination.
///
/// To listen for platform shutdown messages (and other lifecycle changes),
/// consider the [AppLifecycleListener] API.
/// {@endtemplate}
///
/// To artificially cause the entire widget tree to be disposed, consider
/// calling [runApp] with a widget such as [SizedBox.shrink].
///
/// {@template flutter.widgets.runApp.dismissal}
/// ## Dismissing Flutter UI via platform native methods
///
/// An application may have both Flutter and non-Flutter UI in it. If the
/// application calls non-Flutter methods to remove Flutter based UI such as
/// platform native API to manipulate the platform native navigation stack,
/// the framework does not know if the developer intends to eagerly free
/// resources or not. The widget tree remains mounted and ready to render
/// as soon as it is displayed again.
/// {@endtemplate}
///
/// To release resources more eagerly, establish a [platform channel](https://flutter.dev/to/platform-channels)
/// and use it to call [runApp] with a widget such as [SizedBox.shrink] when
/// the framework should dispose of the active widget tree.
///
/// See also:
///
///  * [runWidget], which bootstraps a widget tree without assuming the
///    [FlutterView] into which it will be rendered.
///  * [WidgetsBinding.attachRootWidget], which creates the root widget for the
///    widget hierarchy.
///  * [RenderObjectToWidgetAdapter.attachToRenderTree], which creates the root
///    element for the element hierarchy.
///  * [WidgetsBinding.handleBeginFrame], which pumps the widget pipeline to
///    ensure the widget, element, and render trees are all built.
void runApp(Widget app) {
  final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  _runWidget(binding.wrapWithDefaultView(app), binding, 'runApp');
}

/// Inflate the given widget and bootstrap the widget tree.
///
// TODO(goderbauer): Update the paragraph below to include the Window widget once that exists.
/// Unlike [runApp], this method does not define a [FlutterView] into which the
/// provided `app` widget is rendered into. It is up to the caller to include at
/// least one [View] widget in the provided `app` widget that will bootstrap a
/// render tree and define the [FlutterView] into which content is rendered.
/// [RenderObjectWidget]s without an ancestor [View] widget will result in an
/// exception. Apps that want to render into the default view without dealing
/// with view management should consider calling [runApp] instead.
///
/// {@tool snippet}
/// The sample shows how to utilize [runWidget] to specify the [FlutterView]
/// into which the `MyApp` widget will be drawn:
///
/// ```dart
/// runWidget(
///   View(
///     view: myFlutterView,
///     child: const MyApp(),
///   ),
/// );
/// ```
/// {@end-tool}
///
/// Calling [runWidget] again will detach the previous root widget and attach
/// the given widget in its place. The new widget tree is compared against the
/// previous widget tree and any differences are applied to the underlying
/// render tree, similar to what happens when a [StatefulWidget] rebuilds after
/// calling [State.setState].
///
/// Initializes the binding using [WidgetsFlutterBinding] if necessary.
///
/// {@macro flutter.widgets.runApp.shutdown}
///
/// To artificially cause the entire widget tree to be disposed, consider
/// calling [runWidget] with a [ViewCollection] that does not specify any
/// [ViewCollection.views].
///
/// {@macro flutter.widgets.runApp.dismissal}
///
/// To release resources more eagerly, establish a [platform channel](https://flutter.dev/to/platform-channels)
/// and use it to remove the [View] whose widget resources should be released
/// from the `app` widget tree provided to [runWidget].
///
/// See also:
///
///  * [runApp], which bootstraps a widget tree and renders it into a default
///    [FlutterView].
///  * [WidgetsBinding.attachRootWidget], which creates the root widget for the
///    widget hierarchy.
///  * [RenderObjectToWidgetAdapter.attachToRenderTree], which creates the root
///    element for the element hierarchy.
///  * [WidgetsBinding.handleBeginFrame], which pumps the widget pipeline to
///    ensure the widget, element, and render trees are all built.
void runWidget(Widget app) {
  final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  _runWidget(app, binding, 'runWidget');
}

void _runWidget(Widget app, WidgetsBinding binding, String debugEntryPoint) {
  assert(binding.debugCheckZone(debugEntryPoint));
  binding
    ..scheduleAttachRootWidget(app)
    ..scheduleWarmUpFrame();
}

String _debugDumpAppString() {
  const mode = kDebugMode
      ? 'DEBUG MODE'
      : kReleaseMode
      ? 'RELEASE MODE'
      : 'PROFILE MODE';
  final buffer = StringBuffer();
  buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode');
  if (WidgetsBinding.instance.rootElement != null) {
    buffer.writeln(WidgetsBinding.instance.rootElement!.toStringDeep());
  } else {
    buffer.writeln('<no tree currently mounted>');
  }
  return buffer.toString();
}

/// Print a string representation of the currently running app.
void debugDumpApp() {
  debugPrint(_debugDumpAppString());
}

/// A widget for the root of the widget tree.
///
/// Exposes an [attach] method to attach the widget tree to a [BuildOwner]. That
/// method also bootstraps the element tree.
///
/// Used by [WidgetsBinding.attachRootWidget] (which is indirectly called by
/// [runApp]) to bootstrap applications.
class RootWidget extends Widget {
  /// Creates a [RootWidget].
  const RootWidget({super.key, this.child, this.debugShortDescription});

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget? child;

  /// A short description of this widget used by debugging aids.
  final String? debugShortDescription;

  @override
  RootElement createElement() => RootElement(this);

  /// Inflate this widget and attaches it to the provided [BuildOwner].
  ///
  /// If `element` is null, this function will create a new element. Otherwise,
  /// the given element will have an update scheduled to switch to this widget.
  ///
  /// Used by [WidgetsBinding.attachToBuildOwner] (which is indirectly called by
  /// [runApp]) to bootstrap applications.
  RootElement attach(BuildOwner owner, [RootElement? element]) {
    if (element == null) {
      owner.lockState(() {
        element = createElement();
        assert(element != null);
        element!.assignOwner(owner);
      });
      owner.buildScope(element!, () {
        element!.mount(/* parent */ null, /* slot */ null);
      });
    } else {
      element._newWidget = this;
      element.markNeedsBuild();
    }
    return element!;
  }

  @override
  String toStringShort() => debugShortDescription ?? super.toStringShort();
}

/// The root of the element tree.
///
/// This element class is the instantiation of a [RootWidget]. It can be used
/// only as the root of an [Element] tree (it cannot be mounted into another
/// [Element]; its parent must be null).
///
/// In typical usage, it will be instantiated for a [RootWidget] by calling
/// [RootWidget.attach]. In this usage, it is normally instantiated by the
/// bootstrapping logic in the [WidgetsFlutterBinding] singleton created by
/// [runApp].
class RootElement extends Element with RootElementMixin {
  /// Creates a [RootElement] for the provided [RootWidget].
  RootElement(RootWidget super.widget);

  Element? _child;

  @override
  void visitChildren(ElementVisitor visitor) {
    if (_child != null) {
      visitor(_child!);
    }
  }

  @override
  void forgetChild(Element child) {
    assert(child == _child);
    _child = null;
    super.forgetChild(child);
  }

  @override
  void mount(Element? parent, Object? newSlot) {
    assert(parent == null); // We are the root!
    super.mount(parent, newSlot);
    _rebuild();
    assert(_child != null);
    super.performRebuild(); // clears the "dirty" flag
  }

  @override
  void update(RootWidget newWidget) {
    super.update(newWidget);
    assert(widget == newWidget);
    _rebuild();
  }

  // When we are assigned a new widget, we store it here
  // until we are ready to update to it.
  RootWidget? _newWidget;

  @override
  void performRebuild() {
    if (_newWidget != null) {
      // _newWidget can be null if, for instance, we were rebuilt
      // due to a reassemble.
      final RootWidget newWidget = _newWidget!;
      _newWidget = null;
      update(newWidget);
    }
    super.performRebuild();
    assert(_newWidget == null);
  }

  void _rebuild() {
    try {
      _child = updateChild(_child, (widget as RootWidget).child, /* slot */ null);
    } catch (exception, stack) {
      final details = FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'widgets library',
        context: ErrorDescription('attaching to the render tree'),
      );
      FlutterError.reportError(details);
      // No error widget possible here since it wouldn't have a view to render into.
      _child = null;
    }
  }

  @override
  bool get debugDoingBuild => false; // This element doesn't have a build phase.

  @override
  // There is no ancestor RenderObjectElement that the render object could be attached to.
  bool debugExpectsRenderObjectForSlot(Object? slot) => false;
}

/// A concrete binding for applications based on the Widgets framework.
///
/// This is the glue that binds the framework to the Flutter engine.
///
/// When using the widgets framework, this binding, or one that
/// implements the same interfaces, must be used. The following
/// mixins are used to implement this binding:
///
/// * [GestureBinding], which implements the basics of hit testing.
/// * [SchedulerBinding], which introduces the concepts of frames.
/// * [ServicesBinding], which provides access to the plugin subsystem.
/// * [PaintingBinding], which enables decoding images.
/// * [SemanticsBinding], which supports accessibility.
/// * [RendererBinding], which handles the render tree.
/// * [WidgetsBinding], which handles the widget tree.
class WidgetsFlutterBinding extends BindingBase
    with
        GestureBinding,
        SchedulerBinding,
        ServicesBinding,
        PaintingBinding,
        SemanticsBinding,
        RendererBinding,
        WidgetsBinding {
  /// Returns an instance of the binding that implements
  /// [WidgetsBinding]. If no binding has yet been initialized, the
  /// [WidgetsFlutterBinding] class is used to create and initialize
  /// one.
  ///
  /// You only need to call this method if you need the binding to be
  /// initialized before calling [runApp].
  ///
  /// In the `flutter_test` framework, [testWidgets] initializes the
  /// binding instance to a [TestWidgetsFlutterBinding], not a
  /// [WidgetsFlutterBinding]. See
  /// [TestWidgetsFlutterBinding.ensureInitialized].
  static WidgetsBinding ensureInitialized() {
    if (WidgetsBinding._instance == null) {
      WidgetsFlutterBinding();
    }
    return WidgetsBinding.instance;
  }
}
