CupertinoThemeData equality (#119480)

diff --git a/packages/flutter/lib/src/cupertino/text_theme.dart b/packages/flutter/lib/src/cupertino/text_theme.dart
index 33f797b..d6ee4d1 100644
--- a/packages/flutter/lib/src/cupertino/text_theme.dart
+++ b/packages/flutter/lib/src/cupertino/text_theme.dart
@@ -260,6 +260,41 @@
     properties.add(DiagnosticsProperty<TextStyle>('pickerTextStyle', pickerTextStyle, defaultValue: defaultData.pickerTextStyle));
     properties.add(DiagnosticsProperty<TextStyle>('dateTimePickerTextStyle', dateTimePickerTextStyle, defaultValue: defaultData.dateTimePickerTextStyle));
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is CupertinoTextThemeData
+      && other._defaults == _defaults
+      && other._primaryColor == _primaryColor
+      && other._textStyle == _textStyle
+      && other._actionTextStyle == _actionTextStyle
+      && other._tabLabelTextStyle == _tabLabelTextStyle
+      && other._navTitleTextStyle == _navTitleTextStyle
+      && other._navLargeTitleTextStyle == _navLargeTitleTextStyle
+      && other._navActionTextStyle == _navActionTextStyle
+      && other._pickerTextStyle == _pickerTextStyle
+      && other._dateTimePickerTextStyle == _dateTimePickerTextStyle;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    _defaults,
+    _primaryColor,
+    _textStyle,
+    _actionTextStyle,
+    _tabLabelTextStyle,
+    _navTitleTextStyle,
+    _navLargeTitleTextStyle,
+    _navActionTextStyle,
+    _pickerTextStyle,
+    _dateTimePickerTextStyle,
+  );
 }
 
 
@@ -296,4 +331,20 @@
       ? this
       : _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray);
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is _TextThemeDefaultsBuilder
+      && other.labelColor == labelColor
+      && other.inactiveGrayColor == inactiveGrayColor;
+  }
+
+  @override
+  int get hashCode => Object.hash(labelColor, inactiveGrayColor);
 }
diff --git a/packages/flutter/lib/src/cupertino/theme.dart b/packages/flutter/lib/src/cupertino/theme.dart
index 39048b3..05a572e 100644
--- a/packages/flutter/lib/src/cupertino/theme.dart
+++ b/packages/flutter/lib/src/cupertino/theme.dart
@@ -311,6 +311,35 @@
     properties.add(DiagnosticsProperty<bool>('applyThemeToAll', applyThemeToAll, defaultValue: defaultData.applyThemeToAll));
     textTheme.debugFillProperties(properties);
   }
+
+  @override
+  bool operator == (Object other) {
+    if (identical(this, other)) {
+      return true;
+    }
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is CupertinoThemeData
+      && other.brightness == brightness
+      && other.primaryColor == primaryColor
+      && other.primaryContrastingColor == primaryContrastingColor
+      && other.textTheme == textTheme
+      && other.barBackgroundColor == barBackgroundColor
+      && other.scaffoldBackgroundColor == scaffoldBackgroundColor
+      && other.applyThemeToAll == applyThemeToAll;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+    brightness,
+    primaryColor,
+    primaryContrastingColor,
+    textTheme,
+    barBackgroundColor,
+    scaffoldBackgroundColor,
+    applyThemeToAll,
+  );
 }
 
 /// Styling specifications for a cupertino theme without default values for
diff --git a/packages/flutter/test/cupertino/theme_test.dart b/packages/flutter/test/cupertino/theme_test.dart
index 84058d7..15b1ec5 100644
--- a/packages/flutter/test/cupertino/theme_test.dart
+++ b/packages/flutter/test/cupertino/theme_test.dart
@@ -212,6 +212,18 @@
     );
   });
 
+  testWidgets('CupertinoThemeData equality', (WidgetTester tester) async {
+    const CupertinoThemeData a = CupertinoThemeData(brightness: Brightness.dark);
+    final CupertinoThemeData b = a.copyWith();
+    final CupertinoThemeData c = a.copyWith(brightness: Brightness.light);
+    expect(a, equals(b));
+    expect(b, equals(a));
+    expect(a, isNot(equals(c)));
+    expect(c, isNot(equals(a)));
+    expect(b, isNot(equals(c)));
+    expect(c, isNot(equals(b)));
+  });
+
   late Brightness currentBrightness;
   void colorMatches(Color? componentColor, CupertinoDynamicColor expectedDynamicColor) {
     switch (currentBrightness) {
diff --git a/packages/flutter/test/material/theme_test.dart b/packages/flutter/test/material/theme_test.dart
index 02fb589..2611452 100644
--- a/packages/flutter/test/material/theme_test.dart
+++ b/packages/flutter/test/material/theme_test.dart
@@ -644,12 +644,12 @@
           primarySwatch: Colors.blue,
           cupertinoOverrideTheme: const CupertinoThemeData(
             // But the primary material color is preempted by the override.
-            primaryColor: CupertinoColors.activeOrange,
+            primaryColor: CupertinoColors.systemRed,
           ),
         ));
 
         expect(buildCount, 2);
-        expect(theme.primaryColor, CupertinoColors.activeOrange);
+        expect(theme.primaryColor, CupertinoColors.systemRed);
       },
     );