Flutter 1.20.3 engine cherrypicks (#20838)

* Update 1.20 engine to use Dart 2.9.2
* update license goldens
* Fix EGL_BAD_SURFACE when app is paused (#20735)
* The `ForwardingGestureRecognizers` to have back reference to the `PlatformViewsController` so it can access `FlutterViewController` when its available  (#20708)
* cherry-pick e09af86a26df0fc05ec727d72deb7ae9fc89f446
* skip linting since this was enabled in CI after this release branch cut commit.

Co-authored-by: Emmanuel Garcia <egarciad@google.com>
Co-authored-by: Chris Yang <ychris@google.com>
diff --git a/DEPS b/DEPS
index 09e6e35..25f8227 100644
--- a/DEPS
+++ b/DEPS
@@ -34,7 +34,7 @@
   # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
   # You can use //tools/dart/create_updated_flutter_deps.py to produce
   # updated revision list of existing dependencies.
-  'dart_revision': 'e940ff7819053ed8a4c04a4dfcda7df12e969331',
+  'dart_revision': 'b07da893600eadc4efafc5a54b8f9533e43c0034',
 
   # WARNING: DO NOT EDIT MANUALLY
   # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party
index ea5d6a3..5e03e89 100644
--- a/ci/licenses_golden/licenses_third_party
+++ b/ci/licenses_golden/licenses_third_party
@@ -1,4 +1,4 @@
-Signature: 3d3cc897eb78f9e41161745c866094e3
+Signature: 5a1ec57ea6d353e70a74264709f60d08
 
 UNUSED LICENSES:
 
diff --git a/ci/lint.sh b/ci/lint.sh
index 023d982..c62bdd5 100755
--- a/ci/lint.sh
+++ b/ci/lint.sh
@@ -7,4 +7,6 @@
   ./flutter/tools/gn
 fi
 
-dart flutter/ci/lint.dart $COMPILE_COMMANDS flutter/
+exit 0
+# This CI step was added after 1.20.x was cut
+#dart flutter/ci/lint.dart $COMPILE_COMMANDS flutter/
diff --git a/lib/ui/painting/canvas.cc b/lib/ui/painting/canvas.cc
index d3d0845..16e39ed 100644
--- a/lib/ui/painting/canvas.cc
+++ b/lib/ui/painting/canvas.cc
@@ -292,10 +292,11 @@
                        const PaintData& paint_data) {
   if (!canvas_)
     return;
-  if (!image)
+  if (!image) {
     Dart_ThrowException(
         ToDart("Canvas.drawImage called with non-genuine Image."));
-  external_allocation_size_ += image->GetAllocationSize();
+    return;
+  }
   canvas_->drawImage(image->image(), x, y, paint.paint());
 }
 
@@ -317,7 +318,6 @@
         ToDart("Canvas.drawImageRect called with non-genuine Image."));
   SkRect src = SkRect::MakeLTRB(src_left, src_top, src_right, src_bottom);
   SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
-  external_allocation_size_ += image->GetAllocationSize();
   canvas_->drawImageRect(image->image(), src, dst, paint.paint(),
                          SkCanvas::kFast_SrcRectConstraint);
 }
@@ -343,7 +343,6 @@
   SkIRect icenter;
   center.round(&icenter);
   SkRect dst = SkRect::MakeLTRB(dst_left, dst_top, dst_right, dst_bottom);
-  external_allocation_size_ += image->GetAllocationSize();
   canvas_->drawImageNine(image->image(), icenter, dst, paint.paint());
 }
 
diff --git a/shell/platform/android/android_surface_gl.cc b/shell/platform/android/android_surface_gl.cc
index c8cc3d2..2f93033 100644
--- a/shell/platform/android/android_surface_gl.cc
+++ b/shell/platform/android/android_surface_gl.cc
@@ -35,7 +35,11 @@
 AndroidSurfaceGL::~AndroidSurfaceGL() = default;
 
 void AndroidSurfaceGL::TeardownOnScreenContext() {
+  // When the onscreen surface is destroyed, the context and the surface
+  // instance should be deleted. Issue:
+  // https://github.com/flutter/flutter/issues/64414
   android_context_->ClearCurrent();
+  onscreen_surface_ = nullptr;
 }
 
 bool AndroidSurfaceGL::IsValid() const {
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
index e49e0fa..fdfcd6f 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
@@ -107,6 +107,10 @@
   flutter_view_controller_.reset([flutter_view_controller retain]);
 }
 
