[flutter_releases] Flutter beta 2.13.0-0.2.pre Framework Cherrypicks (#102193)

* Ensure that the engine frame callbacks are installed if the first scheduled frame is a forced frame (#101544)

See https://github.com/flutter/flutter/issues/98419

* Migrate common buttons to Material 3 (#100794)

* Always finish the timeline event logged by Element.inflateWidget (#101794)

* 'Create candidate branch version flutter-2.13-candidate.0 for beta'

* 'Update Engine revision to 24a02fa5ee681840cdc842c22f4cb4bdd5ec3115 for beta release 2.13.0-0.2.pre'

* Update release-candidate-branch.version

Co-authored-by: Jason Simmons <jason-simmons@users.noreply.github.com>
Co-authored-by: Darren Austin <darrenaustin@google.com>
diff --git a/bin/internal/engine.version b/bin/internal/engine.version
index 4bb41dd..9828924 100644
--- a/bin/internal/engine.version
+++ b/bin/internal/engine.version
@@ -1 +1 @@
-499984f99cfe01e3b69d962ec4847f70c4317694
+24a02fa5ee681840cdc842c22f4cb4bdd5ec3115
diff --git a/dev/tools/gen_defaults/bin/gen_defaults.dart b/dev/tools/gen_defaults/bin/gen_defaults.dart
index 187e0f7..0694020 100644
--- a/dev/tools/gen_defaults/bin/gen_defaults.dart
+++ b/dev/tools/gen_defaults/bin/gen_defaults.dart
@@ -17,6 +17,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:gen_defaults/button_template.dart';
 import 'package:gen_defaults/card_template.dart';
 import 'package:gen_defaults/dialog_template.dart';
 import 'package:gen_defaults/fab_template.dart';
@@ -77,6 +78,9 @@
   tokens['colorsLight'] = _readTokenFile('color_light.json');
   tokens['colorsDark'] = _readTokenFile('color_dark.json');
 
+  ButtonTemplate('md.comp.elevated-button', '$materialLib/elevated_button.dart', tokens).updateFile();
+  ButtonTemplate('md.comp.outlined-button', '$materialLib/outlined_button.dart', tokens).updateFile();
+  ButtonTemplate('md.comp.text-button', '$materialLib/text_button.dart', tokens).updateFile();
   CardTemplate('$materialLib/card.dart', tokens).updateFile();
   DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
   FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
diff --git a/dev/tools/gen_defaults/lib/button_template.dart b/dev/tools/gen_defaults/lib/button_template.dart
new file mode 100644
index 0000000..3810871
--- /dev/null
+++ b/dev/tools/gen_defaults/lib/button_template.dart
@@ -0,0 +1,153 @@
+// 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.
+
+import 'template.dart';
+
+class ButtonTemplate extends TokenTemplate {
+  const ButtonTemplate(this.tokenGroup, String fileName, Map<String, dynamic> tokens)
+    : super(fileName, tokens,
+        colorSchemePrefix: '_colors.',
+      );
+
+  final String tokenGroup;
+
+  String _backgroundColor() {
+    if (tokens.containsKey('$tokenGroup.container.color')) {
+      return '''
+
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return ${componentColor('$tokenGroup.disabled.container')};
+      return ${componentColor('$tokenGroup.container')};
+    })''';
+    }
+    return '''
+
+    ButtonStyleButton.allOrNull<Color>(Colors.transparent)''';
+  }
+
+  String _elevation() {
+    if (tokens.containsKey('$tokenGroup.container.elevation')) {
+      return '''
+
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return ${elevation("$tokenGroup.disabled.container")};
+      if (states.contains(MaterialState.hovered))
+        return ${elevation("$tokenGroup.hover.container")};
+      if (states.contains(MaterialState.focused))
+        return ${elevation("$tokenGroup.focus.container")};
+      if (states.contains(MaterialState.pressed))
+        return ${elevation("$tokenGroup.pressed.container")};
+      return ${elevation("$tokenGroup.container")};
+    })''';
+    }
+    return '''
+
+    ButtonStyleButton.allOrNull<double>(0.0)''';
+  }
+
+  @override
+  String generate() => '''
+// Generated version ${tokens["version"]}
+class _TokenDefaultsM3 extends ButtonStyle {
+  _TokenDefaultsM3(this.context)
+   : super(
+       animationDuration: kThemeChangeDuration,
+       enableFeedback: true,
+       alignment: Alignment.center,
+     );
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override
+  MaterialStateProperty<TextStyle?> get textStyle =>
+    MaterialStateProperty.all<TextStyle?>(${textStyle("$tokenGroup.label-text")});
+
+  @override
+  MaterialStateProperty<Color?>? get backgroundColor =>${_backgroundColor()};
+
+  @override
+  MaterialStateProperty<Color?>? get foregroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return ${componentColor('$tokenGroup.disabled.label-text')};
+      return ${componentColor('$tokenGroup.label-text')};
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get overlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.hovered))
+        return ${componentColor('$tokenGroup.hover.state-layer')};
+      if (states.contains(MaterialState.focused))
+        return ${componentColor('$tokenGroup.focus.state-layer')};
+      if (states.contains(MaterialState.pressed))
+        return ${componentColor('$tokenGroup.pressed.state-layer')};
+      return null;
+    });
+
+${tokens.containsKey("$tokenGroup.container.shadow-color") ? '''
+  @override
+  MaterialStateProperty<Color>? get shadowColor =>
+    ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.shadow-color")});''' : '''
+  // No default shadow color'''}
+
+${tokens.containsKey("$tokenGroup.container.surface-tint-layer.color") ? '''
+  @override
+  MaterialStateProperty<Color>? get surfaceTintColor =>
+    ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.surface-tint-layer.color")});''' : '''
+  // No default surface tint color'''}
+
+  @override
+  MaterialStateProperty<double>? get elevation =>${_elevation()};
+
+  @override
+  MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
+    ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
+
+  @override
+  MaterialStateProperty<Size>? get minimumSize =>
+    ButtonStyleButton.allOrNull<Size>(const Size(64.0, ${tokens["$tokenGroup.container.height"]}));
+
+  // No default fixedSize
+
+  @override
+  MaterialStateProperty<Size>? get maximumSize =>
+    ButtonStyleButton.allOrNull<Size>(Size.infinite);
+
+${tokens.containsKey("$tokenGroup.outline.color") ? '''
+  @override
+  MaterialStateProperty<BorderSide>? get side =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+    if (states.contains(MaterialState.disabled))
+      return ${border("$tokenGroup.disabled.outline")};
+    return ${border("$tokenGroup.outline")};
+  });''' : '''
+  // No default side'''}
+
+  @override
+  MaterialStateProperty<OutlinedBorder>? get shape =>
+    ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("$tokenGroup.container")});
+
+  @override
+  MaterialStateProperty<MouseCursor?>? get mouseCursor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return SystemMouseCursors.basic;
+      return SystemMouseCursors.click;
+    });
+
+  @override
+  VisualDensity? get visualDensity => Theme.of(context).visualDensity;
+
+  @override
+  MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
+
+  @override
+  InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
+}
+''';
+}
diff --git a/dev/tools/gen_defaults/lib/template.dart b/dev/tools/gen_defaults/lib/template.dart
index f63bea0..ff37837 100644
--- a/dev/tools/gen_defaults/lib/template.dart
+++ b/dev/tools/gen_defaults/lib/template.dart
@@ -70,8 +70,8 @@
   ///   * [componentColor], that provides support for an optional opacity.
   String color(String colorToken) {
     return tokens.containsKey(colorToken)
-        ? '$colorSchemePrefix${tokens[colorToken]}'
-        : 'null';
+      ? '$colorSchemePrefix${tokens[colorToken]}'
+      : 'null';
   }
 
   /// Generate a [ColorScheme] color name for the given component's color
@@ -91,17 +91,25 @@
     if (!tokens.containsKey(colorToken))
       return 'null';
     String value = color(colorToken);
-    final String tokenOpacity = '$componentToken.opacity';
-    if (tokens.containsKey(tokenOpacity)) {
-      final dynamic opacityValue = tokens[tokenOpacity];
-      final String opacity = opacityValue is double
-       ? opacityValue.toString()
-       : tokens[tokens[tokenOpacity]!]!.toString();
-      value += '.withOpacity($opacity)';
+    final String opacityToken = '$componentToken.opacity';
+    if (tokens.containsKey(opacityToken)) {
+      value += '.withOpacity(${opacity(opacityToken)})';
     }
     return value;
   }
 
+  /// Generate the opacity value for the given token.
+  String? opacity(String token) {
+    final dynamic value = tokens[token];
+    if (value == null) {
+      return null;
+    }
+    if (value is double) {
+      return value.toString();
+    }
+    return tokens[value].toString();
+  }
+
   /// Generate an elevation value for the given component token.
   String elevation(String componentToken) {
     return tokens[tokens['$componentToken.elevation']!]!.toString();
@@ -135,7 +143,7 @@
       return 'null';
     }
     final String borderColor = componentColor(componentToken);
-    final double width = tokens['$componentToken.width'] as double;
+    final double width = (tokens['$componentToken.width'] ?? 1.0) as double;
     return 'BorderSide(color: $borderColor${width != 1.0 ? ", width: $width" : ""})';
   }
 
diff --git a/dev/tracing_tests/test/inflate_widget_update_test.dart b/dev/tracing_tests/test/inflate_widget_update_test.dart
new file mode 100644
index 0000000..acfd014
--- /dev/null
+++ b/dev/tracing_tests/test/inflate_widget_update_test.dart
@@ -0,0 +1,77 @@
+// 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.
+
+import 'package:flutter/scheduler.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'common.dart';
+
+void main() {
+  WidgetsFlutterBinding.ensureInitialized();
+  initTimelineTests();
+  test('Widgets with updated keys produce well formed timelines', () async {
+    await runFrame(() { runApp(const TestRoot()); });
+    await SchedulerBinding.instance.endOfFrame;
+
+    debugProfileBuildsEnabled = true;
+
+    await runFrame(() {
+      TestRoot.state.updateKey();
+    });
+
+    int buildCount = 0;
+    for (final TimelineEvent event in await fetchTimelineEvents()) {
+      if (event.json!['name'] == 'BUILD') {
+        final String ph = event.json!['ph'] as String;
+        if (ph == 'B') {
+          buildCount++;
+        } else if (ph == 'E') {
+          buildCount--;
+        }
+      }
+    }
+    expect(buildCount, 0);
+
+    debugProfileBuildsEnabled = false;
+  }, skip: isBrowser); // [intended] uses dart:isolate and io.
+}
+
+class TestRoot extends StatefulWidget {
+  const TestRoot({super.key});
+
+  static late TestRootState state;
+
+  @override
+  State<TestRoot> createState() => TestRootState();
+}
+
+class TestRootState extends State<TestRoot> {
+  final Key _globalKey = GlobalKey();
+  Key _localKey = UniqueKey();
+
+  @override
+  void initState() {
+    super.initState();
+    TestRoot.state = this;
+  }
+
+  void updateKey() {
+    setState(() {
+      _localKey = UniqueKey();
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      key: _localKey,
+      child: SizedBox(
+        key: _globalKey,
+        width: 100,
+        height: 100,
+      ),
+    );
+  }
+}
diff --git a/examples/api/lib/material/button_style/button_style.0.dart b/examples/api/lib/material/button_style/button_style.0.dart
new file mode 100644
index 0000000..bff8602
--- /dev/null
+++ b/examples/api/lib/material/button_style/button_style.0.dart
@@ -0,0 +1,95 @@
+// 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.
+
+// Flutter code sample for ElevatedButton
+
+import 'package:flutter/material.dart';
+
+void main() {
+  runApp(const ButtonApp());
+}
+
+class ButtonApp extends StatelessWidget {
+  const ButtonApp({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
+      title: 'Button Types',
+      home: const Scaffold(
+        body: ButtonTypesExample(),
+      ),
+    );
+  }
+}
+
+class ButtonTypesExample extends StatelessWidget {
+  const ButtonTypesExample({Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return Padding(
+      padding: const EdgeInsets.all(4.0),
+      child: Row(
+        children: const <Widget>[
+          Spacer(),
+          ButtonTypesGroup(enabled: true),
+          ButtonTypesGroup(enabled: false),
+          Spacer(),
+        ],
+      ),
+    );
+  }
+}
+
+class ButtonTypesGroup extends StatelessWidget {
+  const ButtonTypesGroup({ Key? key, required this.enabled }) : super(key: key);
+
+  final bool enabled;
+
+  @override
+  Widget build(BuildContext context) {
+    final VoidCallback? onPressed = enabled ? () {} : null;
+    return Padding(
+      padding: const EdgeInsets.all(4.0),
+      child: Column(
+        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+        children: <Widget>[
+          ElevatedButton(onPressed: onPressed, child: const Text('Elevated')),
+
+          // Use an ElevatedButton with specific style to implement the
+          // 'Filled' type.
+          ElevatedButton(
+            style: ElevatedButton.styleFrom(
+              // Foreground color
+              onPrimary: Theme.of(context).colorScheme.onPrimary,
+              // Background color
+              primary: Theme.of(context).colorScheme.primary,
+            ).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
+            onPressed: onPressed,
+            child: const Text('Filled'),
+          ),
+
+          // Use an ElevatedButton with specific style to implement the
+          // 'Filled Tonal' type.
+          ElevatedButton(
+            style: ElevatedButton.styleFrom(
+              // Foreground color
+              onPrimary: Theme.of(context).colorScheme.onSecondaryContainer,
+              // Background color
+              primary: Theme.of(context).colorScheme.secondaryContainer,
+            ).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
+            onPressed: onPressed,
+            child: const Text('Filled Tonal'),
+          ),
+
+          OutlinedButton(onPressed: onPressed, child: const Text('Outlined')),
+
+          TextButton(onPressed: onPressed, child: const Text('Text')),
+        ],
+      ),
+    );
+  }
+}
diff --git a/packages/flutter/lib/src/material/button_style.dart b/packages/flutter/lib/src/material/button_style.dart
index 3d1ad80..4026fd7 100644
--- a/packages/flutter/lib/src/material/button_style.dart
+++ b/packages/flutter/lib/src/material/button_style.dart
@@ -91,6 +91,27 @@
 ///   home: MyAppHome(),
 /// )
 /// ```
+///
+/// ## Material 3 button types
+///
+/// Material Design 3 specifies five types of common buttons. Flutter provides
+/// support for these using the following button classes:
+/// <style>table,td,th { border-collapse: collapse; padding: 0.45em; } td { border: 1px solid }</style>
+///
+/// | Type         | Flutter implementation  |
+/// | :----------- | :---------------------- |
+/// | Elevated     | [ElevatedButton]        |
+/// | Filled       | Styled [ElevatedButton] |
+/// | Filled Tonal | Styled [ElevatedButton] |
+/// | Outlined     | [OutlinedButton]        |
+/// | Text         | [TextButton]            |
+///
+/// {@tool dartpad}
+/// This sample shows how to create each of the Material 3 button types with Flutter.
+///
+/// ** See code in examples/api/lib/material/button_style/button_style.0.dart **
+/// {@end-tool}
+///
 /// See also:
 ///
 ///  * [TextButtonTheme], the theme for [TextButton]s.
@@ -105,6 +126,7 @@
     this.foregroundColor,
     this.overlayColor,
     this.shadowColor,
+    this.surfaceTintColor,
     this.elevation,
     this.padding,
     this.minimumSize,
@@ -150,6 +172,11 @@
   /// [ThemeData.applyElevationOverlayColor].
   final MaterialStateProperty<Color?>? shadowColor;
 
+  /// The surface tint color of the button's [Material].
+  ///
+  /// See [Material.surfaceTintColor] for more details.
+  final MaterialStateProperty<Color?>? surfaceTintColor;
+
   /// The elevation of the button's [Material].
   final MaterialStateProperty<double?>? elevation;
 
@@ -267,6 +294,7 @@
     MaterialStateProperty<Color?>? foregroundColor,
     MaterialStateProperty<Color?>? overlayColor,
     MaterialStateProperty<Color?>? shadowColor,
+    MaterialStateProperty<Color?>? surfaceTintColor,
     MaterialStateProperty<double?>? elevation,
     MaterialStateProperty<EdgeInsetsGeometry?>? padding,
     MaterialStateProperty<Size?>? minimumSize,
@@ -288,6 +316,7 @@
       foregroundColor: foregroundColor ?? this.foregroundColor,
       overlayColor: overlayColor ?? this.overlayColor,
       shadowColor: shadowColor ?? this.shadowColor,
+      surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
       elevation: elevation ?? this.elevation,
       padding: padding ?? this.padding,
       minimumSize: minimumSize ?? this.minimumSize,
@@ -319,6 +348,7 @@
       foregroundColor: foregroundColor ?? style.foregroundColor,
       overlayColor: overlayColor ?? style.overlayColor,
       shadowColor: shadowColor ?? style.shadowColor,
+      surfaceTintColor: surfaceTintColor ?? style.surfaceTintColor,
       elevation: elevation ?? style.elevation,
       padding: padding ?? style.padding,
       minimumSize: minimumSize ?? style.minimumSize,
@@ -343,6 +373,7 @@
     foregroundColor,
     overlayColor,
     shadowColor,
+    surfaceTintColor,
     elevation,
     padding,
     minimumSize,
@@ -371,6 +402,7 @@
         && other.foregroundColor == foregroundColor
         && other.overlayColor == overlayColor
         && other.shadowColor == shadowColor
+        && other.surfaceTintColor == surfaceTintColor
         && other.elevation == elevation
         && other.padding == padding
         && other.minimumSize == minimumSize
@@ -395,6 +427,7 @@
     properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('foregroundColor', foregroundColor, defaultValue: null));
     properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('overlayColor', overlayColor, defaultValue: null));
     properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('shadowColor', shadowColor, defaultValue: null));
+    properties.add(DiagnosticsProperty<MaterialStateProperty<Color?>>('surfaceTintColor', surfaceTintColor, defaultValue: null));
     properties.add(DiagnosticsProperty<MaterialStateProperty<double?>>('elevation', elevation, defaultValue: null));
     properties.add(DiagnosticsProperty<MaterialStateProperty<EdgeInsetsGeometry?>>('padding', padding, defaultValue: null));
     properties.add(DiagnosticsProperty<MaterialStateProperty<Size?>>('minimumSize', minimumSize, defaultValue: null));
@@ -421,6 +454,7 @@
       foregroundColor:  _lerpProperties<Color?>(a?.foregroundColor, b?.foregroundColor, t, Color.lerp),
       overlayColor: _lerpProperties<Color?>(a?.overlayColor, b?.overlayColor, t, Color.lerp),
       shadowColor: _lerpProperties<Color?>(a?.shadowColor, b?.shadowColor, t, Color.lerp),
+      surfaceTintColor: _lerpProperties<Color?>(a?.surfaceTintColor, b?.surfaceTintColor, t, Color.lerp),
       elevation: _lerpProperties<double?>(a?.elevation, b?.elevation, t, lerpDouble),
       padding:  _lerpProperties<EdgeInsetsGeometry?>(a?.padding, b?.padding, t, EdgeInsetsGeometry.lerp),
       minimumSize: _lerpProperties<Size?>(a?.minimumSize, b?.minimumSize, t, Size.lerp),
diff --git a/packages/flutter/lib/src/material/button_style_button.dart b/packages/flutter/lib/src/material/button_style_button.dart
index 385fd22..c30480b 100644
--- a/packages/flutter/lib/src/material/button_style_button.dart
+++ b/packages/flutter/lib/src/material/button_style_button.dart
@@ -247,6 +247,7 @@
     Color? resolvedBackgroundColor = resolve<Color?>((ButtonStyle? style) => style?.backgroundColor);
     final Color? resolvedForegroundColor = resolve<Color?>((ButtonStyle? style) => style?.foregroundColor);
     final Color? resolvedShadowColor = resolve<Color?>((ButtonStyle? style) => style?.shadowColor);
+    final Color? resolvedSurfaceTintColor = resolve<Color?>((ButtonStyle? style) => style?.surfaceTintColor);
     final EdgeInsetsGeometry? resolvedPadding = resolve<EdgeInsetsGeometry?>((ButtonStyle? style) => style?.padding);
     final Size? resolvedMinimumSize = resolve<Size?>((ButtonStyle? style) => style?.minimumSize);
     final Size? resolvedFixedSize = resolve<Size?>((ButtonStyle? style) => style?.fixedSize);
@@ -343,6 +344,7 @@
         shape: resolvedShape!.copyWith(side: resolvedSide),
         color: resolvedBackgroundColor,
         shadowColor: resolvedShadowColor,
+        surfaceTintColor: resolvedSurfaceTintColor,
         type: resolvedBackgroundColor == null ? MaterialType.transparency : MaterialType.button,
         animationDuration: resolvedAnimationDuration,
         clipBehavior: widget.clipBehavior,
diff --git a/packages/flutter/lib/src/material/elevated_button.dart b/packages/flutter/lib/src/material/elevated_button.dart
index dbb3285..b01c3d6 100644
--- a/packages/flutter/lib/src/material/elevated_button.dart
+++ b/packages/flutter/lib/src/material/elevated_button.dart
@@ -148,6 +148,7 @@
     Color? onPrimary,
     Color? onSurface,
     Color? shadowColor,
+    Color? surfaceTintColor,
     double? elevation,
     TextStyle? textStyle,
     EdgeInsetsGeometry? padding,
@@ -187,6 +188,7 @@
       foregroundColor: foregroundColor,
       overlayColor: overlayColor,
       shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
+      surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
       elevation: elevationValue,
       padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
       minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
@@ -228,6 +230,8 @@
   /// The color of the [ButtonStyle.textStyle] is not used, the
   /// [ButtonStyle.foregroundColor] color is used instead.
   ///
+  /// ## Material 2 defaults
+  ///
   /// * `textStyle` - Theme.textTheme.button
   /// * `backgroundColor`
   ///   * disabled - Theme.colorScheme.onSurface(0.12)
@@ -245,7 +249,7 @@
   ///   * hovered or focused - 4
   ///   * pressed - 8
   /// * `padding`
-  ///   * textScaleFactor <= 1 - horizontal(16)
+  ///   * `textScaleFactor <= 1` - horizontal(16)
   ///   * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
   ///   * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
   ///   * `3 < textScaleFactor` - horizontal(4)
@@ -276,38 +280,75 @@
   /// outline, is null. That means that the outline is defined by the button
   /// shape's [OutlinedBorder.side]. Typically the default value of an
   /// [OutlinedBorder]'s side is [BorderSide.none], so an outline is not drawn.
+  ///
+  /// ## Material 3 defaults
+  ///
+  /// If [ThemeData.useMaterial3] is set to true the following defaults will
+  /// be used:
+  ///
+  /// * `textStyle` - Theme.textTheme.labelLarge
+  /// * `backgroundColor`
+  ///   * disabled - Theme.colorScheme.onSurface(0.12)
+  ///   * others - Theme.colorScheme.surface
+  /// * `foregroundColor`
+  ///   * disabled - Theme.colorScheme.onSurface(0.38)
+  ///   * others - Theme.colorScheme.primary
+  /// * `overlayColor`
+  ///   * hovered - Theme.colorScheme.primary(0.08)
+  ///   * focused or pressed - Theme.colorScheme.primary(0.12)
+  /// * `shadowColor` - Theme.colorScheme.shadow
+  /// * `surfaceTintColor` - Theme.colorScheme.surfaceTint
+  /// * `elevation`
+  ///   * disabled - 0
+  ///   * default - 1
+  ///   * hovered - 3
+  ///   * focused or pressed - 1
+  /// * `padding`
+  ///   * `textScaleFactor <= 1` - horizontal(16)
+  ///   * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
+  ///   * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
+  ///   * `3 < textScaleFactor` - horizontal(4)
+  /// * `minimumSize` - Size(64, 40)
+  /// * `fixedSize` - null
+  /// * `maximumSize` - Size.infinite
+  /// * `side` - null
+  /// * `shape` - StadiumBorder()
+  /// * `mouseCursor`
+  ///   * disabled - SystemMouseCursors.basic
+  ///   * others - SystemMouseCursors.click
+  /// * `visualDensity` - Theme.visualDensity
+  /// * `tapTargetSize` - Theme.materialTapTargetSize
+  /// * `animationDuration` - kThemeChangeDuration
+  /// * `enableFeedback` - true
+  /// * `alignment` - Alignment.center
+  /// * `splashFactory` - Theme.splashFactory
   @override
   ButtonStyle defaultStyleOf(BuildContext context) {
     final ThemeData theme = Theme.of(context);
     final ColorScheme colorScheme = theme.colorScheme;
 
-    final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
-      const EdgeInsets.symmetric(horizontal: 16),
-      const EdgeInsets.symmetric(horizontal: 8),
-      const EdgeInsets.symmetric(horizontal: 4),
-      MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
-    );
-
-    return styleFrom(
-      primary: colorScheme.primary,
-      onPrimary: colorScheme.onPrimary,
-      onSurface: colorScheme.onSurface,
-      shadowColor: theme.shadowColor,
-      elevation: 2,
-      textStyle: theme.textTheme.button,
-      padding: scaledPadding,
-      minimumSize: const Size(64, 36),
-      maximumSize: Size.infinite,
-      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
-      enabledMouseCursor: SystemMouseCursors.click,
-      disabledMouseCursor: SystemMouseCursors.basic,
-      visualDensity: theme.visualDensity,
-      tapTargetSize: theme.materialTapTargetSize,
-      animationDuration: kThemeChangeDuration,
-      enableFeedback: true,
-      alignment: Alignment.center,
-      splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
-    );
+    return Theme.of(context).useMaterial3
+      ? _TokenDefaultsM3(context)
+      : styleFrom(
+          primary: colorScheme.primary,
+          onPrimary: colorScheme.onPrimary,
+          onSurface: colorScheme.onSurface,
+          shadowColor: theme.shadowColor,
+          elevation: 2,
+          textStyle: theme.textTheme.button,
+          padding: _scaledPadding(context),
+          minimumSize: const Size(64, 36),
+          maximumSize: Size.infinite,
+          shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
+          enabledMouseCursor: SystemMouseCursors.click,
+          disabledMouseCursor: SystemMouseCursors.basic,
+          visualDensity: theme.visualDensity,
+          tapTargetSize: theme.materialTapTargetSize,
+          animationDuration: kThemeChangeDuration,
+          enableFeedback: true,
+          alignment: Alignment.center,
+          splashFactory: InkRipple.splashFactory,
+        );
   }
 
   /// Returns the [ElevatedButtonThemeData.style] of the closest
@@ -318,6 +359,15 @@
   }
 }
 
+EdgeInsetsGeometry _scaledPadding(BuildContext context) {
+  return ButtonStyleButton.scaledPadding(
+    const EdgeInsets.symmetric(horizontal: 16),
+    const EdgeInsets.symmetric(horizontal: 8),
+    const EdgeInsets.symmetric(horizontal: 4),
+    MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+  );
+}
+
 @immutable
 class _ElevatedButtonDefaultBackground extends MaterialStateProperty<Color?> with Diagnosticable {
   _ElevatedButtonDefaultBackground(this.primary, this.onSurface);
@@ -457,3 +507,115 @@
     );
   }
 }
+
+// BEGIN GENERATED TOKEN PROPERTIES
+
+// Generated code to the end of this file. Do not edit by hand.
+// These defaults are generated from the Material Design Token
+// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Generated version v0_92
+class _TokenDefaultsM3 extends ButtonStyle {
+  _TokenDefaultsM3(this.context)
+   : super(
+       animationDuration: kThemeChangeDuration,
+       enableFeedback: true,
+       alignment: Alignment.center,
+     );
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override
+  MaterialStateProperty<TextStyle?> get textStyle =>
+    MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
+
+  @override
+  MaterialStateProperty<Color?>? get backgroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return _colors.onSurface.withOpacity(0.12);
+      return _colors.surface;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get foregroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return _colors.onSurface.withOpacity(0.38);
+      return _colors.primary;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get overlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.hovered))
+        return _colors.primary.withOpacity(0.08);
+      if (states.contains(MaterialState.focused))
+        return _colors.primary.withOpacity(0.12);
+      if (states.contains(MaterialState.pressed))
+        return _colors.primary.withOpacity(0.12);
+      return null;
+    });
+
+  @override
+  MaterialStateProperty<Color>? get shadowColor =>
+    ButtonStyleButton.allOrNull<Color>(_colors.shadow);
+
+  @override
+  MaterialStateProperty<Color>? get surfaceTintColor =>
+    ButtonStyleButton.allOrNull<Color>(_colors.surfaceTint);
+
+  @override
+  MaterialStateProperty<double>? get elevation =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return 0.0;
+      if (states.contains(MaterialState.hovered))
+        return 3.0;
+      if (states.contains(MaterialState.focused))
+        return 1.0;
+      if (states.contains(MaterialState.pressed))
+        return 1.0;
+      return 1.0;
+    });
+
+  @override
+  MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
+    ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
+
+  @override
+  MaterialStateProperty<Size>? get minimumSize =>
+    ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
+
+  // No default fixedSize
+
+  @override
+  MaterialStateProperty<Size>? get maximumSize =>
+    ButtonStyleButton.allOrNull<Size>(Size.infinite);
+
+  // No default side
+
+  @override
+  MaterialStateProperty<OutlinedBorder>? get shape =>
+    ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
+
+  @override
+  MaterialStateProperty<MouseCursor?>? get mouseCursor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return SystemMouseCursors.basic;
+      return SystemMouseCursors.click;
+    });
+
+  @override
+  VisualDensity? get visualDensity => Theme.of(context).visualDensity;
+
+  @override
+  MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
+
+  @override
+  InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
+}
+
+// END GENERATED TOKEN PROPERTIES
diff --git a/packages/flutter/lib/src/material/outlined_button.dart b/packages/flutter/lib/src/material/outlined_button.dart
index 0e233e6..e6fbdcd 100644
--- a/packages/flutter/lib/src/material/outlined_button.dart
+++ b/packages/flutter/lib/src/material/outlined_button.dart
@@ -146,6 +146,7 @@
     Color? onSurface,
     Color? backgroundColor,
     Color? shadowColor,
+    Color? surfaceTintColor,
     double? elevation,
     TextStyle? textStyle,
     EdgeInsetsGeometry? padding,
@@ -179,6 +180,7 @@
       backgroundColor: ButtonStyleButton.allOrNull<Color>(backgroundColor),
       overlayColor: overlayColor,
       shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
+      surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
       elevation: ButtonStyleButton.allOrNull<double>(elevation),
       padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
       minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
@@ -219,6 +221,8 @@
   /// The color of the [ButtonStyle.textStyle] is not used, the
   /// [ButtonStyle.foregroundColor] is used instead.
   ///
+  /// ## Material 2 defaults
+  ///
   /// * `textStyle` - Theme.textTheme.button
   /// * `backgroundColor` - transparent
   /// * `foregroundColor`
@@ -248,41 +252,75 @@
   /// * `enableFeedback` - true
   /// * `alignment` - Alignment.center
   /// * `splashFactory` - InkRipple.splashFactory
+  ///
+  /// ## Material 3 defaults
+  ///
+  /// If [ThemeData.useMaterial3] is set to true the following defaults will
+  /// be used:
+  ///
+  /// * `textStyle` - Theme.textTheme.labelLarge
+  /// * `backgroundColor` - transparent
+  /// * `foregroundColor`
+  ///   * disabled - Theme.colorScheme.onSurface(0.38)
+  ///   * others - Theme.colorScheme.primary
+  /// * `overlayColor`
+  ///   * hovered - Theme.colorScheme.primary(0.08)
+  ///   * focused or pressed - Theme.colorScheme.primary(0.12)
+  ///   * others - null
+  /// * `shadowColor` - null
+  /// * `surfaceTintColor` - null
+  /// * `elevation` - 0
+  /// * `padding`
+  ///   * `textScaleFactor <= 1` - horizontal(16)
+  ///   * `1 < textScaleFactor <= 2` - lerp(horizontal(16), horizontal(8))
+  ///   * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
+  ///   * `3 < textScaleFactor` - horizontal(4)
+  /// * `minimumSize` - Size(64, 40)
+  /// * `fixedSize` - null
+  /// * `maximumSize` - Size.infinite
+  /// * `side`
+  ///   * disabled - BorderSide(color: Theme.colorScheme.onSurface(0.12))
+  ///   * others - BorderSide(color: Theme.colorScheme.outline)
+  /// * `shape` - StadiumBorder()
+  /// * `mouseCursor`
+  ///   * disabled - SystemMouseCursors.basic
+  ///   * others - SystemMouseCursors.click
+  /// * `visualDensity` - theme.visualDensity
+  /// * `tapTargetSize` - theme.materialTapTargetSize
+  /// * `animationDuration` - kThemeChangeDuration
+  /// * `enableFeedback` - true
+  /// * `alignment` - Alignment.center
+  /// * `splashFactory` - Theme.splashFactory
   @override
   ButtonStyle defaultStyleOf(BuildContext context) {
     final ThemeData theme = Theme.of(context);
     final ColorScheme colorScheme = theme.colorScheme;
 
-    final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
-      const EdgeInsets.symmetric(horizontal: 16),
-      const EdgeInsets.symmetric(horizontal: 8),
-      const EdgeInsets.symmetric(horizontal: 4),
-      MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
-    );
-
-    return styleFrom(
-      primary: colorScheme.primary,
-      onSurface: colorScheme.onSurface,
-      backgroundColor: Colors.transparent,
-      shadowColor: theme.shadowColor,
-      elevation: 0,
-      textStyle: theme.textTheme.button,
-      padding: scaledPadding,
-      minimumSize: const Size(64, 36),
-      maximumSize: Size.infinite,
-      side: BorderSide(
-        color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
-      ),
-      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
-      enabledMouseCursor: SystemMouseCursors.click,
-      disabledMouseCursor: SystemMouseCursors.basic,
-      visualDensity: theme.visualDensity,
-      tapTargetSize: theme.materialTapTargetSize,
-      animationDuration: kThemeChangeDuration,
-      enableFeedback: true,
-      alignment: Alignment.center,
-      splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
-    );
+    return Theme.of(context).useMaterial3
+      ? _TokenDefaultsM3(context)
+      : styleFrom(
+          primary: colorScheme.primary,
+          onSurface: colorScheme.onSurface,
+          backgroundColor: Colors.transparent,
+          shadowColor: theme.shadowColor,
+          elevation: 0,
+          textStyle: theme.textTheme.button,
+          padding: _scaledPadding(context),
+          minimumSize: const Size(64, 36),
+          maximumSize: Size.infinite,
+          side: BorderSide(
+            color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12),
+          ),
+          shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
+          enabledMouseCursor: SystemMouseCursors.click,
+          disabledMouseCursor: SystemMouseCursors.basic,
+          visualDensity: theme.visualDensity,
+          tapTargetSize: theme.materialTapTargetSize,
+          animationDuration: kThemeChangeDuration,
+          enableFeedback: true,
+          alignment: Alignment.center,
+          splashFactory: InkRipple.splashFactory,
+        );
   }
 
   @override
@@ -291,6 +329,15 @@
   }
 }
 
+EdgeInsetsGeometry _scaledPadding(BuildContext context) {
+  return ButtonStyleButton.scaledPadding(
+    const EdgeInsets.symmetric(horizontal: 16),
+    const EdgeInsets.symmetric(horizontal: 8),
+    const EdgeInsets.symmetric(horizontal: 4),
+    MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+  );
+}
+
 @immutable
 class _OutlinedButtonDefaultForeground extends MaterialStateProperty<Color?>  with Diagnosticable {
   _OutlinedButtonDefaultForeground(this.primary, this.onSurface);
@@ -382,3 +429,103 @@
     );
   }
 }
+
+// BEGIN GENERATED TOKEN PROPERTIES
+
+// Generated code to the end of this file. Do not edit by hand.
+// These defaults are generated from the Material Design Token
+// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Generated version v0_92
+class _TokenDefaultsM3 extends ButtonStyle {
+  _TokenDefaultsM3(this.context)
+   : super(
+       animationDuration: kThemeChangeDuration,
+       enableFeedback: true,
+       alignment: Alignment.center,
+     );
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override
+  MaterialStateProperty<TextStyle?> get textStyle =>
+    MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
+
+  @override
+  MaterialStateProperty<Color?>? get backgroundColor =>
+    ButtonStyleButton.allOrNull<Color>(Colors.transparent);
+
+  @override
+  MaterialStateProperty<Color?>? get foregroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return _colors.onSurface.withOpacity(0.38);
+      return _colors.primary;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get overlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.hovered))
+        return _colors.primary.withOpacity(0.08);
+      if (states.contains(MaterialState.focused))
+        return _colors.primary.withOpacity(0.12);
+      if (states.contains(MaterialState.pressed))
+        return _colors.primary.withOpacity(0.12);
+      return null;
+    });
+
+  // No default shadow color
+
+  // No default surface tint color
+
+  @override
+  MaterialStateProperty<double>? get elevation =>
+    ButtonStyleButton.allOrNull<double>(0.0);
+
+  @override
+  MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
+    ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
+
+  @override
+  MaterialStateProperty<Size>? get minimumSize =>
+    ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
+
+  // No default fixedSize
+
+  @override
+  MaterialStateProperty<Size>? get maximumSize =>
+    ButtonStyleButton.allOrNull<Size>(Size.infinite);
+
+  @override
+  MaterialStateProperty<BorderSide>? get side =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+    if (states.contains(MaterialState.disabled))
+      return BorderSide(color: _colors.onSurface.withOpacity(0.12));
+    return BorderSide(color: _colors.outline);
+  });
+
+  @override
+  MaterialStateProperty<OutlinedBorder>? get shape =>
+    ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
+
+  @override
+  MaterialStateProperty<MouseCursor?>? get mouseCursor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return SystemMouseCursors.basic;
+      return SystemMouseCursors.click;
+    });
+
+  @override
+  VisualDensity? get visualDensity => Theme.of(context).visualDensity;
+
+  @override
+  MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
+
+  @override
+  InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
+}
+
+// END GENERATED TOKEN PROPERTIES
diff --git a/packages/flutter/lib/src/material/text_button.dart b/packages/flutter/lib/src/material/text_button.dart
index 92fac91..2caa127 100644
--- a/packages/flutter/lib/src/material/text_button.dart
+++ b/packages/flutter/lib/src/material/text_button.dart
@@ -147,6 +147,7 @@
     Color? onSurface,
     Color? backgroundColor,
     Color? shadowColor,
+    Color? surfaceTintColor,
     double? elevation,
     TextStyle? textStyle,
     EdgeInsetsGeometry? padding,
@@ -180,6 +181,7 @@
       foregroundColor: foregroundColor,
       overlayColor: overlayColor,
       shadowColor: ButtonStyleButton.allOrNull<Color>(shadowColor),
+      surfaceTintColor: ButtonStyleButton.allOrNull<Color>(surfaceTintColor),
       elevation: ButtonStyleButton.allOrNull<double>(elevation),
       padding: ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(padding),
       minimumSize: ButtonStyleButton.allOrNull<Size>(minimumSize),
@@ -223,6 +225,8 @@
   /// The color of the [ButtonStyle.textStyle] is not used, the
   /// [ButtonStyle.foregroundColor] color is used instead.
   ///
+  /// ## Material 2 defaults
+  ///
   /// * `textStyle` - Theme.textTheme.button
   /// * `backgroundColor` - transparent
   /// * `foregroundColor`
@@ -264,38 +268,70 @@
   /// outline, is null. That means that the outline is defined by the button
   /// shape's [OutlinedBorder.side]. Typically the default value of an
   /// [OutlinedBorder]'s side is [BorderSide.none], so an outline is not drawn.
+  ///
+  /// ## Material 3 defaults
+  ///
+  /// If [ThemeData.useMaterial3] is set to true the following defaults will
+  /// be used:
+  ///
+  /// * `textStyle` - Theme.textTheme.labelLarge
+  /// * `backgroundColor` - transparent
+  /// * `foregroundColor`
+  ///   * disabled - Theme.colorScheme.onSurface(0.38)
+  ///   * others - Theme.colorScheme.primary
+  /// * `overlayColor`
+  ///   * hovered - Theme.colorScheme.primary(0.08)
+  ///   * focused or pressed - Theme.colorScheme.primary(0.12)
+  ///   * others - null
+  /// * `shadowColor` - null
+  /// * `surfaceTintColor` - null
+  /// * `elevation` - 0
+  /// * `padding`
+  ///   * `textScaleFactor <= 1` - all(8)
+  ///   * `1 < textScaleFactor <= 2` - lerp(all(8), horizontal(8))
+  ///   * `2 < textScaleFactor <= 3` - lerp(horizontal(8), horizontal(4))
+  ///   * `3 < textScaleFactor` - horizontal(4)
+  /// * `minimumSize` - Size(64, 40)
+  /// * `fixedSize` - null
+  /// * `maximumSize` - Size.infinite
+  /// * `side` - null
+  /// * `shape` - StadiumBorder()
+  /// * `mouseCursor`
+  ///   * disabled - SystemMouseCursors.basic
+  ///   * others - SystemMouseCursors.click
+  /// * `visualDensity` - theme.visualDensity
+  /// * `tapTargetSize` - theme.materialTapTargetSize
+  /// * `animationDuration` - kThemeChangeDuration
+  /// * `enableFeedback` - true
+  /// * `alignment` - Alignment.center
+  /// * `splashFactory` - Theme.splashFactory
   @override
   ButtonStyle defaultStyleOf(BuildContext context) {
     final ThemeData theme = Theme.of(context);
     final ColorScheme colorScheme = theme.colorScheme;
 
-    final EdgeInsetsGeometry scaledPadding = ButtonStyleButton.scaledPadding(
-      const EdgeInsets.all(8),
-      const EdgeInsets.symmetric(horizontal: 8),
-      const EdgeInsets.symmetric(horizontal: 4),
-      MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
-    );
-
-    return styleFrom(
-      primary: colorScheme.primary,
-      onSurface: colorScheme.onSurface,
-      backgroundColor: Colors.transparent,
-      shadowColor: theme.shadowColor,
-      elevation: 0,
-      textStyle: theme.textTheme.button,
-      padding: scaledPadding,
-      minimumSize: const Size(64, 36),
-      maximumSize: Size.infinite,
-      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
-      enabledMouseCursor: SystemMouseCursors.click,
-      disabledMouseCursor: SystemMouseCursors.basic,
-      visualDensity: theme.visualDensity,
-      tapTargetSize: theme.materialTapTargetSize,
-      animationDuration: kThemeChangeDuration,
-      enableFeedback: true,
-      alignment: Alignment.center,
-      splashFactory: theme.useMaterial3 ? theme.splashFactory : InkRipple.splashFactory,
-    );
+    return Theme.of(context).useMaterial3
+      ? _TokenDefaultsM3(context)
+      : styleFrom(
+          primary: colorScheme.primary,
+          onSurface: colorScheme.onSurface,
+          backgroundColor: Colors.transparent,
+          shadowColor: theme.shadowColor,
+          elevation: 0,
+          textStyle: theme.textTheme.button,
+          padding: _scaledPadding(context),
+          minimumSize: const Size(64, 36),
+          maximumSize: Size.infinite,
+          shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))),
+          enabledMouseCursor: SystemMouseCursors.click,
+          disabledMouseCursor: SystemMouseCursors.basic,
+          visualDensity: theme.visualDensity,
+          tapTargetSize: theme.materialTapTargetSize,
+          animationDuration: kThemeChangeDuration,
+          enableFeedback: true,
+          alignment: Alignment.center,
+          splashFactory: InkRipple.splashFactory,
+        );
   }
 
   /// Returns the [TextButtonThemeData.style] of the closest
@@ -306,6 +342,15 @@
   }
 }
 
+EdgeInsetsGeometry _scaledPadding(BuildContext context) {
+  return ButtonStyleButton.scaledPadding(
+    const EdgeInsets.all(8),
+    const EdgeInsets.symmetric(horizontal: 8),
+    const EdgeInsets.symmetric(horizontal: 4),
+    MediaQuery.maybeOf(context)?.textScaleFactor ?? 1,
+  );
+}
+
 @immutable
 class _TextButtonDefaultForeground extends MaterialStateProperty<Color?> {
   _TextButtonDefaultForeground(this.primary, this.onSurface);
@@ -424,3 +469,97 @@
     );
   }
 }
+
+// BEGIN GENERATED TOKEN PROPERTIES
+
+// Generated code to the end of this file. Do not edit by hand.
+// These defaults are generated from the Material Design Token
+// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Generated version v0_92
+class _TokenDefaultsM3 extends ButtonStyle {
+  _TokenDefaultsM3(this.context)
+   : super(
+       animationDuration: kThemeChangeDuration,
+       enableFeedback: true,
+       alignment: Alignment.center,
+     );
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override
+  MaterialStateProperty<TextStyle?> get textStyle =>
+    MaterialStateProperty.all<TextStyle?>(Theme.of(context).textTheme.labelLarge);
+
+  @override
+  MaterialStateProperty<Color?>? get backgroundColor =>
+    ButtonStyleButton.allOrNull<Color>(Colors.transparent);
+
+  @override
+  MaterialStateProperty<Color?>? get foregroundColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return _colors.onSurface.withOpacity(0.38);
+      return _colors.primary;
+    });
+
+  @override
+  MaterialStateProperty<Color?>? get overlayColor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.hovered))
+        return _colors.primary.withOpacity(0.08);
+      if (states.contains(MaterialState.focused))
+        return _colors.primary.withOpacity(0.12);
+      if (states.contains(MaterialState.pressed))
+        return _colors.primary.withOpacity(0.12);
+      return null;
+    });
+
+  // No default shadow color
+
+  // No default surface tint color
+
+  @override
+  MaterialStateProperty<double>? get elevation =>
+    ButtonStyleButton.allOrNull<double>(0.0);
+
+  @override
+  MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
+    ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
+
+  @override
+  MaterialStateProperty<Size>? get minimumSize =>
+    ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0));
+
+  // No default fixedSize
+
+  @override
+  MaterialStateProperty<Size>? get maximumSize =>
+    ButtonStyleButton.allOrNull<Size>(Size.infinite);
+
+  // No default side
+
+  @override
+  MaterialStateProperty<OutlinedBorder>? get shape =>
+    ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder());
+
+  @override
+  MaterialStateProperty<MouseCursor?>? get mouseCursor =>
+    MaterialStateProperty.resolveWith((Set<MaterialState> states) {
+      if (states.contains(MaterialState.disabled))
+        return SystemMouseCursors.basic;
+      return SystemMouseCursors.click;
+    });
+
+  @override
+  VisualDensity? get visualDensity => Theme.of(context).visualDensity;
+
+  @override
+  MaterialTapTargetSize? get tapTargetSize => Theme.of(context).materialTapTargetSize;
+
+  @override
+  InteractiveInkFeatureFactory? get splashFactory => Theme.of(context).splashFactory;
+}
+
+// END GENERATED TOKEN PROPERTIES
diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart
index b7f79df..95b445a 100644
--- a/packages/flutter/lib/src/material/theme_data.dart
+++ b/packages/flutter/lib/src/material/theme_data.dart
@@ -1224,21 +1224,25 @@
   /// {@endtemplate}
   final VisualDensity visualDensity;
 
-  /// A temporary flag used to opt-in to new Material 3 features.
+  /// A temporary flag used to opt-in to Material 3 features.
   ///
   /// If true, then components that have been migrated to Material 3 will
-  /// start using new colors, typography and other features of Material 3.
+  /// use new colors, typography and other features of Material 3.
   /// If false, they will use the Material 2 look and feel.
   ///
   /// If a [ThemeData] is constructed with [useMaterial3] set to true, then
   /// some properties will get special defaults. However, just copying a [ThemeData]
   /// with [useMaterial3] set to true will not change any of these properties in the
   /// resulting [ThemeData]. These properties are:
-  /// | Property | [useMaterial3] default | fallback default |
-  /// |:---|:---|:---|
-  /// | [typography] | [Typography.material2021] | [Typography.material2014] |
-  /// | [splashFactory] | [InkSparkle]* | [InkSplash] |
-  /// *if and only if the target platform is Android and the app is not running on the web.
+  /// <style>table,td,th { border-collapse: collapse; padding: 0.45em; } td { border: 1px solid }</style>
+  ///
+  /// | Property        | Material 3 default           | Fallback default          |
+  /// | :-------------- | :--------------------------- | :------------------------ |
+  /// | [typography]    | [Typography.material2021]    | [Typography.material2014] |
+  /// | [splashFactory] | [InkSparkle]* or [InkRipple] | [InkSplash]               |
+  ///
+  /// \* if and only if the target platform is Android and the app is not
+  /// running on the web, otherwise it will fallback to [InkRipple].
   ///
   /// During the migration to Material 3, turning this on may yield
   /// inconsistent look and feel in your app. Some components will be migrated
@@ -1255,12 +1259,15 @@
   ///   * [AlertDialog]
   ///   * [Card]
   ///   * [Dialog]
+  ///   * [ElevatedButton]
   ///   * [FloatingActionButton]
   ///   * [Material]
   ///   * [NavigationBar]
   ///   * [NavigationRail]
+  ///   * [OutlinedButton]
   ///   * [StretchingOverscrollIndicator], replacing the
   ///     [GlowingOverscrollIndicator]
+  ///   * [TextButton]
   ///
   /// See also:
   ///
diff --git a/packages/flutter/lib/src/scheduler/binding.dart b/packages/flutter/lib/src/scheduler/binding.dart
index eb1eb76..1be5607 100644
--- a/packages/flutter/lib/src/scheduler/binding.dart
+++ b/packages/flutter/lib/src/scheduler/binding.dart
@@ -825,6 +825,7 @@
         debugPrintStack(label: 'scheduleForcedFrame() called. Current phase is $schedulerPhase.');
       return true;
     }());
+    ensureFrameCallbacksRegistered();
     platformDispatcher.scheduleFrame();
     _hasScheduledFrame = true;
   }
diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart
index ac3673e..c6382b9 100644
--- a/packages/flutter/lib/src/widgets/framework.dart
+++ b/packages/flutter/lib/src/widgets/framework.dart
@@ -3793,33 +3793,35 @@
       );
     }
 
-    final Key? key = newWidget.key;
-    if (key is GlobalKey) {
-      final Element? newChild = _retakeInactiveElement(key, newWidget);
-      if (newChild != null) {
-        assert(newChild._parent == null);
-        assert(() {
-          _debugCheckForCycles(newChild);
-          return true;
-        }());
-        newChild._activateWithParent(this, newSlot);
-        final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
-        assert(newChild == updatedChild);
-        return updatedChild!;
+    try {
+      final Key? key = newWidget.key;
+      if (key is GlobalKey) {
+        final Element? newChild = _retakeInactiveElement(key, newWidget);
+        if (newChild != null) {
+          assert(newChild._parent == null);
+          assert(() {
+            _debugCheckForCycles(newChild);
+            return true;
+          }());
+          newChild._activateWithParent(this, newSlot);
+          final Element? updatedChild = updateChild(newChild, newWidget, newSlot);
+          assert(newChild == updatedChild);
+          return updatedChild!;
+        }
       }
+      final Element newChild = newWidget.createElement();
+      assert(() {
+        _debugCheckForCycles(newChild);
+        return true;
+      }());
+      newChild.mount(this, newSlot);
+      assert(newChild._lifecycleState == _ElementLifecycle.active);
+
+      return newChild;
+    } finally {
+      if (isTimelineTracked)
+        Timeline.finishSync();
     }
-    final Element newChild = newWidget.createElement();
-    assert(() {
-      _debugCheckForCycles(newChild);
-      return true;
-    }());
-    newChild.mount(this, newSlot);
-    assert(newChild._lifecycleState == _ElementLifecycle.active);
-
-    if (isTimelineTracked)
-      Timeline.finishSync();
-
-    return newChild;
   }
 
   void _debugCheckForCycles(Element newChild) {
diff --git a/packages/flutter/test/material/button_style_test.dart b/packages/flutter/test/material/button_style_test.dart
index b9a2640..32afc9b 100644
--- a/packages/flutter/test/material/button_style_test.dart
+++ b/packages/flutter/test/material/button_style_test.dart
@@ -20,6 +20,8 @@
     expect(style.backgroundColor, null);
     expect(style.foregroundColor, null);
     expect(style.overlayColor, null);
+    expect(style.shadowColor, null);
+    expect(style.surfaceTintColor, null);
     expect(style.elevation, null);
     expect(style.padding, null);
     expect(style.minimumSize, null);
@@ -53,10 +55,12 @@
       backgroundColor: MaterialStateProperty.all<Color>(const Color(0xfffffff1)),
       foregroundColor: MaterialStateProperty.all<Color>(const Color(0xfffffff2)),
       overlayColor: MaterialStateProperty.all<Color>(const Color(0xfffffff3)),
+      shadowColor: MaterialStateProperty.all<Color>(const Color(0xfffffff4)),
+      surfaceTintColor: MaterialStateProperty.all<Color>(const Color(0xfffffff5)),
       elevation: MaterialStateProperty.all<double>(1.5),
       padding: MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(1.0)),
       minimumSize: MaterialStateProperty.all<Size>(const Size(1.0, 2.0)),
-      side: MaterialStateProperty.all<BorderSide>(const BorderSide(width: 4.0, color: Color(0xfffffff4))),
+      side: MaterialStateProperty.all<BorderSide>(const BorderSide(width: 4.0, color: Color(0xfffffff6))),
       maximumSize: MaterialStateProperty.all<Size>(const Size(100.0, 200.0)),
       shape: MaterialStateProperty.all<OutlinedBorder>(const StadiumBorder()),
       mouseCursor: MaterialStateProperty.all<MouseCursor>(SystemMouseCursors.forbidden),
@@ -75,11 +79,13 @@
       'backgroundColor: MaterialStateProperty.all(Color(0xfffffff1))',
       'foregroundColor: MaterialStateProperty.all(Color(0xfffffff2))',
       'overlayColor: MaterialStateProperty.all(Color(0xfffffff3))',
+      'shadowColor: MaterialStateProperty.all(Color(0xfffffff4))',
+      'surfaceTintColor: MaterialStateProperty.all(Color(0xfffffff5))',
       'elevation: MaterialStateProperty.all(1.5)',
       'padding: MaterialStateProperty.all(EdgeInsets.all(1.0))',
       'minimumSize: MaterialStateProperty.all(Size(1.0, 2.0))',
       'maximumSize: MaterialStateProperty.all(Size(100.0, 200.0))',
-      'side: MaterialStateProperty.all(BorderSide(Color(0xfffffff4), 4.0, BorderStyle.solid))',
+      'side: MaterialStateProperty.all(BorderSide(Color(0xfffffff6), 4.0, BorderStyle.solid))',
       'shape: MaterialStateProperty.all(StadiumBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none)))',
       'mouseCursor: MaterialStateProperty.all(SystemMouseCursor(forbidden))',
       'tapTargetSize: shrinkWrap',
@@ -93,6 +99,8 @@
     final MaterialStateProperty<Color> backgroundColor =  MaterialStateProperty.all<Color>(const Color(0xfffffff1));
     final MaterialStateProperty<Color> foregroundColor =  MaterialStateProperty.all<Color>(const Color(0xfffffff2));
     final MaterialStateProperty<Color> overlayColor =  MaterialStateProperty.all<Color>(const Color(0xfffffff3));
+    final MaterialStateProperty<Color> shadowColor =  MaterialStateProperty.all<Color>(const Color(0xfffffff4));
+    final MaterialStateProperty<Color> surfaceTintColor =  MaterialStateProperty.all<Color>(const Color(0xfffffff5));
     final MaterialStateProperty<double> elevation =  MaterialStateProperty.all<double>(1);
     final MaterialStateProperty<EdgeInsets> padding = MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(1));
     final MaterialStateProperty<Size> minimumSize = MaterialStateProperty.all<Size>(const Size(1, 2));
@@ -111,6 +119,8 @@
       backgroundColor: backgroundColor,
       foregroundColor: foregroundColor,
       overlayColor: overlayColor,
+      shadowColor: shadowColor,
+      surfaceTintColor: surfaceTintColor,
       elevation: elevation,
       padding: padding,
       minimumSize: minimumSize,
@@ -132,6 +142,8 @@
         backgroundColor: backgroundColor,
         foregroundColor: foregroundColor,
         overlayColor: overlayColor,
+        shadowColor: shadowColor,
+        surfaceTintColor: surfaceTintColor,
         elevation: elevation,
         padding: padding,
         minimumSize: minimumSize,
diff --git a/packages/flutter/test/material/elevated_button_test.dart b/packages/flutter/test/material/elevated_button_test.dart
index 12afdeb..3478826 100644
--- a/packages/flutter/test/material/elevated_button_test.dart
+++ b/packages/flutter/test/material/elevated_button_test.dart
@@ -14,11 +14,13 @@
 void main() {
   testWidgets('ElevatedButton, ElevatedButton.icon defaults', (WidgetTester tester) async {
     const ColorScheme colorScheme = ColorScheme.light();
+    final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
+    final bool material3 = theme.useMaterial3;
 
     // Enabled ElevatedButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: ElevatedButton(
             onPressed: () { },
@@ -39,11 +41,13 @@
     expect(material.borderOnForeground, true);
     expect(material.borderRadius, null);
     expect(material.clipBehavior, Clip.none);
-    expect(material.color, colorScheme.primary);
-    expect(material.elevation, 2);
+    expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
+    expect(material.elevation, material3 ? 1: 2);
     expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
-    expect(material.textStyle!.color, colorScheme.onPrimary);
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
+    expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
     expect(material.textStyle!.fontWeight, FontWeight.w500);
@@ -56,8 +60,13 @@
     final TestGesture gesture = await tester.startGesture(center);
     await tester.pump(); // start the splash animation
     await tester.pump(const Duration(milliseconds: 100)); // splash is underway
-    final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
-    expect(inkFeatures, paints..circle(color: colorScheme.onPrimary.withAlpha(0x3d))); // splash color is onPrimary(0.24)
+
+    // Material 3 uses the InkSparkle which uses a shader, so we can't capture
+    // the effect with paint methods.
+    if (!material3) {
+      final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+      expect(inkFeatures, paints..circle(color: colorScheme.onPrimary.withOpacity(0.24)));
+    }
 
     // Only elevation changes when enabled and pressed.
     material = tester.widget<Material>(buttonMaterial);
@@ -65,11 +74,13 @@
     expect(material.borderOnForeground, true);
     expect(material.borderRadius, null);
     expect(material.clipBehavior, Clip.none);
-    expect(material.color, colorScheme.primary);
-    expect(material.elevation, 8);
+    expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
+    expect(material.elevation, material3 ? 1 : 8);
     expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
-    expect(material.textStyle!.color, colorScheme.onPrimary);
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
+    expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
     expect(material.textStyle!.fontWeight, FontWeight.w500);
@@ -82,7 +93,7 @@
     final Key iconButtonKey = UniqueKey();
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: ElevatedButton.icon(
             key: iconButtonKey,
@@ -104,11 +115,13 @@
     expect(material.borderOnForeground, true);
     expect(material.borderRadius, null);
     expect(material.clipBehavior, Clip.none);
-    expect(material.color, colorScheme.primary);
-    expect(material.elevation, 2);
+    expect(material.color, material3 ? colorScheme.onPrimary : colorScheme.primary);
+    expect(material.elevation, material3? 1 : 2);
     expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
-    expect(material.textStyle!.color, colorScheme.onPrimary);
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
+    expect(material.textStyle!.color, material3 ? colorScheme.primary : colorScheme.onPrimary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
     expect(material.textStyle!.fontWeight, FontWeight.w500);
@@ -117,7 +130,7 @@
     // Disabled ElevatedButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: const Center(
           child: ElevatedButton(
             onPressed: null,
@@ -138,7 +151,9 @@
     expect(material.color, colorScheme.onSurface.withOpacity(0.12));
     expect(material.elevation, 0.0);
     expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
     expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
@@ -770,6 +785,9 @@
     Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
       return tester.pumpWidget(
         MaterialApp(
+          // Test was setup using fonts from Material 2, so make sure we always
+          // test against englishLike2014.
+          theme: ThemeData(textTheme: Typography.englishLike2014),
           home: Directionality(
             textDirection: TextDirection.rtl,
             child: Center(
@@ -961,7 +979,15 @@
           testWidgets(testName, (WidgetTester tester) async {
             await tester.pumpWidget(
               MaterialApp(
-                theme: ThemeData.from(colorScheme: const ColorScheme.light()),
+                theme: ThemeData(
+                  colorScheme: const ColorScheme.light(),
+                  // Force Material 2 defaults for the typography and size
+                  // default values as the test was designed against these settings.
+                  textTheme: Typography.englishLike2014,
+                  elevatedButtonTheme: ElevatedButtonThemeData(
+                    style: ElevatedButton.styleFrom(minimumSize: const Size(64, 36)),
+                  ),
+                ),
                 home: Builder(
                   builder: (BuildContext context) {
                     return MediaQuery(
@@ -1137,7 +1163,7 @@
 
     Widget buildFrame({ required bool enabled }) {
       return MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: ThemeData.from(colorScheme: colorScheme, useMaterial3: false),
         home: Center(
           child: ElevatedButton(
             onPressed: enabled ? () { } : null,
@@ -1181,23 +1207,29 @@
     const Color borderColor = Color(0xff4caf50);
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: const ColorScheme.light()),
+        theme: ThemeData(colorScheme: const ColorScheme.light(), textTheme: Typography.englishLike2014, useMaterial3: false),
         home: Center(
           child: ElevatedButton(
             style: ElevatedButton.styleFrom(
               shape: const RoundedRectangleBorder(
                 borderRadius: BorderRadius.all(Radius.circular(16)),
-                side: BorderSide(width: 4, color: borderColor),
+                side: BorderSide(width: 10, color: borderColor),
               ),
+              minimumSize: const Size(64, 36),
             ),
-            onPressed: () { },
+            onPressed: () {},
             child: const Text('button'),
           ),
         ),
       ),
     );
 
-    expect(find.byType(ElevatedButton), paints ..path(strokeWidth: 4) ..drrect(color: borderColor));
+    expect(find.byType(ElevatedButton), paints ..drrect(
+      // Outer and inner rect that give the outline a width of 10.
+      outer: RRect.fromLTRBR(0.0, 0.0, 116.0, 36.0, const Radius.circular(16)),
+      inner: RRect.fromLTRBR(10.0, 10.0, 106.0, 26.0, const Radius.circular(16 - 10)),
+      color: borderColor)
+    );
   });
 
   testWidgets('Fixed size ElevatedButtons', (WidgetTester tester) async {
@@ -1261,8 +1293,8 @@
       await tester.pumpAndSettle();
     }
 
-    // Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
-    await tester.pumpWidget(buildFrame());
+    // InkRipple.splashFactory, one splash circle drawn.
+    await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
     {
       final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
       final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
@@ -1386,6 +1418,7 @@
 
     await tester.pumpWidget(
       MaterialApp(
+        theme: ThemeData(textTheme: Typography.englishLike2014),
         home: Scaffold(
           body: Center(
             child: Column(
diff --git a/packages/flutter/test/material/outlined_button_test.dart b/packages/flutter/test/material/outlined_button_test.dart
index bcdbeb4..ecbf00c 100644
--- a/packages/flutter/test/material/outlined_button_test.dart
+++ b/packages/flutter/test/material/outlined_button_test.dart
@@ -14,11 +14,13 @@
 void main() {
   testWidgets('OutlinedButton, OutlinedButton.icon defaults', (WidgetTester tester) async {
     const ColorScheme colorScheme = ColorScheme.light();
+    final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
+    final bool material3 = theme.useMaterial3;
 
     // Enabled OutlinedButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: OutlinedButton(
             onPressed: () { },
@@ -40,12 +42,14 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
 
-    expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
-    RoundedRectangleBorder materialShape = material.shape! as RoundedRectangleBorder;
-    expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
-    expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
+    expect(material.shape, material3
+      ? StadiumBorder(side: BorderSide(color: colorScheme.outline))
+      : RoundedRectangleBorder(
+          side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
+          borderRadius: const BorderRadius.all(Radius.circular(4))
+        ));
 
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
@@ -60,8 +64,13 @@
     final TestGesture gesture = await tester.startGesture(center);
     await tester.pump(); // start the splash animation
     await tester.pump(const Duration(milliseconds: 100)); // splash is underway
-    final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
-    expect(inkFeatures, paints..circle(color: colorScheme.primary.withAlpha(0x1f))); // splash color is primary(0.12)
+
+    // Material 3 uses the InkSparkle which uses a shader, so we can't capture
+    // the effect with paint methods.
+    if (!material3) {
+      final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+      expect(inkFeatures, paints..circle(color: colorScheme.primary.withOpacity(0.12)));
+    }
 
     await gesture.up();
     await tester.pumpAndSettle();
@@ -73,12 +82,14 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
 
-    expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
-    materialShape = material.shape! as RoundedRectangleBorder;
-    expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
-    expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
+    expect(material.shape, material3
+      ? StadiumBorder(side: BorderSide(color: colorScheme.outline))
+      : RoundedRectangleBorder(
+          side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
+          borderRadius: const BorderRadius.all(Radius.circular(4))
+        ));
 
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
@@ -90,7 +101,7 @@
     final Key iconButtonKey = UniqueKey();
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: OutlinedButton.icon(
             key: iconButtonKey,
@@ -114,12 +125,14 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
 
-    expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
-    materialShape = material.shape! as RoundedRectangleBorder;
-    expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
-    expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
+    expect(material.shape, material3
+        ? StadiumBorder(side: BorderSide(color: colorScheme.outline))
+        : RoundedRectangleBorder(
+            side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
+            borderRadius: const BorderRadius.all(Radius.circular(4))
+        ));
 
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
@@ -130,7 +143,7 @@
     // Disabled OutlinedButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: const Center(
           child: OutlinedButton(
             onPressed: null,
@@ -147,12 +160,14 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
 
-    expect(material.shape, isInstanceOf<RoundedRectangleBorder>());
-    materialShape = material.shape! as RoundedRectangleBorder;
-    expect(materialShape.side, BorderSide(color: colorScheme.onSurface.withOpacity(0.12)));
-    expect(materialShape.borderRadius, const BorderRadius.all(Radius.circular(4.0)));
+    expect(material.shape, material3
+        ? StadiumBorder(side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)))
+        : RoundedRectangleBorder(
+        side: BorderSide(color: colorScheme.onSurface.withOpacity(0.12)),
+        borderRadius: const BorderRadius.all(Radius.circular(4))
+    ));
 
     expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
     expect(material.textStyle!.fontFamily, 'Roboto');
@@ -531,6 +546,10 @@
             child: OutlinedButton(
               style: ButtonStyle(
                 side: MaterialStateProperty.resolveWith<BorderSide>(getBorderSide),
+                // Test assumes a rounded rect for the shape
+                shape: ButtonStyleButton.allOrNull(
+                  const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4)))
+                ),
               ),
               onPressed: () {},
               focusNode: focusNode,
@@ -808,13 +827,14 @@
       return Directionality(
         textDirection: TextDirection.ltr,
         child: Theme(
-          data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap),
+          data: ThemeData(materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, textTheme: Typography.englishLike2014),
           child: Container(
             alignment: Alignment.topLeft,
             child: OutlinedButton(
               style: OutlinedButton.styleFrom(
                 shape: const RoundedRectangleBorder(), // default border radius is 0
                 backgroundColor: fillColor,
+                minimumSize: const Size(64, 36),
               ).copyWith(
                 side: MaterialStateProperty.resolveWith<BorderSide>((Set<MaterialState> states) {
                   if (states.contains(MaterialState.disabled))
@@ -964,20 +984,24 @@
 
   testWidgets('OutlinedButton scales textScaleFactor', (WidgetTester tester) async {
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(),
-          child: Center(
-            child: OutlinedButton(
-              style: ButtonStyle(
-                // Specifying minimumSize to mimic the original minimumSize for
-                // RaisedButton so that the corresponding button size matches
-                // the original version of this test.
-                minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(),
+            child: Center(
+              child: OutlinedButton(
+                style: ButtonStyle(
+                  // Specifying minimumSize to mimic the original minimumSize for
+                  // RaisedButton so that the corresponding button size matches
+                  // the original version of this test.
+                  minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
+                ),
+                onPressed: () {},
+                child: const Text('ABC'),
               ),
-              onPressed: () {},
-              child: const Text('ABC'),
             ),
           ),
         ),
@@ -989,20 +1013,24 @@
 
     // textScaleFactor expands text, but not button.
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(textScaleFactor: 1.3),
-          child: Center(
-            child: OutlinedButton(
-              style: ButtonStyle(
-                // Specifying minimumSize to mimic the original minimumSize for
-                // RaisedButton so that the corresponding button size matches
-                // the original version of this test.
-                minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(textScaleFactor: 1.3),
+            child: Center(
+              child: OutlinedButton(
+                style: ButtonStyle(
+                  // Specifying minimumSize to mimic the original minimumSize for
+                  // RaisedButton so that the corresponding button size matches
+                  // the original version of this test.
+                  minimumSize: MaterialStateProperty.all<Size>(const Size(88, 36)),
+                ),
+                onPressed: () {},
+                child: const Text('ABC'),
               ),
-              onPressed: () {},
-              child: const Text('ABC'),
             ),
           ),
         ),
@@ -1017,14 +1045,18 @@
 
     // Set text scale large enough to expand text and button.
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(textScaleFactor: 3.0),
-          child: Center(
-            child: OutlinedButton(
-              onPressed: () {},
-              child: const Text('ABC'),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(textScaleFactor: 3.0),
+            child: Center(
+              child: OutlinedButton(
+                onPressed: () {},
+                child: const Text('ABC'),
+              ),
             ),
           ),
         ),
@@ -1039,7 +1071,6 @@
     expect(tester.getSize(find.byType(Text)).height, equals(42.0));
   });
 
-
   testWidgets('OutlinedButton onPressed and onLongPress callbacks are distinctly recognized', (WidgetTester tester) async {
     bool didPressButton = false;
     bool didLongPressButton = false;
@@ -1078,11 +1109,15 @@
     Future<void> buildTest(VisualDensity visualDensity, {bool useText = false}) async {
       return tester.pumpWidget(
         MaterialApp(
+          theme: ThemeData(textTheme: Typography.englishLike2014),
           home: Directionality(
             textDirection: TextDirection.rtl,
             child: Center(
               child: OutlinedButton(
-                style: ButtonStyle(visualDensity: visualDensity),
+                style: ButtonStyle(
+                  visualDensity: visualDensity,
+                  minimumSize: ButtonStyleButton.allOrNull(const Size(64, 36)),
+                ),
                 key: key,
                 onPressed: () {},
                 child: useText
@@ -1203,7 +1238,15 @@
           testWidgets(testName, (WidgetTester tester) async {
             await tester.pumpWidget(
               MaterialApp(
-                theme: ThemeData.from(colorScheme: const ColorScheme.light()),
+                theme: ThemeData(
+                  colorScheme: const ColorScheme.light(),
+                  // Force Material 2 defaults for the typography and size
+                  // default values as the test was designed against these settings.
+                  textTheme: Typography.englishLike2014,
+                  outlinedButtonTheme: OutlinedButtonThemeData(
+                    style: OutlinedButton.styleFrom(minimumSize: const Size(64, 36)),
+                  ),
+                ),
                 home: Builder(
                   builder: (BuildContext context) {
                     return MediaQuery(
@@ -1434,8 +1477,8 @@
       await tester.pumpAndSettle();
     }
 
-    // Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
-    await tester.pumpWidget(buildFrame());
+    // InkRipple.splashFactory, one splash circle drawn.
+    await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
     {
       final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
       final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
@@ -1559,6 +1602,7 @@
 
     await tester.pumpWidget(
       MaterialApp(
+        theme: ThemeData(textTheme: Typography.englishLike2014),
         home: Scaffold(
           body: Center(
             child: Column(
diff --git a/packages/flutter/test/material/text_button_test.dart b/packages/flutter/test/material/text_button_test.dart
index ba90dc9..8da1d07 100644
--- a/packages/flutter/test/material/text_button_test.dart
+++ b/packages/flutter/test/material/text_button_test.dart
@@ -14,11 +14,13 @@
 void main() {
   testWidgets('TextButton, TextButton.icon defaults', (WidgetTester tester) async {
     const ColorScheme colorScheme = ColorScheme.light();
+    final ThemeData theme = ThemeData.from(colorScheme: colorScheme);
+    final bool material3 = theme.useMaterial3;
 
     // Enabled TextButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: TextButton(
             onPressed: () { },
@@ -40,8 +42,10 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
@@ -55,8 +59,13 @@
     final TestGesture gesture = await tester.startGesture(center);
     await tester.pump(); // start the splash animation
     await tester.pump(const Duration(milliseconds: 100)); // splash is underway
-    final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
-    expect(inkFeatures, paints..circle(color: colorScheme.primary.withAlpha(0x1f))); // splash color is primary(0.12)
+
+    // Material 3 uses the InkSparkle which uses a shader, so we can't capture
+    // the effect with paint methods.
+    if (!material3) {
+      final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+      expect(inkFeatures, paints..circle(color: colorScheme.primary.withOpacity(0.12)));
+    }
 
     await gesture.up();
     await tester.pumpAndSettle();
@@ -68,8 +77,10 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
@@ -80,7 +91,7 @@
     final Key iconButtonKey = UniqueKey();
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: Center(
           child: TextButton.icon(
             key: iconButtonKey,
@@ -104,8 +115,10 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
     expect(material.textStyle!.color, colorScheme.primary);
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
@@ -115,7 +128,7 @@
     // Disabled TextButton
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData.from(colorScheme: colorScheme),
+        theme: theme,
         home: const Center(
           child: TextButton(
             onPressed: null,
@@ -132,8 +145,10 @@
     expect(material.clipBehavior, Clip.none);
     expect(material.color, Colors.transparent);
     expect(material.elevation, 0.0);
-    expect(material.shadowColor, const Color(0xff000000));
-    expect(material.shape, const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))));
+    expect(material.shadowColor, material3 ? null : const Color(0xff000000));
+    expect(material.shape, material3
+      ? const StadiumBorder()
+      : const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4))));
     expect(material.textStyle!.color, colorScheme.onSurface.withOpacity(0.38));
     expect(material.textStyle!.fontFamily, 'Roboto');
     expect(material.textStyle!.fontSize, 14);
@@ -517,14 +532,18 @@
 
   testWidgets('Does TextButton scale with font scale changes', (WidgetTester tester) async {
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(),
-          child: Center(
-            child: TextButton(
-              onPressed: () { },
-              child: const Text('ABC'),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(),
+            child: Center(
+              child: TextButton(
+                onPressed: () { },
+                child: const Text('ABC'),
+              ),
             ),
           ),
         ),
@@ -536,14 +555,18 @@
 
     // textScaleFactor expands text, but not button.
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(textScaleFactor: 1.3),
-          child: Center(
-            child: TextButton(
-              onPressed: () { },
-              child: const Text('ABC'),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(textScaleFactor: 1.3),
+            child: Center(
+              child: TextButton(
+                onPressed: () { },
+                child: const Text('ABC'),
+              ),
             ),
           ),
         ),
@@ -559,14 +582,18 @@
 
     // Set text scale large enough to expand text and button.
     await tester.pumpWidget(
-      Directionality(
-        textDirection: TextDirection.ltr,
-        child: MediaQuery(
-          data: const MediaQueryData(textScaleFactor: 3.0),
-          child: Center(
-            child: TextButton(
-              onPressed: () { },
-              child: const Text('ABC'),
+      Theme(
+        // Force Material 2 typography.
+        data: ThemeData(textTheme: Typography.englishLike2014),
+        child: Directionality(
+          textDirection: TextDirection.ltr,
+          child: MediaQuery(
+            data: const MediaQueryData(textScaleFactor: 3.0),
+            child: Center(
+              child: TextButton(
+                onPressed: () { },
+                child: const Text('ABC'),
+              ),
             ),
           ),
         ),
@@ -581,7 +608,6 @@
     expect(tester.getSize(find.byType(Text)).height, equals(42.0));
   });
 
-
   testWidgets('TextButton size is configurable by ThemeData.materialTapTargetSize', (WidgetTester tester) async {
     Widget buildFrame(MaterialTapTargetSize tapTargetSize, Key key) {
       return Theme(
@@ -591,6 +617,7 @@
           child: Center(
             child: TextButton(
               key: key,
+              style: TextButton.styleFrom(minimumSize: const Size(64, 36)),
               child: const SizedBox(width: 50.0, height: 8.0),
               onPressed: () { },
             ),
@@ -855,6 +882,7 @@
     Future<void> buildTest(VisualDensity visualDensity, { bool useText = false }) async {
       return tester.pumpWidget(
         MaterialApp(
+          theme: ThemeData(textTheme: Typography.englishLike2014),
           home: Directionality(
             textDirection: TextDirection.rtl,
             child: Center(
@@ -993,7 +1021,15 @@
           testWidgets(testName, (WidgetTester tester) async {
             await tester.pumpWidget(
               MaterialApp(
-                theme: ThemeData.from(colorScheme: const ColorScheme.light()),
+                theme: ThemeData(
+                  colorScheme: const ColorScheme.light(),
+                  // Force Material 2 defaults for the typography and size
+                  // default values as the test was designed against these settings.
+                  textTheme: Typography.englishLike2014,
+                  textButtonTheme: TextButtonThemeData(
+                    style: TextButton.styleFrom(minimumSize: const Size(64, 36)),
+                  ),
+                ),
                 home: Builder(
                   builder: (BuildContext context) {
                     return MediaQuery(
@@ -1227,8 +1263,8 @@
       await tester.pumpAndSettle();
     }
 
-    // Default splashFactory (from Theme.of().splashFactory), one splash circle drawn.
-    await tester.pumpWidget(buildFrame());
+    // InkRipple.splashFactory, one splash circle drawn.
+    await tester.pumpWidget(buildFrame(splashFactory: InkRipple.splashFactory));
     {
       final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('test')));
       final MaterialInkController material = Material.of(tester.element(find.text('test')))!;
@@ -1352,6 +1388,7 @@
 
     await tester.pumpWidget(
       MaterialApp(
+        theme: ThemeData(textTheme: Typography.englishLike2014),
         home: Scaffold(
           body: Center(
             child: Column(
diff --git a/packages/flutter/test/scheduler/binding_test.dart b/packages/flutter/test/scheduler/binding_test.dart
new file mode 100644
index 0000000..d4018ff
--- /dev/null
+++ b/packages/flutter/test/scheduler/binding_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+import 'package:flutter/scheduler.dart';
+import 'package:flutter/widgets.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  WidgetsFlutterBinding.ensureInitialized();
+
+  test('scheduleForcedFrame sets up frame callbacks', () async {
+    SchedulerBinding.instance.scheduleForcedFrame();
+    expect(SchedulerBinding.instance.platformDispatcher.onBeginFrame, isNotNull);
+  });
+}