+UIViewController* FlutterPlatformViewsController::getFlutterViewController() {
+  return flutter_view_controller_.get();
+}
+
 void FlutterPlatformViewsController::OnMethodCall(FlutterMethodCall* call, FlutterResult& result) {
   if ([[call method] isEqualToString:@"create"]) {
     OnCreate(call, result);
@@ -161,7 +165,7 @@
 
   FlutterTouchInterceptingView* touch_interceptor = [[[FlutterTouchInterceptingView alloc]
                   initWithEmbeddedView:embedded_view.view
-                 flutterViewController:flutter_view_controller_.get()
+               platformViewsController:GetWeakPtr()
       gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies[viewType]]
       autorelease];
 
@@ -701,7 +705,8 @@
 // directly to the FlutterView.
 @interface ForwardingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
 - (instancetype)initWithTarget:(id)target
-         flutterViewController:(UIViewController*)flutterViewController;
+       platformViewsController:
+           (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController;
 @end
 
 @implementation FlutterTouchInterceptingView {
@@ -709,7 +714,8 @@
   FlutterPlatformViewGestureRecognizersBlockingPolicy _blockingPolicy;
 }
 - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
-               flutterViewController:(UIViewController*)flutterViewController
+             platformViewsController:
+                 (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController
     gestureRecognizersBlockingPolicy:
         (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy {
   self = [super initWithFrame:embeddedView.frame];
@@ -720,9 +726,9 @@
 
     [self addSubview:embeddedView];
 
-    ForwardingGestureRecognizer* forwardingRecognizer =
-        [[[ForwardingGestureRecognizer alloc] initWithTarget:self
-                                       flutterViewController:flutterViewController] autorelease];
+    ForwardingGestureRecognizer* forwardingRecognizer = [[[ForwardingGestureRecognizer alloc]
+                 initWithTarget:self
+        platformViewsController:std::move(platformViewsController)] autorelease];
 
     _delayingRecognizer.reset([[DelayingGestureRecognizer alloc]
               initWithTarget:self
@@ -833,39 +839,42 @@
 @end
 
 @implementation ForwardingGestureRecognizer {
-  // We can't dispatch events to the framework without this back pointer.
-  // This is a weak reference, the ForwardingGestureRecognizer is owned by the
-  // FlutterTouchInterceptingView which is strong referenced only by the FlutterView,
-  // which is strongly referenced by the FlutterViewController.
-  // So this is safe as when FlutterView is deallocated the reference to ForwardingGestureRecognizer
-  // will go away.
-  UIViewController* _flutterViewController;
+  // Weak reference to FlutterPlatformViewsController. The FlutterPlatformViewsController has
+  // a reference to the FlutterViewController, where we can dispatch pointer events to.
+  //
+  // The lifecycle of FlutterPlatformViewsController is bind to FlutterEngine, which should always
+  // outlives the FlutterViewController. And ForwardingGestureRecognizer is owned by a subview of
+  // FlutterView, so the ForwardingGestureRecognizer never out lives FlutterViewController.
+  // Therefore, `_platformViewsController` should never be nullptr.
+  fml::WeakPtr<flutter::FlutterPlatformViewsController> _platformViewsController;
   // Counting the pointers that has started in one touch sequence.
   NSInteger _currentTouchPointersCount;
 }
 
 - (instancetype)initWithTarget:(id)target
-         flutterViewController:(UIViewController*)flutterViewController {
+       platformViewsController:
+           (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController {
   self = [super initWithTarget:target action:nil];
   if (self) {
     self.delegate = self;
-    _flutterViewController = flutterViewController;
+    FML_DCHECK(platformViewsController.get() != nullptr);
+    _platformViewsController = std::move(platformViewsController);
     _currentTouchPointersCount = 0;
   }
   return self;
 }
 
 - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
-  [_flutterViewController touchesBegan:touches withEvent:event];
+  [_platformViewsController.get()->getFlutterViewController() touchesBegan:touches withEvent:event];
   _currentTouchPointersCount += touches.count;
 }
 
 - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
-  [_flutterViewController touchesMoved:touches withEvent:event];
+  [_platformViewsController.get()->getFlutterViewController() touchesMoved:touches withEvent:event];
 }
 
 - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
-  [_flutterViewController touchesEnded:touches withEvent:event];
+  [_platformViewsController.get()->getFlutterViewController() touchesEnded:touches withEvent:event];
   _currentTouchPointersCount -= touches.count;
   // Touches in one touch sequence are sent to the touchesEnded method separately if different
   // fingers stop touching the screen at different time. So one touchesEnded method triggering does
@@ -877,7 +886,8 @@
 }
 
 - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
-  [_flutterViewController touchesCancelled:touches withEvent:event];
+  [_platformViewsController.get()->getFlutterViewController() touchesCancelled:touches
+                                                                     withEvent:event];
   _currentTouchPointersCount = 0;
   self.state = UIGestureRecognizerStateFailed;
 }
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
index 0e8397e..39d6b98 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
@@ -7,7 +7,9 @@
 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
+#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
+#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
 #import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
 #import "third_party/ocmock/Source/OCMock/OCMock.h"
 
@@ -508,6 +510,70 @@
   flutterPlatformViewsController->Reset();
 }
 
+- (void)testSetFlutterViewControllerAfterCreateCanStillDispatchTouchEvents {
+  flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
+  auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
+  flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
+                               /*platform=*/thread_task_runner,
+                               /*raster=*/thread_task_runner,
+                               /*ui=*/thread_task_runner,
+                               /*io=*/thread_task_runner);
+  auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
+      /*delegate=*/mock_delegate,
+      /*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
+      /*task_runners=*/runners);
+
+  auto flutterPlatformViewsController = std::make_unique<flutter::FlutterPlatformViewsController>();
+
+  FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
+      [[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
+  flutterPlatformViewsController->RegisterViewFactory(
+      factory, @"MockFlutterPlatformView",
+      FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
+  FlutterResult result = ^(id result) {
+  };
+  flutterPlatformViewsController->OnMethodCall(
+      [FlutterMethodCall
+          methodCallWithMethodName:@"create"
+                         arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
+      result);
+
+  XCTAssertNotNil(gMockPlatformView);
+
+  // Find touch inteceptor view
+  UIView* touchInteceptorView = gMockPlatformView;
+  while (touchInteceptorView != nil &&
+         ![touchInteceptorView isKindOfClass:[FlutterTouchInterceptingView class]]) {
+    touchInteceptorView = touchInteceptorView.superview;
+  }
+  XCTAssertNotNil(touchInteceptorView);
+
+  // Find ForwardGestureRecognizer
+  UIGestureRecognizer* forwardGectureRecognizer = nil;
+  for (UIGestureRecognizer* gestureRecognizer in touchInteceptorView.gestureRecognizers) {
+    if ([gestureRecognizer isKindOfClass:NSClassFromString(@"ForwardingGestureRecognizer")]) {
+      forwardGectureRecognizer = gestureRecognizer;
+      break;
+    }
+  }
+
+  // Before setting flutter view controller, events are not dispatched.
+  NSSet* touches1 = OCMClassMock([NSSet class]);
+  UIEvent* event1 = OCMClassMock([UIEvent class]);
+  UIViewController* mockFlutterViewContoller = OCMClassMock([UIViewController class]);
+  [forwardGectureRecognizer touchesBegan:touches1 withEvent:event1];
+  OCMReject([mockFlutterViewContoller touchesBegan:touches1 withEvent:event1]);
+
+  // Set flutter view controller allows events to be dispatched.
+  NSSet* touches2 = OCMClassMock([NSSet class]);
+  UIEvent* event2 = OCMClassMock([UIEvent class]);
+  flutterPlatformViewsController->SetFlutterViewController(mockFlutterViewContoller);
+  [forwardGectureRecognizer touchesBegan:touches2 withEvent:event2];
+  OCMVerify([mockFlutterViewContoller touchesBegan:touches2 withEvent:event2]);
+
+  flutterPlatformViewsController->Reset();
+}
+
 - (int)alphaOfPoint:(CGPoint)point onView:(UIView*)view {
   unsigned char pixel[4] = {0};
 
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
index 796d1e5..2364da2 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
@@ -16,6 +16,8 @@
 #include "flutter/shell/platform/darwin/ios/ios_context.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
 
+@class FlutterTouchInterceptingView;
+
 // A UIView that acts as a clipping mask for the |ChildClippingView|.
 //
 // On the [UIView drawRect:] method, this view performs a series of clipping operations and sets the
@@ -43,24 +45,6 @@
 
 @end
 
-// A UIView that is used as the parent for embedded UIViews.
-//
-// This view has 2 roles:
-// 1. Delay or prevent touch events from arriving the embedded view.
-// 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
-@interface FlutterTouchInterceptingView : UIView
-- (instancetype)initWithEmbeddedView:(UIView*)embeddedView
-               flutterViewController:(UIViewController*)flutterViewController
-    gestureRecognizersBlockingPolicy:
-        (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy;
-
-// Stop delaying any active touch sequence (and let it arrive the embedded view).
-- (void)releaseGesture;
-
-// Prevent the touch sequence from ever arriving to the embedded view.
-- (void)blockGesture;
-@end
-
 // The parent view handles clipping to its subviews.
 @interface ChildClippingView : UIView
 
@@ -143,10 +127,14 @@
 
   ~FlutterPlatformViewsController();
 
+  fml::WeakPtr<flutter::FlutterPlatformViewsController> GetWeakPtr();
+
   void SetFlutterView(UIView* flutter_view);
 
   void SetFlutterViewController(UIViewController* flutter_view_controller);
 
+  UIViewController* getFlutterViewController();
+
   void RegisterViewFactory(
       NSObject<FlutterPlatformViewFactory>* factory,
       NSString* factoryId,
@@ -255,6 +243,8 @@
   std::map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
       gesture_recognizers_blocking_policies;
 
+  std::unique_ptr<fml::WeakPtrFactory<FlutterPlatformViewsController>> weak_factory_;
+
   void OnCreate(FlutterMethodCall* call, FlutterResult& result);
   void OnDispose(FlutterMethodCall* call, FlutterResult& result);
   void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
@@ -313,4 +303,23 @@
 
 }  // namespace flutter
 
+// A UIView that is used as the parent for embedded UIViews.
+//
+// This view has 2 roles:
+// 1. Delay or prevent touch events from arriving the embedded view.
+// 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
+@interface FlutterTouchInterceptingView : UIView
+- (instancetype)initWithEmbeddedView:(UIView*)embeddedView
+             platformViewsController:
+                 (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController
+    gestureRecognizersBlockingPolicy:
+        (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy;
+
+// Stop delaying any active touch sequence (and let it arrive the embedded view).
+- (void)releaseGesture;
+
+// Prevent the touch sequence from ever arriving to the embedded view.
+- (void)blockGesture;
+@end
+
 #endif  // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
index 5e9ed80..0179deb 100644
--- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
+++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
@@ -24,10 +24,15 @@
 FlutterPlatformViewLayer::~FlutterPlatformViewLayer() = default;
 
 FlutterPlatformViewsController::FlutterPlatformViewsController()
-    : layer_pool_(std::make_unique<FlutterPlatformViewLayerPool>()){};
+    : layer_pool_(std::make_unique<FlutterPlatformViewLayerPool>()),
+      weak_factory_(std::make_unique<fml::WeakPtrFactory<FlutterPlatformViewsController>>(this)){};
 
 FlutterPlatformViewsController::~FlutterPlatformViewsController() = default;
 
+fml::WeakPtr<flutter::FlutterPlatformViewsController> FlutterPlatformViewsController::GetWeakPtr() {
+  return weak_factory_->GetWeakPtr();
+}
+
 CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
   // Skia only supports 2D transform so we don't map z.
   CATransform3D transform = CATransform3DIdentity;
diff --git a/testing/dart/canvas_test.dart b/testing/dart/canvas_test.dart
index 7bf5072..57ad280 100644
--- a/testing/dart/canvas_test.dart
+++ b/testing/dart/canvas_test.dart
@@ -218,34 +218,6 @@
     expect(areEqual, true);
   }, skip: !Platform.isLinux); // https://github.com/flutter/flutter/issues/53784
 
-  test('Image size reflected in picture size for image*, drawAtlas, and drawPicture methods', () async {
-    final Image image = await createImage(100, 100);
-    final PictureRecorder recorder = PictureRecorder();
-    final Canvas canvas = Canvas(recorder);
-    const Rect rect = Rect.fromLTWH(0, 0, 100, 100);
-    canvas.drawImage(image, Offset.zero, Paint());
-    canvas.drawImageRect(image, rect, rect, Paint());
-    canvas.drawImageNine(image, rect, rect, Paint());
-    canvas.drawAtlas(image, <RSTransform>[], <Rect>[], <Color>[], BlendMode.src, rect, Paint());
-    final Picture picture = recorder.endRecording();
-
-    // Some of the numbers here appear to utilize sharing/reuse of common items,
-    // e.g. of the Paint() or same `Rect` usage, etc.
-    // The raw utilization of a 100x100 picture here should be 53333:
-    // 100 * 100 * 4 * (4/3) = 53333.333333....
-    // To avoid platform specific idiosyncrasies and brittleness against changes
-    // to Skia, we just assert this is _at least_ 4x the image size.
-    const int minimumExpected = 53333 * 4;
-    expect(picture.approximateBytesUsed, greaterThan(minimumExpected));
-
-    final PictureRecorder recorder2 = PictureRecorder();
-    final Canvas canvas2 = Canvas(recorder2);
-    canvas2.drawPicture(picture);
-    final Picture picture2 = recorder2.endRecording();
-
-    expect(picture2.approximateBytesUsed, greaterThan(minimumExpected));
-  });
-
   test('Vertex buffer size reflected in picture size for drawVertices', () async {
     final PictureRecorder recorder = PictureRecorder();
     final Canvas canvas = Canvas(recorder);