From 379f2e8719f62051c35a4a4e0bab3b959c6c0609 Mon Sep 17 00:00:00 2001 From: Xilai Zhang Date: Tue, 3 Oct 2023 11:21:47 -0600 Subject: [PATCH 01/31] [flutter_releases] Flutter beta 3.16.0-0.1.pre Engine Cherrypicks (#46506) # Flutter beta 3.16.0-0.1.pre Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@5c23602e3 --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index f9814f12b8a9b..1dda1ab7141a5 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '077d768accfa3419b8b57cf779cca8228b417faa', + 'dart_revision': '5c23602e3e22df0c0cbab680d3955ee288122acd', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py From 7ccdde78a7d174dc0bf0be77102b205e844c7998 Mon Sep 17 00:00:00 2001 From: Xilai Zhang Date: Tue, 10 Oct 2023 14:55:34 -0700 Subject: [PATCH 02/31] [flutter release cp] Use x86 machines for ios builds. (#46726) (#46737) This is to workaround rosetta not being installed in dart-internal machines and to unblock beta releases. Bug: https://github.com/flutter/flutter/issues/136219 Co-authored-by: godofredoc --- ci/builders/mac_ios_engine.json | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/ci/builders/mac_ios_engine.json b/ci/builders/mac_ios_engine.json index 600f495929b0c..3dfc5c4d559b4 100644 --- a/ci/builders/mac_ios_engine.json +++ b/ci/builders/mac_ios_engine.json @@ -3,8 +3,8 @@ { "drone_dimensions": [ "device_type=none", - "mac_model=Macmini8,1", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -26,7 +26,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -49,7 +50,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -72,7 +74,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -96,7 +99,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -120,8 +124,8 @@ { "drone_dimensions": [ "device_type=none", - "mac_model=Macmini8,1", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -144,7 +148,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -168,7 +173,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -192,7 +198,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", @@ -217,7 +224,8 @@ { "drone_dimensions": [ "device_type=none", - "os=Mac-12" + "os=Mac-12", + "cpu=x86" ], "gn": [ "--ios", From a8f73942bd23dc3513e9f126dec6eb19ae582e5c Mon Sep 17 00:00:00 2001 From: Chris Yang Date: Wed, 11 Oct 2023 14:47:47 -0700 Subject: [PATCH 03/31] [cp][ios] Link PlatformView back to semantics tree (#46471) (#46715) Cherry pick https://github.com/flutter/engine/commit/250daadbca517677317277f314ea2a40568eb345 Cherry pick issue https://github.com/flutter/flutter/issues/136266 Description: The PlatformView does not have a semantics container when added to semantics tree, this PR gives it a semantics container to ensure accessibility traversal works. This fixes https://github.com/flutter/flutter/issues/135504, which is a regression of https://github.com/flutter/engine/commit/b8332e3c4870512a941d685d7d375b1d2d62983c Before https://github.com/flutter/engine/commit/b8332e3c4870512a941d685d7d375b1d2d62983c, the traversal works because the PlatformView is added to the accessibilityElements of the FlutterPlatFormViewSemanticsContainer, which implicitly made the FlutterPlatFormViewSemanticsContainer as the PlatformVIew's AccessibilityContainer. Now we use the PlatformVIew as the nativeAccessibility of the FlutterPlatFormViewSemanticsContainer, we need to expilicitly set the container. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- ci/licenses_golden/licenses_flutter | 6 + shell/platform/darwin/ios/BUILD.gn | 3 + .../framework/Source/FlutterPlatformViews.mm | 19 ++- .../Source/FlutterPlatformViewsTest.mm | 9 + .../Source/FlutterPlatformViews_Internal.h | 13 +- .../FlutterTouchInterceptingView_Test.h | 14 ++ .../ios/framework/Source/SemanticsObject.h | 4 +- .../ios/framework/Source/SemanticsObject.mm | 13 +- .../framework/Source/SemanticsObjectTest.mm | 155 +----------------- .../Source/SemanticsObjectTestMocks.h | 95 +++++++++++ .../Source/SemanticsObjectTest_mrc.mm | 89 ++++++++++ .../framework/Source/accessibility_bridge.mm | 2 +- 12 files changed, 254 insertions(+), 168 deletions(-) create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h create mode 100644 shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h create mode 100644 shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 53a9299268fe4..f31b0f04c8c8b 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2697,6 +2697,7 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextI ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelayTest.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m + ../../../flutter/LICENSE @@ -2718,6 +2719,8 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/KeyCodeMap_I ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController_FlutterScreenAndSceneIfLoadedTest.mm + ../../../flutter/LICENSE @@ -5465,6 +5468,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInp FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelay.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTextureRegistryRelayTest.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUIPressProxy.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterUmbrellaImport.m @@ -5486,6 +5490,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/KeyCodeMap_Int FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/UIViewController_FlutterScreenAndSceneIfLoadedTest.mm diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index fe180c2af422f..b8bd60198ae0a 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -238,8 +238,11 @@ source_set("ios_test_flutter_mrc") { "framework/Source/FlutterEngineTest_mrc.mm", "framework/Source/FlutterPlatformPluginTest.mm", "framework/Source/FlutterPlatformViewsTest.mm", + "framework/Source/FlutterTouchInterceptingView_Test.h", "framework/Source/FlutterViewControllerTest_mrc.mm", "framework/Source/FlutterViewTest.mm", + "framework/Source/SemanticsObjectTestMocks.h", + "framework/Source/SemanticsObjectTest_mrc.mm", "framework/Source/VsyncWaiterIosTest.mm", "framework/Source/accessibility_bridge_test.mm", "platform_message_handler_ios_test.mm", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index bf7e607878d1b..6c3bcd9ccdaab 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -406,10 +406,15 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, } UIView* FlutterPlatformViewsController::GetPlatformViewByID(int64_t view_id) { + return [GetFlutterTouchInterceptingViewByID(view_id) embeddedView]; +} + +FlutterTouchInterceptingView* FlutterPlatformViewsController::GetFlutterTouchInterceptingViewByID( + int64_t view_id) { if (views_.empty()) { return nil; } - return [touch_interceptors_[view_id].get() embeddedView]; + return touch_interceptors_[view_id].get(); } long FlutterPlatformViewsController::FindFirstResponderPlatformViewId() { @@ -957,6 +962,10 @@ @implementation FlutterTouchInterceptingView { fml::scoped_nsobject _delayingRecognizer; FlutterPlatformViewGestureRecognizersBlockingPolicy _blockingPolicy; UIView* _embeddedView; + // The used as the accessiblityContainer. + // The `accessiblityContainer` is used in UIKit to determine the parent of this accessibility + // node. + NSObject* _flutterAccessibilityContainer; } - (instancetype)initWithEmbeddedView:(UIView*)embeddedView platformViewsController: @@ -1035,6 +1044,14 @@ - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { } +- (void)setFlutterAccessibilityContainer:(NSObject*)flutterAccessibilityContainer { + _flutterAccessibilityContainer = flutterAccessibilityContainer; +} + +- (id)accessibilityContainer { + return _flutterAccessibilityContainer; +} + @end @implementation DelayingGestureRecognizer { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 1e6dad56089aa..c55111136df9b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -11,6 +11,7 @@ #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/FlutterTouchInterceptingView_Test.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" @@ -3099,4 +3100,12 @@ - (void)testOnlyPlatformViewsAreRemovedWhenReset { XCTAssertEqual(mockFlutterView.subviews.firstObject, someView); } +- (void)testFlutterTouchInterceptingViewLinksToAccessibilityContainer { + FlutterTouchInterceptingView* touchInteceptorView = + [[[FlutterTouchInterceptingView alloc] init] autorelease]; + NSObject* container = [[[NSObject alloc] init] autorelease]; + [touchInteceptorView setFlutterAccessibilityContainer:container]; + XCTAssertEqualObjects([touchInteceptorView accessibilityContainer], container); +} + @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 43cb43cf4e33b..e18569868115f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -12,6 +12,7 @@ #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h" #import "flutter/shell/platform/darwin/ios/ios_context.h" @class FlutterTouchInterceptingView; @@ -230,10 +231,17 @@ class FlutterPlatformViewsController { // Returns the `FlutterPlatformView`'s `view` object associated with the view_id. // // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or - // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method + // a `FlutterPlatformView` object associated with the view_id cannot be found, the method // returns nil. UIView* GetPlatformViewByID(int64_t view_id); + // Returns the `FlutterTouchInterceptingView` with the view_id. + // + // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or + // a `FlutterPlatformView` object associated with the view_id cannot be found, the method + // returns nil. + FlutterTouchInterceptingView* GetFlutterTouchInterceptingViewByID(int64_t view_id); + PostPrerollResult PostPrerollAction( const fml::RefPtr& raster_thread_merger); @@ -424,6 +432,9 @@ class FlutterPlatformViewsController { // Get embedded view - (UIView*)embeddedView; + +// Sets flutterAccessibilityContainer as this view's accessibilityContainer. +- (void)setFlutterAccessibilityContainer:(NSObject*)flutterAccessibilityContainer; @end @interface UIView (FirstResponder) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h b/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h new file mode 100644 index 0000000000000..52f4f465c0f16 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h @@ -0,0 +1,14 @@ +// Copyright 2013 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 "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" + +#ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_TOUCH_INTERCEPTING_VIEW_TEST_H_ +#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_TOUCH_INTERCEPTING_VIEW_TEST_H_ + +@interface FlutterTouchInterceptingView (Tests) +- (id)accessibilityContainer; +@end + +#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_TOUCH_INTERCEPTING_VIEW_TESTS_H_ diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.h b/shell/platform/darwin/ios/framework/Source/SemanticsObject.h index f7c611dec2ced..8a431193d1a8d 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.h +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.h @@ -18,6 +18,7 @@ constexpr float kScrollExtentMaxForInf = 1000; @class FlutterCustomAccessibilityAction; @class FlutterPlatformViewSemanticsContainer; +@class FlutterTouchInterceptingView; /** * A node in the iOS semantics tree. This object is a wrapper over a native accessibiliy @@ -171,7 +172,8 @@ constexpr float kScrollExtentMaxForInf = 1000; - (instancetype)initWithBridge:(fml::WeakPtr)bridge uid:(int32_t)uid - platformView:(UIView*)platformView NS_DESIGNATED_INITIALIZER; + platformView:(FlutterTouchInterceptingView*)platformView + NS_DESIGNATED_INITIALIZER; @end diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm index 5889a32463892..8f278fe31a721 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm @@ -157,9 +157,7 @@ @interface FlutterScrollableSemanticsObject () @property(nonatomic, retain) FlutterSemanticsScrollView* scrollView; @end -@implementation FlutterScrollableSemanticsObject { - fml::scoped_nsobject _container; -} +@implementation FlutterScrollableSemanticsObject - (instancetype)initWithBridge:(fml::WeakPtr)bridge uid:(int32_t)uid { @@ -865,9 +863,10 @@ @implementation FlutterPlatformViewSemanticsContainer - (instancetype)initWithBridge:(fml::WeakPtr)bridge uid:(int32_t)uid - platformView:(nonnull UIView*)platformView { + platformView:(nonnull FlutterTouchInterceptingView*)platformView { if (self = [super initWithBridge:bridge uid:uid]) { _platformView = [platformView retain]; + [platformView setFlutterAccessibilityContainer:self]; } return self; } @@ -882,12 +881,6 @@ - (id)nativeAccessibility { return _platformView; } -#pragma mark - UIAccessibilityContainer overrides - -- (NSArray*)accessibilityElements { - return @[ _platformView ]; -} - @end @implementation SemanticsObjectContainer { diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm index 2a3f7e799e40f..3d7f2cdf0163e 100644 --- a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest.mm @@ -7,97 +7,13 @@ #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" #import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h" FLUTTER_ASSERT_ARC -const CGRect kScreenSize = CGRectMake(0, 0, 600, 800); - -namespace flutter { -namespace { - -class SemanticsActionObservation { - public: - SemanticsActionObservation(int32_t observed_id, SemanticsAction observed_action) - : id(observed_id), action(observed_action) {} - - int32_t id; - SemanticsAction action; -}; - -class MockAccessibilityBridge : public AccessibilityBridgeIos { - public: - MockAccessibilityBridge() : observations({}) { - view_ = [[UIView alloc] initWithFrame:kScreenSize]; - window_ = [[UIWindow alloc] initWithFrame:kScreenSize]; - [window_ addSubview:view_]; - } - bool isVoiceOverRunning() const override { return isVoiceOverRunningValue; } - UIView* view() const override { return view_; } - UIView* textInputView() override { return nil; } - void DispatchSemanticsAction(int32_t id, SemanticsAction action) override { - SemanticsActionObservation observation(id, action); - observations.push_back(observation); - } - void DispatchSemanticsAction(int32_t id, - SemanticsAction action, - fml::MallocMapping args) override { - SemanticsActionObservation observation(id, action); - observations.push_back(observation); - } - void AccessibilityObjectDidBecomeFocused(int32_t id) override {} - void AccessibilityObjectDidLoseFocus(int32_t id) override {} - std::shared_ptr GetPlatformViewsController() const override { - return nil; - } - std::vector observations; - bool isVoiceOverRunningValue; - - private: - UIView* view_; - UIWindow* window_; -}; - -class MockAccessibilityBridgeNoWindow : public AccessibilityBridgeIos { - public: - MockAccessibilityBridgeNoWindow() : observations({}) { - view_ = [[UIView alloc] initWithFrame:kScreenSize]; - } - bool isVoiceOverRunning() const override { return isVoiceOverRunningValue; } - UIView* view() const override { return view_; } - UIView* textInputView() override { return nil; } - void DispatchSemanticsAction(int32_t id, SemanticsAction action) override { - SemanticsActionObservation observation(id, action); - observations.push_back(observation); - } - void DispatchSemanticsAction(int32_t id, - SemanticsAction action, - fml::MallocMapping args) override { - SemanticsActionObservation observation(id, action); - observations.push_back(observation); - } - void AccessibilityObjectDidBecomeFocused(int32_t id) override {} - void AccessibilityObjectDidLoseFocus(int32_t id) override {} - std::shared_ptr GetPlatformViewsController() const override { - return nil; - } - std::vector observations; - bool isVoiceOverRunningValue; - - private: - UIView* view_; -}; -} // namespace -} // namespace flutter - @interface SemanticsObjectTest : XCTestCase @end -@interface SemanticsObject (Tests) -- (BOOL)accessibilityScrollToVisible; -- (BOOL)accessibilityScrollToVisibleWithChild:(id)child; -- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event; -@end - @implementation SemanticsObjectTest - (void)testCreate { @@ -203,54 +119,6 @@ - (void)testAccessibilityHitTestNoFocusableItem { XCTAssertNil(hitTestResult); } -- (void)testAccessibilityHitTestSearchCanReturnPlatformView { - fml::WeakPtrFactory factory( - new flutter::MockAccessibilityBridge()); - fml::WeakPtr bridge = factory.GetWeakPtr(); - SemanticsObject* object0 = [[SemanticsObject alloc] initWithBridge:bridge uid:0]; - SemanticsObject* object1 = [[SemanticsObject alloc] initWithBridge:bridge uid:1]; - SemanticsObject* object3 = [[SemanticsObject alloc] initWithBridge:bridge uid:3]; - UIView* platformView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; - FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer = - [[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge - uid:1 - platformView:platformView]; - - object0.children = @[ object1 ]; - object0.childrenInHitTestOrder = @[ object1 ]; - object1.children = @[ platformViewSemanticsContainer, object3 ]; - object1.childrenInHitTestOrder = @[ platformViewSemanticsContainer, object3 ]; - - flutter::SemanticsNode node0; - node0.id = 0; - node0.rect = SkRect::MakeXYWH(0, 0, 200, 200); - node0.label = "0"; - [object0 setSemanticsNode:&node0]; - - flutter::SemanticsNode node1; - node1.id = 1; - node1.rect = SkRect::MakeXYWH(0, 0, 200, 200); - node1.label = "1"; - [object1 setSemanticsNode:&node1]; - - flutter::SemanticsNode node2; - node2.id = 2; - node2.rect = SkRect::MakeXYWH(0, 0, 100, 100); - node2.label = "2"; - [platformViewSemanticsContainer setSemanticsNode:&node2]; - - flutter::SemanticsNode node3; - node3.id = 3; - node3.rect = SkRect::MakeXYWH(0, 0, 200, 200); - node3.label = "3"; - [object3 setSemanticsNode:&node3]; - - CGPoint point = CGPointMake(10, 10); - id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; - - XCTAssertEqual(hitTestResult, platformView); -} - - (void)testAccessibilityScrollToVisible { fml::WeakPtrFactory factory( new flutter::MockAccessibilityBridge()); @@ -897,27 +765,6 @@ - (void)testShouldDispatchShowOnScreenActionForHidden { XCTAssertTrue(bridge->observations[0].action == flutter::SemanticsAction::kShowOnScreen); } -- (void)testFlutterPlatformViewSemanticsContainer { - fml::WeakPtrFactory factory( - new flutter::MockAccessibilityBridge()); - fml::WeakPtr bridge = factory.GetWeakPtr(); - __weak UIView* weakPlatformView; - @autoreleasepool { - UIView* platformView = [[UIView alloc] init]; - - FlutterPlatformViewSemanticsContainer* container = - [[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge - uid:1 - platformView:platformView]; - XCTAssertEqualObjects(container.accessibilityElements, @[ platformView ]); - weakPlatformView = platformView; - XCTAssertNotNil(weakPlatformView); - } - // Check if there's no more strong references to `platformView` after container and platformView - // are released. - XCTAssertNil(weakPlatformView); -} - - (void)testFlutterSwitchSemanticsObjectMatchesUISwitch { fml::WeakPtrFactory factory( new flutter::MockAccessibilityBridge()); diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h new file mode 100644 index 0000000000000..0f0c0303d4a98 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h @@ -0,0 +1,95 @@ +// Copyright 2013 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. + +#ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_TEST_MOCKS_H_ +#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_TEST_MOCKS_H_ + +#import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h" + +const CGRect kScreenSize = CGRectMake(0, 0, 600, 800); + +namespace flutter { +namespace { + +class SemanticsActionObservation { + public: + SemanticsActionObservation(int32_t observed_id, SemanticsAction observed_action) + : id(observed_id), action(observed_action) {} + + int32_t id; + SemanticsAction action; +}; + +class MockAccessibilityBridge : public AccessibilityBridgeIos { + public: + MockAccessibilityBridge() : observations({}) { + view_ = [[UIView alloc] initWithFrame:kScreenSize]; + window_ = [[UIWindow alloc] initWithFrame:kScreenSize]; + [window_ addSubview:view_]; + } + bool isVoiceOverRunning() const override { return isVoiceOverRunningValue; } + UIView* view() const override { return view_; } + UIView* textInputView() override { return nil; } + void DispatchSemanticsAction(int32_t id, SemanticsAction action) override { + SemanticsActionObservation observation(id, action); + observations.push_back(observation); + } + void DispatchSemanticsAction(int32_t id, + SemanticsAction action, + fml::MallocMapping args) override { + SemanticsActionObservation observation(id, action); + observations.push_back(observation); + } + void AccessibilityObjectDidBecomeFocused(int32_t id) override {} + void AccessibilityObjectDidLoseFocus(int32_t id) override {} + std::shared_ptr GetPlatformViewsController() const override { + return nil; + } + std::vector observations; + bool isVoiceOverRunningValue; + + private: + UIView* view_; + UIWindow* window_; +}; + +class MockAccessibilityBridgeNoWindow : public AccessibilityBridgeIos { + public: + MockAccessibilityBridgeNoWindow() : observations({}) { + view_ = [[UIView alloc] initWithFrame:kScreenSize]; + } + bool isVoiceOverRunning() const override { return isVoiceOverRunningValue; } + UIView* view() const override { return view_; } + UIView* textInputView() override { return nil; } + void DispatchSemanticsAction(int32_t id, SemanticsAction action) override { + SemanticsActionObservation observation(id, action); + observations.push_back(observation); + } + void DispatchSemanticsAction(int32_t id, + SemanticsAction action, + fml::MallocMapping args) override { + SemanticsActionObservation observation(id, action); + observations.push_back(observation); + } + void AccessibilityObjectDidBecomeFocused(int32_t id) override {} + void AccessibilityObjectDidLoseFocus(int32_t id) override {} + std::shared_ptr GetPlatformViewsController() const override { + return nil; + } + std::vector observations; + bool isVoiceOverRunningValue; + + private: + UIView* view_; +}; +} // namespace +} // namespace flutter + +@interface SemanticsObject (Tests) +- (BOOL)accessibilityScrollToVisible; +- (BOOL)accessibilityScrollToVisibleWithChild:(id)child; +- (id)_accessibilityHitTest:(CGPoint)point withEvent:(UIEvent*)event; +@end + +#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_TEST_MOCKS_H_ diff --git a/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm new file mode 100644 index 0000000000000..0567e37c0e30e --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/SemanticsObjectTest_mrc.mm @@ -0,0 +1,89 @@ +// Copyright 2013 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 +#import + +#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTouchInterceptingView_Test.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/SemanticsObjectTestMocks.h" + +FLUTTER_ASSERT_NOT_ARC + +@interface SemanticsObjectTestMRC : XCTestCase +@end + +@implementation SemanticsObjectTestMRC + +- (void)testAccessibilityHitTestSearchCanReturnPlatformView { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + SemanticsObject* object0 = [[[SemanticsObject alloc] initWithBridge:bridge uid:0] autorelease]; + SemanticsObject* object1 = [[[SemanticsObject alloc] initWithBridge:bridge uid:1] autorelease]; + SemanticsObject* object3 = [[[SemanticsObject alloc] initWithBridge:bridge uid:3] autorelease]; + FlutterTouchInterceptingView* platformView = + [[[FlutterTouchInterceptingView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)] autorelease]; + FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer = + [[[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge + uid:1 + platformView:platformView] autorelease]; + + object0.children = @[ object1 ]; + object0.childrenInHitTestOrder = @[ object1 ]; + object1.children = @[ platformViewSemanticsContainer, object3 ]; + object1.childrenInHitTestOrder = @[ platformViewSemanticsContainer, object3 ]; + + flutter::SemanticsNode node0; + node0.id = 0; + node0.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node0.label = "0"; + [object0 setSemanticsNode:&node0]; + + flutter::SemanticsNode node1; + node1.id = 1; + node1.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node1.label = "1"; + [object1 setSemanticsNode:&node1]; + + flutter::SemanticsNode node2; + node2.id = 2; + node2.rect = SkRect::MakeXYWH(0, 0, 100, 100); + node2.label = "2"; + [platformViewSemanticsContainer setSemanticsNode:&node2]; + + flutter::SemanticsNode node3; + node3.id = 3; + node3.rect = SkRect::MakeXYWH(0, 0, 200, 200); + node3.label = "3"; + [object3 setSemanticsNode:&node3]; + + CGPoint point = CGPointMake(10, 10); + id hitTestResult = [object0 _accessibilityHitTest:point withEvent:nil]; + + XCTAssertEqual(hitTestResult, platformView); +} + +- (void)testFlutterPlatformViewSemanticsContainer { + fml::WeakPtrFactory factory( + new flutter::MockAccessibilityBridge()); + fml::WeakPtr bridge = factory.GetWeakPtr(); + FlutterTouchInterceptingView* platformView = + [[[FlutterTouchInterceptingView alloc] init] autorelease]; + @autoreleasepool { + FlutterPlatformViewSemanticsContainer* container = + [[[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:bridge + uid:1 + platformView:platformView] autorelease]; + XCTAssertEqualObjects(platformView.accessibilityContainer, container); + XCTAssertEqual(platformView.retainCount, 2u); + } + // Check if there's no more strong references to `platformView` after container and platformView + // are released. + XCTAssertEqual(platformView.retainCount, 1u); +} + +@end diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index bf19109e92d07..27b33ad4ca3d4 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -279,7 +279,7 @@ static void ReplaceSemanticsObject(SemanticsObject* oldObject, return [[[FlutterPlatformViewSemanticsContainer alloc] initWithBridge:weak_ptr uid:node.id - platformView:weak_ptr->GetPlatformViewsController()->GetPlatformViewByID( + platformView:weak_ptr->GetPlatformViewsController()->GetFlutterTouchInterceptingViewByID( node.platformViewId)] autorelease]; } else { return [[[FlutterSemanticsObject alloc] initWithBridge:weak_ptr uid:node.id] autorelease]; From 249cc9b86c45acb7e32b4097bc8a5059b91c888e Mon Sep 17 00:00:00 2001 From: godofredoc Date: Wed, 11 Oct 2023 16:12:04 -0700 Subject: [PATCH 04/31] Update dart to 620c1721 (#46799) Update dart sdk to Dart 3.2.0-210.2.beta. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 1dda1ab7141a5..d014d94c5809c 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '5c23602e3e22df0c0cbab680d3955ee288122acd', + 'dart_revision': '620c172167c07c66324778ce4122b4119abebcca', # 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_dart b/ci/licenses_golden/licenses_dart index f463b1c0dbf13..d2b187ad5e479 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: fdaa9367efe1c4a57d9abc0eb91db374 +Signature: ac9f081e16efc618b80b9d4827a5aeb1 ==================================================================================================== LIBRARY: dart From 54d5d0f07bff5bb8560d1b9a53d391f6caa584dd Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 17 Oct 2023 05:23:15 -0700 Subject: [PATCH 05/31] [CP][Impeller] Fix framebuffer blend UVs. (#46489) (#46775) CP for https://github.com/flutter/flutter/issues/136371 --- impeller/aiks/aiks_unittests.cc | 20 ++++++++++++++++++ .../contents/framebuffer_blend_contents.cc | 21 +++++++------------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 4950aae8496fc..841fca9a9297a 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1580,6 +1580,26 @@ TEST_P(AiksTest, DrawPaintWithAdvancedBlendOverFilter) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, DrawAdvancedBlendPartlyOffscreen) { + std::vector colors = {Color{0.9568, 0.2627, 0.2118, 1.0}, + Color{0.1294, 0.5882, 0.9529, 1.0}}; + std::vector stops = {0.0, 1.0}; + + Paint paint = { + .color_source = ColorSource::MakeLinearGradient( + {0, 0}, {100, 100}, std::move(colors), std::move(stops), + Entity::TileMode::kRepeat, Matrix::MakeScale(Vector3(0.3, 0.3, 0.3))), + .blend_mode = BlendMode::kLighten, + }; + + Canvas canvas; + canvas.DrawPaint({.color = Color::Blue()}); + canvas.Scale(Vector2(2, 2)); + canvas.ClipRect(Rect::MakeLTRB(0, 0, 200, 200)); + canvas.DrawCircle({100, 100}, 100, paint); + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + #define BLEND_MODE_TUPLE(blend_mode) {#blend_mode, BlendMode::k##blend_mode}, struct BlendModeSelection { diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc index 3ced8b52d9d76..c571c0a349a24 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -48,6 +48,7 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, std::nullopt, // sampler_descriptor true, // msaa_enabled "FramebufferBlendContents Snapshot"); // label + if (!src_snapshot.has_value()) { return true; } @@ -56,21 +57,16 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, return true; } Rect src_coverage = coverage.value(); - auto maybe_src_uvs = src_snapshot->GetCoverageUVs(src_coverage); - if (!maybe_src_uvs.has_value()) { - return true; - } - std::array src_uvs = maybe_src_uvs.value(); auto size = src_coverage.size; VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ - {Point(0, 0), src_uvs[0]}, - {Point(size.width, 0), src_uvs[1]}, - {Point(size.width, size.height), src_uvs[3]}, - {Point(0, 0), src_uvs[0]}, - {Point(size.width, size.height), src_uvs[3]}, - {Point(0, size.height), src_uvs[2]}, + {Point(0, 0), Point(0, 0)}, + {Point(size.width, 0), Point(1, 0)}, + {Point(size.width, size.height), Point(1, 1)}, + {Point(0, 0), Point(0, 0)}, + {Point(size.width, size.height), Point(1, 1)}, + {Point(0, size.height), Point(0, 1)}, }); auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer); @@ -147,8 +143,7 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, FS::BindTextureSamplerSrc(cmd, src_snapshot->texture, src_sampler); frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * - entity.GetTransformation() * - Matrix::MakeTranslation(src_coverage.origin); + src_snapshot->transform; frame_info.src_y_coord_scale = src_snapshot->texture->GetYCoordScale(); VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info)); From 39078da3f0adfe889dfb36be6c6cd3862cd49703 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 17 Oct 2023 07:45:01 -0700 Subject: [PATCH 06/31] [CP][Impeller] Apply the transform to PointFieldGeometry coverage (#46428) (#46776) CP for https://github.com/flutter/flutter/issues/136372 --- impeller/entity/entity_unittests.cc | 8 ++++++++ impeller/entity/geometry/point_field_geometry.cc | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index c76ece221dbd8..ca094aa0fe54f 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -2417,6 +2417,14 @@ TEST_P(EntityTest, PointFieldGeometryDivisions) { ASSERT_EQ(PointFieldGeometry::ComputeCircleDivisions(20000.0, true), 140u); } +TEST_P(EntityTest, PointFieldGeometryCoverage) { + std::vector points = {{10, 20}, {100, 200}}; + auto geometry = Geometry::MakePointField(points, 5.0, false); + ASSERT_EQ(*geometry->GetCoverage(Matrix()), Rect::MakeLTRB(5, 15, 105, 205)); + ASSERT_EQ(*geometry->GetCoverage(Matrix::MakeTranslation({30, 0, 0})), + Rect::MakeLTRB(35, 15, 135, 205)); +} + TEST_P(EntityTest, ColorFilterContentsWithLargeGeometry) { Entity entity; entity.SetTransformation(Matrix::MakeScale(GetContentScale())); diff --git a/impeller/entity/geometry/point_field_geometry.cc b/impeller/entity/geometry/point_field_geometry.cc index 81fe3885d916b..9821bad91ad7b 100644 --- a/impeller/entity/geometry/point_field_geometry.cc +++ b/impeller/entity/geometry/point_field_geometry.cc @@ -287,8 +287,9 @@ std::optional PointFieldGeometry::GetCoverage( right = std::max(right, it->x); bottom = std::max(bottom, it->y); } - return Rect::MakeLTRB(left - radius_, top - radius_, right + radius_, - bottom + radius_); + auto coverage = Rect::MakeLTRB(left - radius_, top - radius_, + right + radius_, bottom + radius_); + return coverage.TransformBounds(transform); } return std::nullopt; } From 84d95624a3d55a2071add09944ed70517d1a38bc Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 17 Oct 2023 07:45:03 -0700 Subject: [PATCH 07/31] [CP][Impeller] Fixed subpass filter coverage with image filters (#46431). (#46777) CP for https://github.com/flutter/flutter/issues/136373 --- impeller/aiks/aiks_unittests.cc | 19 +++++++++++++++++++ impeller/entity/entity_pass.cc | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 841fca9a9297a..2a5dec3e942b4 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -3582,6 +3582,25 @@ TEST_P(AiksTest, ClearBlend) { clear.blend_mode = BlendMode::kClear; canvas.DrawCircle(Point::MakeXY(300.0, 300.0), 200.0, clear); +} + +TEST_P(AiksTest, MatrixImageFilterMagnify) { + Canvas canvas; + canvas.Scale(GetContentScale()); + auto image = std::make_shared(CreateTextureForFixture("airplane.jpg")); + canvas.Translate({600, -200}); + canvas.SaveLayer({ + .image_filter = std::make_shared( + Matrix{ + 2, 0, 0, 0, // + 0, 2, 0, 0, // + 0, 0, 2, 0, // + 0, 0, 0, 1 // + }, + SamplerDescriptor{}), + }); + canvas.DrawImage(image, {0, 0}, Paint{.color = Color(1.0, 1.0, 1.0, 0.5)}); + canvas.Restore(); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 0d91112369ae7..bc312cd6bcb1a 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -202,8 +202,8 @@ std::optional EntityPass::GetSubpassCoverage( // has deviated too much from the parent pass to safely intersect with the // pass coverage limit. coverage_limit = - (image_filter && image_filter->IsTranslationOnly() ? std::nullopt - : coverage_limit); + (image_filter && !image_filter->IsTranslationOnly() ? std::nullopt + : coverage_limit); auto entities_coverage = subpass.GetElementsCoverage(coverage_limit); // The entities don't cover anything. There is nothing to do. From 731c67873817b0b056e8c2d31ae82212b978ddf9 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Tue, 17 Oct 2023 08:14:47 -0700 Subject: [PATCH 08/31] Cherrypick disable hardware buffer platform views for 3.16 (#46968) --- .../io/flutter/plugin/platform/PlatformViewsController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 0e7ad70aee29d..b5559a3a9e23a 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -147,7 +147,7 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega // Whether software rendering is used. private boolean usesSoftwareRendering = false; - private static boolean enableHardwareBufferRenderingTarget = true; + private static boolean enableHardwareBufferRenderingTarget = false; private final PlatformViewsChannel.PlatformViewsHandler channelHandler = new PlatformViewsChannel.PlatformViewsHandler() { From 91cde06da08323f25bd4bcc4a1832862f2b58c08 Mon Sep 17 00:00:00 2001 From: Kevin Chisholm Date: Thu, 19 Oct 2023 16:06:37 -0500 Subject: [PATCH 09/31] [flutter_releases] Flutter beta 3.16.0-0.3.pre Engine Cherrypicks (#47107) # Flutter beta 3.16.0-0.3.pre Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@668bef34e --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index d014d94c5809c..742d37d6273e2 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '620c172167c07c66324778ce4122b4119abebcca', + 'dart_revision': '668bef34e453fc84ab9fa572d917110b51fa88eb', # 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_dart b/ci/licenses_golden/licenses_dart index d2b187ad5e479..c49c79f508ad0 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: ac9f081e16efc618b80b9d4827a5aeb1 +Signature: 405b8ee3823b5f5570f4fba28f153a5b ==================================================================================================== LIBRARY: dart From abdaabc6dc88e20dd0fe290a2d3dfcac03b2706f Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Tue, 31 Oct 2023 15:04:05 -0700 Subject: [PATCH 10/31] [flutter_releases] Flutter beta 3.16.0-0.4.pre Engine Cherrypicks (#47513) # Flutter beta 3.16.0-0.4.pre Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@a30d2edb8 --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 742d37d6273e2..35c298fadd2d0 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '668bef34e453fc84ab9fa572d917110b51fa88eb', + 'dart_revision': 'a30d2edb8118b3b19793931f7832c8f7260b3509', # 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_dart b/ci/licenses_golden/licenses_dart index c49c79f508ad0..814964d0524c9 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 405b8ee3823b5f5570f4fba28f153a5b +Signature: 323f1797e915f510d400d94a16cacb78 ==================================================================================================== LIBRARY: dart From 2dd11e3383f7f0e488c05a6be74bad7d695f07e9 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 2 Nov 2023 08:18:03 -0700 Subject: [PATCH 11/31] [CP][Impeller] fix clear color optimization for large subpasses. (#46887) (#47577) Fixes https://github.com/flutter/flutter/issues/136507 . The cause of this bug is that we use different sizes to compute the clear color value when constructing the render target and when skipping entities: https://github.com/flutter/engine/blob/main/impeller/entity/entity_pass.cc#L632 https://github.com/flutter/engine/blob/main/impeller/entity/entity_pass.cc#L731 and https://github.com/flutter/engine/blob/main/impeller/entity/entity_pass.cc#L900C3-L900C3 Either the former should use the root pass size or the later should use the subpass size. This usually isn't an issue because if something covers the root pass size it generally always covers the subpass size. But during the page transition, the scaled subpass ends up slightly bigger than the root pass size and so these conditions are mismatched: Subpass size: (1550, 3188) root pass size (1440, 3036) I think subpass size is correct. If the subpass is larger than the parent, then checking the parent size will give incorrect result. --- impeller/aiks/aiks_unittests.cc | 24 +++++++++++++++++++++++- impeller/entity/entity_pass.cc | 5 +++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 2a5dec3e942b4..72679b05feb12 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -2106,9 +2106,12 @@ TEST_P(AiksTest, CanRenderClippedLayers) { canvas.DrawRect(Rect::MakeSize(Size{400, 400}), {.color = Color::White()}); // Fill the layer with green, but do so with a color blend that can't be // collapsed into the parent pass. + // TODO(jonahwilliams): this blend mode was changed from color burn to + // hardlight to work around https://github.com/flutter/flutter/issues/136554 + // . canvas.DrawRect( Rect::MakeSize(Size{400, 400}), - {.color = Color::Green(), .blend_mode = BlendMode::kColorBurn}); + {.color = Color::Green(), .blend_mode = BlendMode::kHardLight}); } ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); @@ -3605,5 +3608,24 @@ TEST_P(AiksTest, MatrixImageFilterMagnify) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +// This should be solid red, if you see a little red box this is broken. +TEST_P(AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass) { + Canvas canvas; + canvas.Scale(GetContentScale()); + canvas.DrawRect(Rect::MakeLTRB(200, 200, 300, 300), {.color = Color::Red()}); + canvas.SaveLayer({ + .image_filter = std::make_shared( + Matrix::MakeScale({2, 2, 1}), SamplerDescriptor{}), + }); + // Draw a rectangle that would fully cover the parent pass size, but not + // the subpass that it is rendered in. + canvas.DrawRect(Rect::MakeLTRB(0, 0, 400, 400), {.color = Color::Green()}); + // Draw a bigger rectangle to force the subpass to be bigger. + canvas.DrawRect(Rect::MakeLTRB(0, 0, 800, 800), {.color = Color::Red()}); + canvas.Restore(); + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index bc312cd6bcb1a..64580febfcf24 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -720,9 +720,10 @@ bool EntityPass::OnRender( VALIDATION_LOG << SPrintF("Pass context invalid (Depth=%d)", pass_depth); return false; } + auto clear_color_size = pass_target.GetRenderTarget().GetRenderTargetSize(); if (!collapsed_parent_pass && - !GetClearColor(root_pass_size).IsTransparent()) { + !GetClearColor(clear_color_size).IsTransparent()) { // Force the pass context to create at least one new pass if the clear color // is present. pass_context.GetRenderPass(pass_depth); @@ -892,7 +893,7 @@ bool EntityPass::OnRender( // Skip elements that are incorporated into the clear color. if (is_collapsing_clear_colors) { auto [entity_color, _] = - ElementAsBackgroundColor(element, root_pass_size); + ElementAsBackgroundColor(element, clear_color_size); if (entity_color.has_value()) { continue; } From ab14aba1d5564df418f0e87f6772916c80a9a00a Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Thu, 2 Nov 2023 08:32:16 -0700 Subject: [PATCH 12/31] [CP][Impeller] Disable raster stats service protocol. (#47206) (#47578) As far as I can tell, this functionality has _always_ been falling back to software rendering with Skia when Impeller was enabled. This is at best extremely misleading. Since I started putting Impeller specific objects in the display list it introduced crashes, and must be disabled. Fixes https://github.com/flutter/flutter/issues/136847 --- flow/layers/layer_tree.h | 2 ++ shell/common/shell.cc | 7 ++++++ shell/common/shell_unittests.cc | 41 +++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 5f573da2099a0..686abbace2e0e 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -70,6 +70,8 @@ class LayerTree { /// When `Paint` is called, if leaf layer tracing is enabled, additional /// metadata around raterization of leaf layers is collected. /// + /// This is not supported in the Impeller backend. + /// /// See: `LayerSnapshotStore` void enable_leaf_layer_tracing(bool enable) { enable_leaf_layer_tracing_ = enable; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 82db9dea4ff64..5164d1a1db176 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1968,6 +1968,13 @@ bool Shell::OnServiceProtocolRenderFrameWithRasterStats( rapidjson::Document* response) { FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread()); + // Impeller does not support this protocol method. + if (io_manager_->GetImpellerContext()) { + const char* error = "Raster status not supported on Impeller backend."; + ServiceProtocolFailureError(response, error); + return false; + } + // TODO(dkwingsmt): This method only handles view #0, including the snapshot // and the frame size. We need to adapt this method to multi-view. // https://github.com/flutter/flutter/issues/131892 diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 2371fa9113aa7..11d911d2bc356 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -2713,6 +2713,47 @@ TEST_F(ShellTest, OnServiceProtocolRenderFrameWithRasterStatsWorks) { DestroyShell(std::move(shell)); } +#if defined(FML_OS_MACOSX) +TEST_F(ShellTest, OnServiceProtocolRenderFrameWithRasterStatsDisableImpeller) { + auto settings = CreateSettingsForFixture(); + settings.enable_impeller = true; + std::unique_ptr shell = CreateShell({ + .settings = settings, + .platform_view_create_callback = ShellTestPlatformViewBuilder({ + .rendering_backend = + ShellTestPlatformView::BackendType::kMetalBackend, + }), + }); + + // Create the surface needed by rasterizer + PlatformViewNotifyCreated(shell.get()); + + auto configuration = RunConfiguration::InferFromSettings(settings); + configuration.SetEntrypoint("scene_with_red_box"); + + RunEngine(shell.get(), std::move(configuration)); + PumpOneFrame(shell.get()); + + ServiceProtocol::Handler::ServiceProtocolMap empty_params; + rapidjson::Document document; + OnServiceProtocol( + shell.get(), ServiceProtocolEnum::kRenderFrameWithRasterStats, + shell->GetTaskRunners().GetRasterTaskRunner(), empty_params, &document); + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + document.Accept(writer); + std::string actual_json = buffer.GetString(); + std::string expected_json = + "{\"code\":-32000,\"message\":\"Raster status not supported on Impeller " + "backend.\"}"; + + ASSERT_EQ(actual_json, expected_json); + + PlatformViewNotifyDestroyed(shell.get()); + DestroyShell(std::move(shell)); +} +#endif // FML_OS_MACOSX + // TODO(https://github.com/flutter/flutter/issues/100273): Disabled due to // flakiness. // TODO(https://github.com/flutter/flutter/issues/100299): Fix it when From 768db84d8f83f5cd2fc36f18066604961a8e0083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20S=20Guerrero?= Date: Mon, 13 Nov 2023 14:41:05 -0800 Subject: [PATCH 13/31] [flutter_releases] Flutter stable 3.16.0 Engine Cherrypicks (#47990) # Flutter stable 3.16.0 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@181ac6392 --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 35c298fadd2d0..f9a9f163ed4ac 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'a30d2edb8118b3b19793931f7832c8f7260b3509', + 'dart_revision': '181ac63923dfcab1c8f21a2998b3ecad68c07644', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py From 74d16627b940bb15e50891f82cad6c3e3465bd6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20S=20Guerrero?= Date: Tue, 14 Nov 2023 13:27:59 -0800 Subject: [PATCH 14/31] [flutter_releases] Flutter stable 3.16.0 Engine Cherrypicks (#48029) # Flutter stable 3.16.0 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@525f5bb94 --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index f9a9f163ed4ac..fdb64209c77f2 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '181ac63923dfcab1c8f21a2998b3ecad68c07644', + 'dart_revision': '525f5bb94e01a9e5c6c9ecb9b7919b717020d525', # 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_dart b/ci/licenses_golden/licenses_dart index 814964d0524c9..3ba193d720f20 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 323f1797e915f510d400d94a16cacb78 +Signature: 49e9c2dad10cc40f88d2ac86b7cf26df ==================================================================================================== LIBRARY: dart From f4f0c1d5d5ec25ae76e7e3f76081037ac15f4d8e Mon Sep 17 00:00:00 2001 From: hellohuanlin <41930132+hellohuanlin@users.noreply.github.com> Date: Wed, 15 Nov 2023 16:48:29 -0800 Subject: [PATCH 15/31] [CP (beta)] [ios17][text_input]fix ios 17.0 keyboard freeze when switching languages (#48041) CP for https://github.com/flutter/engine/pull/47566 *List which issues are fixed by this PR. You must list at least one issue.* https://github.com/flutter/flutter/issues/134716 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- .../Source/FlutterTextInputPlugin.mm | 18 ++++++- .../Source/FlutterTextInputPluginTest.mm | 48 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index f02ab85da7ece..09946dc0e50e1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -602,7 +602,7 @@ - (UITextRange*)rangeEnclosingPosition:(UITextPosition*)position case UITextGranularityLine: // The default UITextInputStringTokenizer does not handle line granularity // correctly. We need to implement our own line tokenizer. - result = [self lineEnclosingPosition:position]; + result = [self lineEnclosingPosition:position inDirection:direction]; break; case UITextGranularityCharacter: case UITextGranularityWord: @@ -618,7 +618,21 @@ - (UITextRange*)rangeEnclosingPosition:(UITextPosition*)position return result; } -- (UITextRange*)lineEnclosingPosition:(UITextPosition*)position { +- (UITextRange*)lineEnclosingPosition:(UITextPosition*)position + inDirection:(UITextDirection)direction { + // TODO(hellohuanlin): remove iOS 17 check. The same logic should apply to older iOS version. + if (@available(iOS 17.0, *)) { + // According to the API doc if the text position is at a text-unit boundary, it is considered + // enclosed only if the next position in the given direction is entirely enclosed. Link: + // https://developer.apple.com/documentation/uikit/uitextinputtokenizer/1614464-rangeenclosingposition?language=objc + FlutterTextPosition* flutterPosition = (FlutterTextPosition*)position; + if (flutterPosition.index > _textInputView.text.length || + (flutterPosition.index == _textInputView.text.length && + direction == UITextStorageDirectionForward)) { + return nil; + } + } + // Gets the first line break position after the input position. NSString* textAfter = [_textInputView textInRange:[_textInputView textRangeFromPosition:position diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index f18357acf0ffc..8a6cc6b53a305 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -2660,6 +2660,54 @@ - (void)testFlutterTokenizerCanParseLines { XCTAssertEqual(range.range.length, 20u); } +- (void)testFlutterTokenizerLineEnclosingEndOfDocumentInBackwardDirectionShouldNotReturnNil { + FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin]; + [inputView insertText:@"0123456789\n012345"]; + id tokenizer = [inputView tokenizer]; + + FlutterTextRange* range = + (FlutterTextRange*)[tokenizer rangeEnclosingPosition:[inputView endOfDocument] + withGranularity:UITextGranularityLine + inDirection:UITextStorageDirectionBackward]; + XCTAssertEqual(range.range.location, 11u); + XCTAssertEqual(range.range.length, 6u); +} + +- (void)testFlutterTokenizerLineEnclosingEndOfDocumentInForwardDirectionShouldReturnNilOnIOS17 { + FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin]; + [inputView insertText:@"0123456789\n012345"]; + id tokenizer = [inputView tokenizer]; + + FlutterTextRange* range = + (FlutterTextRange*)[tokenizer rangeEnclosingPosition:[inputView endOfDocument] + withGranularity:UITextGranularityLine + inDirection:UITextStorageDirectionForward]; + if (@available(iOS 17.0, *)) { + XCTAssertNil(range); + } else { + XCTAssertEqual(range.range.location, 11u); + XCTAssertEqual(range.range.length, 6u); + } +} + +- (void)testFlutterTokenizerLineEnclosingOutOfRangePositionShouldReturnNilOnIOS17 { + FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin]; + [inputView insertText:@"0123456789\n012345"]; + id tokenizer = [inputView tokenizer]; + + FlutterTextPosition* position = [FlutterTextPosition positionWithIndex:100]; + FlutterTextRange* range = + (FlutterTextRange*)[tokenizer rangeEnclosingPosition:position + withGranularity:UITextGranularityLine + inDirection:UITextStorageDirectionForward]; + if (@available(iOS 17.0, *)) { + XCTAssertNil(range); + } else { + XCTAssertEqual(range.range.location, 0u); + XCTAssertEqual(range.range.length, 0u); + } +} + - (void)testFlutterTextInputPluginRetainsFlutterTextInputView { FlutterViewController* flutterViewController = [[FlutterViewController alloc] init]; FlutterTextInputPlugin* myInputPlugin = [[FlutterTextInputPlugin alloc] initWithDelegate:engine]; From 22b600f240548c1cf6f5d3f9ae65a5c9e51bc443 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Wed, 22 Nov 2023 11:36:53 -0800 Subject: [PATCH 16/31] [flutter_releases] Flutter stable 3.16.1 Engine Cherrypicks (#48320) # Flutter stable 3.16.1 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@c0cc7a352 --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index fdb64209c77f2..9313f464463c8 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '525f5bb94e01a9e5c6c9ecb9b7919b717020d525', + 'dart_revision': 'c0cc7a352a4e546e652a0ce9fb4be665c880e2c8', # 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_dart b/ci/licenses_golden/licenses_dart index 3ba193d720f20..23fb50ae1ec1b 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 49e9c2dad10cc40f88d2ac86b7cf26df +Signature: 080ba1d4add6ac56042fbf6155e49f1f ==================================================================================================== LIBRARY: dart From 75219481ac23c472660484db4b7d82230872ee50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20S=20Guerrero?= Date: Tue, 28 Nov 2023 13:30:11 -0600 Subject: [PATCH 17/31] [flutter_releases] Flutter stable 3.16.2 Engine Cherrypicks (#48464) # Flutter stable 3.16.2 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@a58c5ab91 --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 9313f464463c8..ea6773d77f51b 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'c0cc7a352a4e546e652a0ce9fb4be665c880e2c8', + 'dart_revision': 'a58c5ab91e954b12a56b51f7ddc55b257dfd0db4', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py From cd424ac7dd33178b43366e73a1bd5d290e1e27cf Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 28 Nov 2023 11:40:02 -0800 Subject: [PATCH 18/31] [CP][Impeller] revert non-zero tessellation optimization. (#48234) (#48459) Fixes https://github.com/flutter/flutter/issues/138598 Cherry pick request: https://github.com/flutter/flutter/issues/139146 --- impeller/tessellator/tessellator.cc | 191 ++++++------------ impeller/tessellator/tessellator.h | 4 - impeller/tessellator/tessellator_unittests.cc | 21 -- 3 files changed, 66 insertions(+), 150 deletions(-) diff --git a/impeller/tessellator/tessellator.cc b/impeller/tessellator/tessellator.cc index f7c80fe747ea0..c8cfdbeff819f 100644 --- a/impeller/tessellator/tessellator.cc +++ b/impeller/tessellator/tessellator.cc @@ -78,140 +78,81 @@ Tessellator::Result Tessellator::Tessellate( constexpr int kVertexSize = 2; constexpr int kPolygonSize = 3; - // If we have a larger polyline and the fill type is non-zero, we can split - // the tessellation up per contour. Since in general the complexity is at - // least nlog(n), this speeds up the processes substantially. - if (polyline.contours.size() > kMultiContourThreshold && - fill_type == FillType::kNonZero) { - std::vector points; - std::vector data; + //---------------------------------------------------------------------------- + /// Feed contour information to the tessellator. + /// + static_assert(sizeof(Point) == 2 * sizeof(float)); + for (size_t contour_i = 0; contour_i < polyline.contours.size(); + contour_i++) { + size_t start_point_index, end_point_index; + std::tie(start_point_index, end_point_index) = + polyline.GetContourPointBounds(contour_i); + + ::tessAddContour(tessellator, // the C tessellator + kVertexSize, // + polyline.points.data() + start_point_index, // + sizeof(Point), // + end_point_index - start_point_index // + ); + } - //---------------------------------------------------------------------------- - /// Feed contour information to the tessellator. - /// - size_t total = 0u; - static_assert(sizeof(Point) == 2 * sizeof(float)); - for (size_t contour_i = 0; contour_i < polyline.contours.size(); - contour_i++) { - size_t start_point_index, end_point_index; - std::tie(start_point_index, end_point_index) = - polyline.GetContourPointBounds(contour_i); - - ::tessAddContour(tessellator, // the C tessellator - kVertexSize, // - polyline.points.data() + start_point_index, // - sizeof(Point), // - end_point_index - start_point_index // - ); - - //---------------------------------------------------------------------------- - /// Let's tessellate. - /// - auto result = ::tessTesselate(tessellator, // tessellator - ToTessWindingRule(fill_type), // winding - TESS_POLYGONS, // element type - kPolygonSize, // polygon size - kVertexSize, // vertex size - nullptr // normal (null is automatic) - ); - - if (result != 1) { - return Result::kTessellationError; - } - - int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; - auto vertices = tessGetVertices(tessellator); - for (int i = 0; i < vertex_item_count; i += 2) { - points.emplace_back(vertices[i], vertices[i + 1]); - } - - int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - auto elements = tessGetElements(tessellator); - total += element_item_count; - for (int i = 0; i < element_item_count; i++) { - data.emplace_back(points[elements[i]].x); - data.emplace_back(points[elements[i]].y); - } - points.clear(); + //---------------------------------------------------------------------------- + /// Let's tessellate. + /// + auto result = ::tessTesselate(tessellator, // tessellator + ToTessWindingRule(fill_type), // winding + TESS_POLYGONS, // element type + kPolygonSize, // polygon size + kVertexSize, // vertex size + nullptr // normal (null is automatic) + ); + + if (result != 1) { + return Result::kTessellationError; + } + + int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; + + // We default to using a 16bit index buffer, but in cases where we generate + // more tessellated data than this can contain we need to fall back to + // dropping the index buffer entirely. Instead code could instead switch to + // a uint32 index buffer, but this is done for simplicity with the other + // fast path above. + if (element_item_count < USHRT_MAX) { + int vertex_item_count = tessGetVertexCount(tessellator); + auto vertices = tessGetVertices(tessellator); + auto elements = tessGetElements(tessellator); + + // libtess uses an int index internally due to usage of -1 as a sentinel + // value. + std::vector indices(element_item_count); + for (int i = 0; i < element_item_count; i++) { + indices[i] = static_cast(elements[i]); } - if (!callback(data.data(), total, nullptr, 0u)) { + if (!callback(vertices, vertex_item_count, indices.data(), + element_item_count)) { return Result::kInputError; } } else { - //---------------------------------------------------------------------------- - /// Feed contour information to the tessellator. - /// - static_assert(sizeof(Point) == 2 * sizeof(float)); - for (size_t contour_i = 0; contour_i < polyline.contours.size(); - contour_i++) { - size_t start_point_index, end_point_index; - std::tie(start_point_index, end_point_index) = - polyline.GetContourPointBounds(contour_i); - - ::tessAddContour(tessellator, // the C tessellator - kVertexSize, // - polyline.points.data() + start_point_index, // - sizeof(Point), // - end_point_index - start_point_index // - ); - } - - //---------------------------------------------------------------------------- - /// Let's tessellate. - /// - auto result = ::tessTesselate(tessellator, // tessellator - ToTessWindingRule(fill_type), // winding - TESS_POLYGONS, // element type - kPolygonSize, // polygon size - kVertexSize, // vertex size - nullptr // normal (null is automatic) - ); + std::vector points; + std::vector data; - if (result != 1) { - return Result::kTessellationError; + int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; + auto vertices = tessGetVertices(tessellator); + points.reserve(vertex_item_count); + for (int i = 0; i < vertex_item_count; i += 2) { + points.emplace_back(vertices[i], vertices[i + 1]); } int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - - // We default to using a 16bit index buffer, but in cases where we generate - // more tessellated data than this can contain we need to fall back to - // dropping the index buffer entirely. Instead code could instead switch to - // a uint32 index buffer, but this is done for simplicity with the other - // fast path above. - if (element_item_count < USHRT_MAX) { - int vertex_item_count = tessGetVertexCount(tessellator); - auto vertices = tessGetVertices(tessellator); - auto elements = tessGetElements(tessellator); - - // libtess uses an int index internally due to usage of -1 as a sentinel - // value. - std::vector indices(element_item_count); - for (int i = 0; i < element_item_count; i++) { - indices[i] = static_cast(elements[i]); - } - if (!callback(vertices, vertex_item_count, indices.data(), - element_item_count)) { - return Result::kInputError; - } - } else { - std::vector points; - std::vector data; - - int vertex_item_count = tessGetVertexCount(tessellator) * kVertexSize; - auto vertices = tessGetVertices(tessellator); - for (int i = 0; i < vertex_item_count; i += 2) { - points.emplace_back(vertices[i], vertices[i + 1]); - } - - int element_item_count = tessGetElementCount(tessellator) * kPolygonSize; - auto elements = tessGetElements(tessellator); - for (int i = 0; i < element_item_count; i++) { - data.emplace_back(points[elements[i]].x); - data.emplace_back(points[elements[i]].y); - } - if (!callback(data.data(), element_item_count, nullptr, 0u)) { - return Result::kInputError; - } + auto elements = tessGetElements(tessellator); + data.reserve(element_item_count); + for (int i = 0; i < element_item_count; i++) { + data.emplace_back(points[elements[i]].x); + data.emplace_back(points[elements[i]].y); + } + if (!callback(data.data(), element_item_count, nullptr, 0u)) { + return Result::kInputError; } } diff --git a/impeller/tessellator/tessellator.h b/impeller/tessellator/tessellator.h index b6d444c5a81ba..7cd8690da9fb4 100644 --- a/impeller/tessellator/tessellator.h +++ b/impeller/tessellator/tessellator.h @@ -44,10 +44,6 @@ class Tessellator { ~Tessellator(); - /// @brief An arbitrary value to determine when a multi-contour non-zero fill - /// path should be split into multiple tessellations. - static constexpr size_t kMultiContourThreshold = 30u; - /// @brief A callback that returns the results of the tessellation. /// /// The index buffer may not be populated, in which case [indices] will diff --git a/impeller/tessellator/tessellator_unittests.cc b/impeller/tessellator/tessellator_unittests.cc index 8fca675a9a9a6..f3af64c7ff4cb 100644 --- a/impeller/tessellator/tessellator_unittests.cc +++ b/impeller/tessellator/tessellator_unittests.cc @@ -88,27 +88,6 @@ TEST(TessellatorTest, TessellatorBuilderReturnsCorrectResultStatus) { ASSERT_EQ(result, Tessellator::Result::kInputError); } - // More than 30 contours, non-zero fill mode. - { - Tessellator t; - PathBuilder builder = {}; - for (auto i = 0u; i < Tessellator::kMultiContourThreshold + 1; i++) { - builder.AddCircle(Point(i, i), 4); - } - auto polyline = builder.TakePath().CreatePolyline(1.0f); - bool no_indices = false; - Tessellator::Result result = t.Tessellate( - FillType::kNonZero, polyline, - [&no_indices](const float* vertices, size_t vertices_count, - const uint16_t* indices, size_t indices_count) { - no_indices = indices == nullptr; - return true; - }); - - ASSERT_TRUE(no_indices); - ASSERT_EQ(result, Tessellator::Result::kSuccess); - } - // More than uint16 points, odd fill mode. { Tessellator t; From cf7a9d0800f2a5da166dbe0eb9fb2476018269b1 Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Wed, 29 Nov 2023 11:08:36 -0800 Subject: [PATCH 19/31] [CP][Impeller] Switched to static linked libc++ in vulkan validation layers. (#48499) CP of the flutter/engine part of https://github.com/flutter/engine/pull/48290. --- DEPS | 2 +- shell/platform/android/BUILD.gn | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/DEPS b/DEPS index ea6773d77f51b..fd040621e8212 100644 --- a/DEPS +++ b/DEPS @@ -262,7 +262,7 @@ allowed_hosts = [ ] deps = { - 'src': 'https://github.com/flutter/buildroot.git' + '@' + '9780f253156165c515962f5f0c56235d34617689', + 'src': 'https://github.com/flutter/buildroot.git' + '@' + 'f27d99b4428dea312646130d60c33a2d38fa9dc6', # Fuchsia compatibility # diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 06e4c9de02985..d9f2774afb903 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -507,13 +507,9 @@ action("android_jar") { "--native_lib", rebase_path("$validation_layer_out_dir/libVkLayer_khronos_validation.so"), ] - if (current_cpu == "arm64") { - args += [ - "--native_lib", - rebase_path("$android_libcpp_root/libs/arm64-v8a/libc++_shared.so", - root_build_dir), - ] - } else { + if (current_cpu != "arm64") { + # This may not be necessarily required anymore. It was kept to maintain + # old behavior. assert(false, "Validation layers not supported for arch.") } } From 5a118668a4547a11996ab9cb9a78ae47edd3b180 Mon Sep 17 00:00:00 2001 From: LouiseHsu Date: Thu, 30 Nov 2023 14:51:56 -0800 Subject: [PATCH 20/31] [CP] Fix crash on choosing share in selection controls on ipad (#48427) Fixes https://github.com/flutter/flutter/issues/138550 Original PR: https://github.com/flutter/engine/pull/48220 --- .../framework/Source/FlutterPlatformPlugin.mm | 30 +++++++++++++++ .../Source/FlutterPlatformPluginTest.mm | 37 +++++++++++++++++++ .../framework/Source/FlutterTextInputPlugin.h | 4 ++ 3 files changed, 71 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 722571bda0a03..586f1c36b79f4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -10,6 +10,8 @@ #import #include "flutter/fml/logging.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/UIViewController+FlutterScreenAndSceneIfLoaded.h" @@ -154,10 +156,38 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - (void)showShareViewController:(NSString*)content { UIViewController* engineViewController = [_engine.get() viewController]; + NSArray* itemsToShare = @[ content ?: [NSNull null] ]; UIActivityViewController* activityViewController = [[[UIActivityViewController alloc] initWithActivityItems:itemsToShare applicationActivities:nil] autorelease]; + + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + // On iPad, the share screen is presented in a popover view, and requires a + // sourceView and sourceRect + FlutterTextInputPlugin* _textInputPlugin = [_engine.get() textInputPlugin]; + UITextRange* range = _textInputPlugin.textInputView.selectedTextRange; + + // firstRectForRange cannot be used here as it's current implementation does + // not always return the full rect of the range. + CGRect firstRect = [(FlutterTextInputView*)_textInputPlugin.textInputView + caretRectForPosition:(FlutterTextPosition*)range.start]; + CGRect transformedFirstRect = [(FlutterTextInputView*)_textInputPlugin.textInputView + localRectFromFrameworkTransform:firstRect]; + CGRect lastRect = [(FlutterTextInputView*)_textInputPlugin.textInputView + caretRectForPosition:(FlutterTextPosition*)range.end]; + CGRect transformedLastRect = [(FlutterTextInputView*)_textInputPlugin.textInputView + localRectFromFrameworkTransform:lastRect]; + + activityViewController.popoverPresentationController.sourceView = engineViewController.view; + // In case of RTL Language, get the minimum x coordinate + activityViewController.popoverPresentationController.sourceRect = + CGRectMake(fmin(transformedFirstRect.origin.x, transformedLastRect.origin.x), + transformedFirstRect.origin.y, + abs(transformedLastRect.origin.x - transformedFirstRect.origin.x), + transformedFirstRect.size.height); + } + [engineViewController presentViewController:activityViewController animated:YES completion:nil]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm index 73cc460b351f3..79e8089c42278 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm @@ -161,6 +161,43 @@ - (void)testShareScreenInvoked { [self waitForExpectationsWithTimeout:1 handler:nil]; } +- (void)testShareScreenInvokedOnIPad { + FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease]; + [engine runWithEntrypoint:nil]; + std::unique_ptr> _weakFactory = + std::make_unique>(engine); + + XCTestExpectation* presentExpectation = + [self expectationWithDescription:@"Share view controller presented on iPad"]; + + FlutterViewController* engineViewController = + [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease]; + FlutterViewController* mockEngineViewController = OCMPartialMock(engineViewController); + OCMStub([mockEngineViewController + presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]] + animated:YES + completion:nil]); + + id mockTraitCollection = OCMClassMock([UITraitCollection class]); + OCMStub([mockTraitCollection userInterfaceIdiom]).andReturn(UIUserInterfaceIdiomPad); + + FlutterPlatformPlugin* plugin = + [[[FlutterPlatformPlugin alloc] initWithEngine:_weakFactory->GetWeakPtr()] autorelease]; + FlutterPlatformPlugin* mockPlugin = OCMPartialMock(plugin); + + FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:@"Share.invoke" + arguments:@"Test"]; + FlutterResult result = ^(id result) { + OCMVerify([mockEngineViewController + presentViewController:[OCMArg isKindOfClass:[UIActivityViewController class]] + animated:YES + completion:nil]); + [presentExpectation fulfill]; + }; + [mockPlugin handleMethodCall:methodCall result:result]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + - (void)testClipboardHasCorrectStrings { [UIPasteboard generalPasteboard].string = nil; FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h index 96eff563e0850..888fdaa898954 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h @@ -164,6 +164,10 @@ FLUTTER_DARWIN_EXPORT - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithOwner:(FlutterTextInputPlugin*)textInputPlugin NS_DESIGNATED_INITIALIZER; +// TODO(louisehsu): These are being exposed to support Share in FlutterPlatformPlugin +// Consider moving that feature into FlutterTextInputPlugin to avoid exposing extra methods +- (CGRect)localRectFromFrameworkTransform:(CGRect)incomingRect; +- (CGRect)caretRectForPosition:(UITextPosition*)position; @end @interface UIView (FindFirstResponder) From 51e50e886066a6709abfdfbc29bd41f6c723915b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=B4=B5=E9=94=8B?= Date: Fri, 1 Dec 2023 08:54:12 +0800 Subject: [PATCH 21/31] [CP] Fix not being able to hide iOS status bar via setEnabledSystemUIMode (#48403) Original PR: https://github.com/flutter/engine/pull/48271 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- .../framework/Source/FlutterPlatformPlugin.mm | 4 +- .../Source/FlutterPlatformPluginTest.mm | 89 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm index 586f1c36b79f4..8ad0e2351426d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm @@ -43,7 +43,7 @@ using namespace flutter; static void SetStatusBarHiddenForSharedApplication(BOOL hidden) { -#if APPLICATION_EXTENSION_API_ONLY +#if not APPLICATION_EXTENSION_API_ONLY [UIApplication sharedApplication].statusBarHidden = hidden; #else FML_LOG(WARNING) << "Application based status bar styling is not available in app extension."; @@ -51,7 +51,7 @@ static void SetStatusBarHiddenForSharedApplication(BOOL hidden) { } static void SetStatusBarStyleForSharedApplication(UIStatusBarStyle style) { -#if APPLICATION_EXTENSION_API_ONLY +#if not APPLICATION_EXTENSION_API_ONLY // Note: -[UIApplication setStatusBarStyle] is deprecated in iOS9 // in favor of delegating to the view controller. [[UIApplication sharedApplication] setStatusBarStyle:style]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm index 79e8089c42278..5b0ef4123f707 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm @@ -405,4 +405,93 @@ - (void)testViewControllerBasedStatusBarHiddenUpdate { [bundleMock stopMocking]; } +- (void)testStatusBarHiddenUpdate { + id bundleMock = OCMPartialMock([NSBundle mainBundle]); + OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]) + .andReturn(@NO); + id mockApplication = OCMClassMock([UIApplication class]); + OCMStub([mockApplication sharedApplication]).andReturn(mockApplication); + + // Enabling system UI overlays to update status bar. + FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease]; + [engine runWithEntrypoint:nil]; + FlutterViewController* flutterViewController = + [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease]; + std::unique_ptr> _weakFactory = + std::make_unique>(engine); + + // Update to hidden. + FlutterPlatformPlugin* plugin = [engine platformPlugin]; + + XCTestExpectation* enableSystemUIOverlaysCalled = + [self expectationWithDescription:@"setEnabledSystemUIOverlays"]; + FlutterResult resultSet = ^(id result) { + [enableSystemUIOverlaysCalled fulfill]; + }; + FlutterMethodCall* methodCallSet = + [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays" + arguments:@[ @"SystemUiOverlay.bottom" ]]; + [plugin handleMethodCall:methodCallSet result:resultSet]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +#if not APPLICATION_EXTENSION_API_ONLY + OCMVerify([mockApplication setStatusBarHidden:YES]); +#endif + + // Update to shown. + XCTestExpectation* enableSystemUIOverlaysCalled2 = + [self expectationWithDescription:@"setEnabledSystemUIOverlays"]; + FlutterResult resultSet2 = ^(id result) { + [enableSystemUIOverlaysCalled2 fulfill]; + }; + FlutterMethodCall* methodCallSet2 = + [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setEnabledSystemUIOverlays" + arguments:@[ @"SystemUiOverlay.top" ]]; + [plugin handleMethodCall:methodCallSet2 result:resultSet2]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +#if not APPLICATION_EXTENSION_API_ONLY + OCMVerify([mockApplication setStatusBarHidden:NO]); +#endif + + [flutterViewController deregisterNotifications]; + [mockApplication stopMocking]; + [bundleMock stopMocking]; +} + +- (void)testStatusBarStyle { + id bundleMock = OCMPartialMock([NSBundle mainBundle]); + OCMStub([bundleMock objectForInfoDictionaryKey:@"UIViewControllerBasedStatusBarAppearance"]) + .andReturn(@NO); + id mockApplication = OCMClassMock([UIApplication class]); + OCMStub([mockApplication sharedApplication]).andReturn(mockApplication); + + FlutterEngine* engine = [[[FlutterEngine alloc] initWithName:@"test" project:nil] autorelease]; + [engine runWithEntrypoint:nil]; + FlutterViewController* flutterViewController = + [[[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil] autorelease]; + std::unique_ptr> _weakFactory = + std::make_unique>(engine); + XCTAssertFalse(flutterViewController.prefersStatusBarHidden); + + FlutterPlatformPlugin* plugin = [engine platformPlugin]; + + XCTestExpectation* enableSystemUIModeCalled = + [self expectationWithDescription:@"setSystemUIOverlayStyle"]; + FlutterResult resultSet = ^(id result) { + [enableSystemUIModeCalled fulfill]; + }; + FlutterMethodCall* methodCallSet = + [FlutterMethodCall methodCallWithMethodName:@"SystemChrome.setSystemUIOverlayStyle" + arguments:@{@"statusBarBrightness" : @"Brightness.dark"}]; + [plugin handleMethodCall:methodCallSet result:resultSet]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + +#if not APPLICATION_EXTENSION_API_ONLY + OCMVerify([mockApplication setStatusBarStyle:UIStatusBarStyleLightContent]); +#endif + + [flutterViewController deregisterNotifications]; + [mockApplication stopMocking]; + [bundleMock stopMocking]; +} + @end From aea49428dc7dd1e3e189194ee7211a50c30c9af1 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Tue, 5 Dec 2023 09:04:49 -0800 Subject: [PATCH 22/31] [CP][Impeller] Skip mask blur with 0 sigma. (#48457) (#48473) <0 sigma render incorrectly with wide gamut, but these shouldn't produce shadows at all as far as I can tell. https://github.com/flutter/flutter/issues/138842 --- impeller/aiks/aiks_unittests.cc | 18 ++++++++++++++++++ impeller/aiks/canvas.cc | 6 ++++++ .../contents/solid_rrect_blur_contents.cc | 4 +++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 72679b05feb12..115f3c1950007 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -3627,5 +3627,23 @@ TEST_P(AiksTest, ClearColorOptimizationWhenSubpassIsBiggerThanParentPass) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) { + Canvas canvas; + + Paint paint = { + .color = Color::White(), + .mask_blur_descriptor = + Paint::MaskBlurDescriptor{ + .style = FilterContents::BlurStyle::kNormal, + .sigma = Sigma(0), + }, + }; + + canvas.DrawCircle({300, 300}, 200, paint); + canvas.DrawRect(Rect::MakeLTRB(100, 300, 500, 600), paint); + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index ae4c9d512037f..32a49871ac506 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -18,6 +18,7 @@ #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/contents/vertices_contents.h" #include "impeller/entity/geometry/geometry.h" +#include "impeller/geometry/constants.h" #include "impeller/geometry/path_builder.h" namespace impeller { @@ -205,6 +206,11 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, return false; } + if (std::fabs(new_paint.mask_blur_descriptor->sigma.sigma) <= + kEhCloseEnough) { + return true; + } + // For symmetrically mask blurred solid RRects, absorb the mask blur and use // a faster SDF approximation. diff --git a/impeller/entity/contents/solid_rrect_blur_contents.cc b/impeller/entity/contents/solid_rrect_blur_contents.cc index ffb190cf7a271..e0078f7093e43 100644 --- a/impeller/entity/contents/solid_rrect_blur_contents.cc +++ b/impeller/entity/contents/solid_rrect_blur_contents.cc @@ -8,6 +8,7 @@ #include "impeller/entity/contents/content_context.h" #include "impeller/entity/entity.h" #include "impeller/geometry/color.h" +#include "impeller/geometry/constants.h" #include "impeller/geometry/path.h" #include "impeller/geometry/path_builder.h" #include "impeller/renderer/render_pass.h" @@ -55,7 +56,8 @@ std::optional SolidRRectBlurContents::GetCoverage( bool SolidRRectBlurContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - if (!rect_.has_value()) { + // Early return if sigma is close to zero to avoid rendering NaNs. + if (!rect_.has_value() || std::fabs(sigma_.sigma) <= kEhCloseEnough) { return true; } From f0c8486b60cccfa77ae835defdd890c97897a46e Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Tue, 5 Dec 2023 09:26:55 -0800 Subject: [PATCH 23/31] [CP] Roll skia to 795ed944 (#48657) https://github.com/flutter/flutter/issues/139371 --- DEPS | 2 +- ci/licenses_golden/licenses_skia | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index fd040621e8212..027166cf4f83a 100644 --- a/DEPS +++ b/DEPS @@ -18,7 +18,7 @@ vars = { 'llvm_git': 'https://llvm.googlesource.com', # OCMock is for testing only so there is no google clone 'ocmock_git': 'https://github.com/erikdoe/ocmock.git', - 'skia_revision': '33502f9b0c7d845adceb4907d1c7dc1f22b3fd4c', + 'skia_revision': '795ed944ff5bde5916d193824589d3bacfa61a7d', # WARNING: DO NOT EDIT canvaskit_cipd_instance MANUALLY # See `lib/web_ui/README.md` for how to roll CanvasKit to a new version. diff --git a/ci/licenses_golden/licenses_skia b/ci/licenses_golden/licenses_skia index 64b87cc1a193f..720013e312849 100644 --- a/ci/licenses_golden/licenses_skia +++ b/ci/licenses_golden/licenses_skia @@ -1,4 +1,4 @@ -Signature: eca53560b3fc7923df8e91b89c6a742d +Signature: d1349790807333b45e728aa0781329ea ==================================================================================================== LIBRARY: etc1 From 54a7145303f0dd9d0f93424a2e124eb4abef5091 Mon Sep 17 00:00:00 2001 From: Casey Hillers Date: Tue, 5 Dec 2023 13:09:18 -0800 Subject: [PATCH 24/31] [flutter_releases] Flutter stable 3.16.3 Engine Cherrypicks (#48687) # Flutter stable 3.16.3 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@7beebdd41 --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index 027166cf4f83a..db781b6642ba9 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'a58c5ab91e954b12a56b51f7ddc55b257dfd0db4', + 'dart_revision': '7beebdd410282beccfd3a75ae13fd0d288b14a5e', # 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_dart b/ci/licenses_golden/licenses_dart index 23fb50ae1ec1b..c854fe3533549 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 080ba1d4add6ac56042fbf6155e49f1f +Signature: 89619e30d21a24727f88927a386e925b ==================================================================================================== LIBRARY: dart From bc2e856edb0fe0368ff1c6725a2d3174dabee7cd Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Wed, 13 Dec 2023 12:33:53 -0800 Subject: [PATCH 25/31] [CP] Fix _availability_version_check for iOS 11 and 12 (#48926) CP of https://github.com/flutter/engine/commit/5587d26aa2d4b2b239a5f2ce8f231c97ab1d36db into 3.16 for https://github.com/flutter/flutter/issues/138711. --- BUILD.gn | 1 + ci/licenses_golden/excluded_files | 1 + ci/licenses_golden/licenses_flutter | 4 + shell/platform/darwin/common/BUILD.gn | 19 +++ .../common/availability_version_check.cc | 159 +++++++++++++++++- .../common/availability_version_check.h | 18 ++ .../availability_version_check_unittests.cc | 35 ++++ shell/platform/darwin/ios/BUILD.gn | 1 + .../Source/availability_version_check_test.mm | 26 +++ testing/run_tests.py | 1 + 10 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 shell/platform/darwin/common/availability_version_check.h create mode 100644 shell/platform/darwin/common/availability_version_check_unittests.cc create mode 100644 shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm diff --git a/BUILD.gn b/BUILD.gn index 704c0f2c8628d..409c5f912a570 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -195,6 +195,7 @@ group("unittests") { if (is_mac) { public_deps += [ "//flutter/impeller/golden_tests:impeller_golden_tests", + "//flutter/shell/platform/darwin/common:availability_version_check_unittests", "//flutter/shell/platform/darwin/common:framework_common_unittests", "//flutter/third_party/spring_animation:spring_animation_unittests", ] diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index feed60b197fdf..412f6d957fbdb 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -280,6 +280,7 @@ ../../../flutter/shell/platform/common/text_input_model_unittests.cc ../../../flutter/shell/platform/common/text_range_unittests.cc ../../../flutter/shell/platform/darwin/Doxyfile +../../../flutter/shell/platform/darwin/common/availability_version_check_unittests.cc ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_codecs_unittest.mm ../../../flutter/shell/platform/darwin/common/framework/Source/flutter_standard_codec_unittest.mm ../../../flutter/shell/platform/darwin/macos/README.md diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index f31b0f04c8c8b..f5fa01c758d78 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -2597,6 +2597,7 @@ ORIGIN: ../../../flutter/shell/platform/common/text_input_model.cc + ../../../fl ORIGIN: ../../../flutter/shell/platform/common/text_input_model.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/common/text_range.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/common/availability_version_check.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/common/availability_version_check.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/common/buffer_conversions.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/common/buffer_conversions.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/common/command_line.h + ../../../flutter/LICENSE @@ -2731,6 +2732,7 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibilit ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection.mm + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection_test.mm + ../../../flutter/LICENSE @@ -5367,6 +5369,7 @@ FILE: ../../../flutter/shell/platform/common/text_input_model.cc FILE: ../../../flutter/shell/platform/common/text_input_model.h FILE: ../../../flutter/shell/platform/common/text_range.h FILE: ../../../flutter/shell/platform/darwin/common/availability_version_check.cc +FILE: ../../../flutter/shell/platform/darwin/common/availability_version_check.h FILE: ../../../flutter/shell/platform/darwin/common/buffer_conversions.h FILE: ../../../flutter/shell/platform/darwin/common/buffer_conversions.mm FILE: ../../../flutter/shell/platform/darwin/common/command_line.h @@ -5502,6 +5505,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_test.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/connection_collection_test.mm diff --git a/shell/platform/darwin/common/BUILD.gn b/shell/platform/darwin/common/BUILD.gn index 0d29be6c703eb..786deba37e03f 100644 --- a/shell/platform/darwin/common/BUILD.gn +++ b/shell/platform/darwin/common/BUILD.gn @@ -50,6 +50,25 @@ source_set("availability_version_check") { public_configs = [ "//flutter:config" ] } +test_fixtures("availability_version_check_fixtures") { + fixtures = [] +} + +executable("availability_version_check_unittests") { + testonly = true + + sources = [ "availability_version_check_unittests.cc" ] + + deps = [ + ":availability_version_check", + ":availability_version_check_fixtures", + "//flutter/fml", + "//flutter/testing", + ] + + public_configs = [ "//flutter:config" ] +} + # Shared framework headers end up in the same folder as platform-specific # framework headers when consumed by clients, so the include paths assume they # are next to each other. diff --git a/shell/platform/darwin/common/availability_version_check.cc b/shell/platform/darwin/common/availability_version_check.cc index 67514cbf5561f..1564bec4335f0 100644 --- a/shell/platform/darwin/common/availability_version_check.cc +++ b/shell/platform/darwin/common/availability_version_check.cc @@ -2,20 +2,141 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "flutter/shell/platform/darwin/common/availability_version_check.h" + +#include +#include +#include + +#include #include #include -#include +#include "flutter/fml/build_config.h" +#include "flutter/fml/file.h" #include "flutter/fml/logging.h" +#include "flutter/fml/mapping.h" +#include "flutter/fml/platform/darwin/cf_utils.h" + +// The implementation of _availability_version_check defined in this file is +// based on the code in the clang-rt library at: +// +// https://github.com/llvm/llvm-project/blob/e315bf25a843582de39257e1345408a10dc08224/compiler-rt/lib/builtins/os_version_check.c +// +// Flutter provides its own implementation due to an issue introduced in recent +// versions of Clang following Clang 18 in which the clang-rt library declares +// weak linkage against the _availability_version_check symbol. This declaration +// causes apps to be rejected from the App Store. When Flutter statically links +// the implementation below, the weak linkage is satisfied at Engine build time, +// the symbol is no longer exposed from the Engine dylib, and apps will then +// not be rejected from the App Store. +// +// The implementation of _availability_version_check can delegate to the +// dynamically looked-up symbol on recent iOS versions, but the lookup will fail +// on iOS 11 and 12. When the lookup fails, the current OS version must be +// retrieved from a plist file at a well-known path. The logic for this below is +// copied from the clang-rt implementation and adapted for the Engine. -// See context in https://github.com/flutter/flutter/issues/132130 and +// See more context in https://github.com/flutter/flutter/issues/132130 and // https://github.com/flutter/engine/pull/44711. // TODO(zanderso): Remove this after Clang 18 rolls into Xcode. -// https://github.com/flutter/flutter/issues/133203 +// https://github.com/flutter/flutter/issues/133203. + +#define CF_PROPERTY_LIST_IMMUTABLE 0 + +namespace flutter { + +// This function parses the platform's version information out of a plist file +// at a well-known path. It parses the plist file using CoreFoundation functions +// to match the implementation in the clang-rt library. +std::optional ProductVersionFromSystemVersionPList() { + std::string plist_path = "/System/Library/CoreServices/SystemVersion.plist"; +#if FML_OS_IOS_SIMULATOR + char* plist_path_prefix = getenv("IPHONE_SIMULATOR_ROOT"); + if (!plist_path_prefix) { + FML_DLOG(ERROR) << "Failed to getenv IPHONE_SIMULATOR_ROOT"; + return std::nullopt; + } + plist_path = std::string(plist_path_prefix) + plist_path; +#endif // FML_OS_IOS_SIMULATOR + + auto plist_mapping = fml::FileMapping::CreateReadOnly(plist_path); + + // Get the file buffer into CF's format. We pass in a null allocator here * + // because we free PListBuf ourselves + auto file_contents = fml::CFRef(CFDataCreateWithBytesNoCopy( + nullptr, plist_mapping->GetMapping(), + static_cast(plist_mapping->GetSize()), kCFAllocatorNull)); + if (!file_contents) { + FML_DLOG(ERROR) << "Failed to CFDataCreateWithBytesNoCopyFunc"; + return std::nullopt; + } + + auto plist = fml::CFRef( + reinterpret_cast(CFPropertyListCreateWithData( + nullptr, file_contents, CF_PROPERTY_LIST_IMMUTABLE, nullptr, + nullptr))); + if (!plist) { + FML_DLOG(ERROR) << "Failed to CFPropertyListCreateWithDataFunc or " + "CFPropertyListCreateFromXMLDataFunc"; + return std::nullopt; + } + + auto product_version = + fml::CFRef(CFStringCreateWithCStringNoCopy( + nullptr, "ProductVersion", kCFStringEncodingASCII, kCFAllocatorNull)); + if (!product_version) { + FML_DLOG(ERROR) << "Failed to CFStringCreateWithCStringNoCopyFunc"; + return std::nullopt; + } + CFTypeRef opaque_value = CFDictionaryGetValue(plist, product_version); + if (!opaque_value || CFGetTypeID(opaque_value) != CFStringGetTypeID()) { + FML_DLOG(ERROR) << "Failed to CFDictionaryGetValueFunc"; + return std::nullopt; + } + + char version_str[32]; + if (!CFStringGetCString(reinterpret_cast(opaque_value), + version_str, sizeof(version_str), + kCFStringEncodingUTF8)) { + FML_DLOG(ERROR) << "Failed to CFStringGetCStringFunc"; + return std::nullopt; + } + + int32_t major = 0; + int32_t minor = 0; + int32_t subminor = 0; + int matches = sscanf(version_str, "%d.%d.%d", &major, &minor, &subminor); + // A major version number is sufficient. The minor and subminor numbers might + // not be present. + if (matches < 1) { + FML_DLOG(ERROR) << "Failed to match product version string: " + << version_str; + return std::nullopt; + } + + return ProductVersion{major, minor, subminor}; +} + +bool IsEncodedVersionLessThanOrSame(uint32_t encoded_lhs, ProductVersion rhs) { + // Parse the values out of encoded_lhs, then compare against rhs. + const int32_t major = (encoded_lhs >> 16) & 0xffff; + const int32_t minor = (encoded_lhs >> 8) & 0xff; + const int32_t subminor = encoded_lhs & 0xff; + auto lhs = ProductVersion{major, minor, subminor}; + + return lhs <= rhs; +} + +} // namespace flutter namespace { +// The host's OS version when the dynamic lookup of _availability_version_check +// has failed. +static flutter::ProductVersion g_version; + typedef uint32_t dyld_platform_t; typedef struct { @@ -36,13 +157,41 @@ void InitializeAvailabilityCheck(void* unused) { } AvailabilityVersionCheck = reinterpret_cast( dlsym(RTLD_DEFAULT, "_availability_version_check")); - FML_CHECK(AvailabilityVersionCheck); + if (AvailabilityVersionCheck) { + return; + } + + // If _availability_version_check can't be dynamically loaded, then version + // information must be parsed out of a system plist file. + auto product_version = flutter::ProductVersionFromSystemVersionPList(); + if (product_version.has_value()) { + g_version = product_version.value(); + } else { + // If reading version info out of the system plist file fails, then + // fall back to the minimum version that Flutter supports. +#if FML_OS_IOS || FML_OS_IOS_SIMULATOR + g_version = std::make_tuple(11, 0, 0); +#elif FML_OS_MACOSX + g_version = std::make_tuple(10, 14, 0); +#endif // FML_OS_MACOSX + } } extern "C" bool _availability_version_check(uint32_t count, dyld_build_version_t versions[]) { dispatch_once_f(&DispatchOnceCounter, NULL, InitializeAvailabilityCheck); - return AvailabilityVersionCheck(count, versions); + if (AvailabilityVersionCheck) { + return AvailabilityVersionCheck(count, versions); + } + + if (count == 0) { + return true; + } + + // This function is called in only one place in the clang-rt implementation + // where there is only one element in the array. + return flutter::IsEncodedVersionLessThanOrSame(versions[0].version, + g_version); } } // namespace diff --git a/shell/platform/darwin/common/availability_version_check.h b/shell/platform/darwin/common/availability_version_check.h new file mode 100644 index 0000000000000..8724a72d1990a --- /dev/null +++ b/shell/platform/darwin/common/availability_version_check.h @@ -0,0 +1,18 @@ +// Copyright 2013 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. + +#include +#include +#include + +namespace flutter { + +using ProductVersion = + std::tuple; + +std::optional ProductVersionFromSystemVersionPList(); + +bool IsEncodedVersionLessThanOrSame(uint32_t encoded_lhs, ProductVersion rhs); + +} // namespace flutter diff --git a/shell/platform/darwin/common/availability_version_check_unittests.cc b/shell/platform/darwin/common/availability_version_check_unittests.cc new file mode 100644 index 0000000000000..7753d1cfa522d --- /dev/null +++ b/shell/platform/darwin/common/availability_version_check_unittests.cc @@ -0,0 +1,35 @@ +// Copyright 2013 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. + +#include + +#include "flutter/shell/platform/darwin/common/availability_version_check.h" + +#include "gtest/gtest.h" + +TEST(AvailabilityVersionCheck, CanDecodeSystemPlist) { + auto maybe_product_version = flutter::ProductVersionFromSystemVersionPList(); + ASSERT_TRUE(maybe_product_version.has_value()); + if (maybe_product_version.has_value()) { + auto product_version = maybe_product_version.value(); + ASSERT_GT(product_version, std::make_tuple(0, 0, 0)); + } +} + +static inline uint32_t ConstructVersion(uint32_t major, + uint32_t minor, + uint32_t subminor) { + return ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff); +} + +TEST(AvailabilityVersionCheck, CanParseAndCompareVersions) { + auto rhs_version = std::make_tuple(17, 2, 0); + uint32_t encoded_lower_version = ConstructVersion(12, 3, 7); + ASSERT_TRUE(flutter::IsEncodedVersionLessThanOrSame(encoded_lower_version, + rhs_version)); + + uint32_t encoded_higher_version = ConstructVersion(42, 0, 1); + ASSERT_FALSE(flutter::IsEncodedVersionLessThanOrSame(encoded_higher_version, + rhs_version)); +} diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index b8bd60198ae0a..5a65050fe0e11 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -314,6 +314,7 @@ shared_library("ios_test_flutter") { "framework/Source/FlutterViewControllerTest.mm", "framework/Source/SemanticsObjectTest.mm", "framework/Source/UIViewController_FlutterScreenAndSceneIfLoadedTest.mm", + "framework/Source/availability_version_check_test.mm", "framework/Source/connection_collection_test.mm", ] deps = [ diff --git a/shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm b/shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm new file mode 100644 index 0000000000000..c843893c216e8 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/availability_version_check_test.mm @@ -0,0 +1,26 @@ +// Copyright 2013 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 + +#import +#import + +#import "flutter/shell/platform/darwin/common/availability_version_check.h" + +@interface AvailabilityVersionCheckTest : XCTestCase +@end + +@implementation AvailabilityVersionCheckTest + +- (void)testSimple { + auto maybe_product_version = flutter::ProductVersionFromSystemVersionPList(); + XCTAssertTrue(maybe_product_version.has_value()); + if (maybe_product_version.has_value()) { + auto product_version = maybe_product_version.value(); + XCTAssertTrue(product_version > std::make_tuple(0, 0, 0)); + } +} + +@end diff --git a/testing/run_tests.py b/testing/run_tests.py index 9a0e24f4f1022..64a17f4efdc09 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -434,6 +434,7 @@ def make_test(name, flags=None, extra_env=None): unittests += [ # The accessibility library only supports Mac and Windows. make_test('accessibility_unittests'), + make_test('availability_version_check_unittests'), make_test('framework_common_unittests'), make_test('spring_animation_unittests'), ] From 5a8e5c55ddaf59132b4c7427ccdd2c61f233bdf2 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Mon, 18 Dec 2023 15:56:31 -0800 Subject: [PATCH 26/31] [CP] [Impeller] Turn off Aiks bounds tracking for filtered SaveLayers. (#49198) Cherry-pick for https://github.com/flutter/engine/pull/49076. For issue: https://github.com/flutter/flutter/issues/139294 --- impeller/aiks/canvas.cc | 8 ++++++++ impeller/aiks/canvas_unittests.cc | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 32a49871ac506..4c4a0ab3f263c 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -540,6 +540,14 @@ void Canvas::SaveLayer(const Paint& paint, const std::shared_ptr& backdrop_filter) { Save(true, paint.blend_mode, backdrop_filter); + // The DisplayList bounds/rtree doesn't account for filters applied to parent + // layers, and so sub-DisplayLists are getting culled as if no filters are + // applied. + // See also: https://github.com/flutter/flutter/issues/139294 + if (paint.image_filter) { + xformation_stack_.back().cull_rect = std::nullopt; + } + auto& new_layer_pass = GetCurrentPass(); new_layer_pass.SetBoundsLimit(bounds); diff --git a/impeller/aiks/canvas_unittests.cc b/impeller/aiks/canvas_unittests.cc index ed83f0500a254..728316cb3c61d 100644 --- a/impeller/aiks/canvas_unittests.cc +++ b/impeller/aiks/canvas_unittests.cc @@ -4,6 +4,7 @@ #include "flutter/testing/testing.h" #include "impeller/aiks/canvas.h" +#include "impeller/aiks/image_filter.h" #include "impeller/geometry/path_builder.h" // TODO(zanderso): https://github.com/flutter/flutter/issues/127701 @@ -336,6 +337,23 @@ TEST(AiksCanvasTest, PathClipDiffAgainstFullyCoveredCullRect) { ASSERT_EQ(canvas.GetCurrentLocalCullingBounds().value(), result_cull); } +TEST(AiksCanvasTest, DisableLocalBoundsRectForFilteredSaveLayers) { + Rect initial_cull = Rect::MakeXYWH(0, 0, 10, 10); + + Canvas canvas(initial_cull); + ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value()); + + canvas.Save(); + canvas.SaveLayer( + Paint{.image_filter = ImageFilter::MakeBlur( + Sigma(10), Sigma(10), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kDecal)}); + ASSERT_FALSE(canvas.GetCurrentLocalCullingBounds().has_value()); + + canvas.Restore(); + ASSERT_TRUE(canvas.GetCurrentLocalCullingBounds().has_value()); +} + } // namespace testing } // namespace impeller From 61b336001c273178633ba9c22f5dd6f90aeb1dba Mon Sep 17 00:00:00 2001 From: Zachary Anderson Date: Mon, 18 Dec 2023 23:58:18 +0000 Subject: [PATCH 27/31] [CP] Fix for AnimatedOpacity affects blended color overlay render (#49190) This PR cherry-picks the following two commits: https://github.com/flutter/engine/commit/2dbc5d2c576ae3e80b23c28e3f4989e79821b41d https://github.com/flutter/engine/commit/0b0fab8215362f50a034d108ad11fbb8e93c3fce to address https://github.com/flutter/flutter/issues/139571 --- impeller/aiks/aiks_unittests.cc | 31 +++++++++++++++++---- impeller/aiks/paint_pass_delegate.cc | 1 - impeller/entity/contents/clip_contents.cc | 4 +-- impeller/entity/contents/clip_contents.h | 4 +-- impeller/entity/contents/contents.cc | 3 +- impeller/entity/contents/contents.h | 2 +- impeller/entity/entity.cc | 4 +++ impeller/entity/entity_pass.cc | 34 ++++++++++++++--------- impeller/entity/entity_pass.h | 8 +++++- impeller/entity/entity_unittests.cc | 14 ++++++++++ 10 files changed, 78 insertions(+), 27 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 115f3c1950007..42b9fd6ab0122 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -2416,19 +2416,18 @@ TEST_P(AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters) { Picture picture = canvas.EndRecordingAsPicture(); std::optional actual_color; + bool found_subpass = false; picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool { if (auto subpass = std::get_if>(&element)) { actual_color = subpass->get()->GetClearColor(); + found_subpass = true; } // Fail if the first element isn't a subpass. return true; }); - ASSERT_TRUE(actual_color.has_value()); - if (!actual_color) { - return; - } - ASSERT_EQ(actual_color.value(), Color::BlackTransparent()); + EXPECT_TRUE(found_subpass); + EXPECT_FALSE(actual_color.has_value()); } TEST_P(AiksTest, CollapsedDrawPaintInSubpass) { @@ -3645,5 +3644,27 @@ TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, SubpassWithClearColorOptimization) { + Canvas canvas; + + // Use a non-srcOver blend mode to ensure that we don't detect this as an + // opacity peephole optimization. + canvas.SaveLayer( + {.color = Color::Blue().WithAlpha(0.5), .blend_mode = BlendMode::kSource}, + Rect::MakeLTRB(0, 0, 200, 200)); + canvas.DrawPaint( + {.color = Color::BlackTransparent(), .blend_mode = BlendMode::kSource}); + canvas.Restore(); + + canvas.SaveLayer( + {.color = Color::Blue(), .blend_mode = BlendMode::kDestinationOver}); + canvas.Restore(); + + // This playground should appear blank on CI since we are only drawing + // transparent black. If the clear color optimization is broken, the texture + // will be filled with NaNs and may produce a magenta texture on macOS or iOS. + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/aiks/paint_pass_delegate.cc b/impeller/aiks/paint_pass_delegate.cc index f9a081a0b55cf..604e4dc92831c 100644 --- a/impeller/aiks/paint_pass_delegate.cc +++ b/impeller/aiks/paint_pass_delegate.cc @@ -10,7 +10,6 @@ #include "impeller/entity/contents/texture_contents.h" #include "impeller/entity/entity_pass.h" #include "impeller/geometry/color.h" -#include "impeller/geometry/path_builder.h" namespace impeller { diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index 21c2eb1aa2469..77bbccc82f0c7 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -66,7 +66,7 @@ Contents::StencilCoverage ClipContents::GetStencilCoverage( bool ClipContents::ShouldRender( const Entity& entity, - const std::optional& stencil_coverage) const { + const std::optional stencil_coverage) const { return true; } @@ -163,7 +163,7 @@ Contents::StencilCoverage ClipRestoreContents::GetStencilCoverage( bool ClipRestoreContents::ShouldRender( const Entity& entity, - const std::optional& stencil_coverage) const { + const std::optional stencil_coverage) const { return true; } diff --git a/impeller/entity/contents/clip_contents.h b/impeller/entity/contents/clip_contents.h index 3b0faac98bc60..bc7b89ac055a5 100644 --- a/impeller/entity/contents/clip_contents.h +++ b/impeller/entity/contents/clip_contents.h @@ -35,7 +35,7 @@ class ClipContents final : public Contents { // |Contents| bool ShouldRender(const Entity& entity, - const std::optional& stencil_coverage) const override; + const std::optional stencil_coverage) const override; // |Contents| bool Render(const ContentContext& renderer, @@ -76,7 +76,7 @@ class ClipRestoreContents final : public Contents { // |Contents| bool ShouldRender(const Entity& entity, - const std::optional& stencil_coverage) const override; + const std::optional stencil_coverage) const override; // |Contents| bool Render(const ContentContext& renderer, diff --git a/impeller/entity/contents/contents.cc b/impeller/entity/contents/contents.cc index a181e22302b21..4671d23b4c0d5 100644 --- a/impeller/entity/contents/contents.cc +++ b/impeller/entity/contents/contents.cc @@ -133,11 +133,10 @@ bool Contents::ApplyColorFilter( } bool Contents::ShouldRender(const Entity& entity, - const std::optional& stencil_coverage) const { + const std::optional stencil_coverage) const { if (!stencil_coverage.has_value()) { return false; } - auto coverage = GetCoverage(entity); if (!coverage.has_value()) { return false; diff --git a/impeller/entity/contents/contents.h b/impeller/entity/contents/contents.h index b9dec5db2d12e..11b5ad00570de 100644 --- a/impeller/entity/contents/contents.h +++ b/impeller/entity/contents/contents.h @@ -113,7 +113,7 @@ class Contents { const std::string& label = "Snapshot") const; virtual bool ShouldRender(const Entity& entity, - const std::optional& stencil_coverage) const; + const std::optional stencil_coverage) const; //---------------------------------------------------------------------------- /// @brief Return the color source's intrinsic size, if available. diff --git a/impeller/entity/entity.cc b/impeller/entity/entity.cc index b7ebc2af966c9..ae18016932911 100644 --- a/impeller/entity/entity.cc +++ b/impeller/entity/entity.cc @@ -71,7 +71,11 @@ Contents::StencilCoverage Entity::GetStencilCoverage( } bool Entity::ShouldRender(const std::optional& stencil_coverage) const { +#ifdef IMPELLER_CONTENT_CULLING return contents_->ShouldRender(*this, stencil_coverage); +#else + return true; +#endif // IMPELLER_CONTENT_CULLING } void Entity::SetContents(std::shared_ptr contents) { diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 64580febfcf24..495856a338bb5 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -368,7 +368,7 @@ bool EntityPass::Render(ContentContext& renderer, if (!supports_onscreen_backdrop_reads && reads_from_onscreen_backdrop) { auto offscreen_target = CreateRenderTarget( renderer, root_render_target.GetRenderTargetSize(), true, - GetClearColor(render_target.GetRenderTargetSize())); + GetClearColorOrDefault(render_target.GetRenderTargetSize())); if (!OnRender(renderer, // renderer capture, // capture @@ -475,7 +475,8 @@ bool EntityPass::Render(ContentContext& renderer, } // Set up the clear color of the root pass. - color0.clear_color = GetClearColor(render_target.GetRenderTargetSize()); + color0.clear_color = + GetClearColorOrDefault(render_target.GetRenderTargetSize()); root_render_target.SetColorAttachment(color0, 0); EntityPassTarget pass_target( @@ -628,10 +629,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement( } auto subpass_target = CreateRenderTarget( - renderer, // renderer - subpass_size, // size - subpass->GetTotalPassReads(renderer) > 0, // readable - subpass->GetClearColor(subpass_size)); // clear_color + renderer, // renderer + subpass_size, // size + subpass->GetTotalPassReads(renderer) > 0, // readable + subpass->GetClearColorOrDefault(subpass_size)); // clear_color if (!subpass_target.IsValid()) { VALIDATION_LOG << "Subpass render target is invalid."; @@ -722,8 +723,7 @@ bool EntityPass::OnRender( } auto clear_color_size = pass_target.GetRenderTarget().GetRenderTargetSize(); - if (!collapsed_parent_pass && - !GetClearColor(clear_color_size).IsTransparent()) { + if (!collapsed_parent_pass && GetClearColor(clear_color_size).has_value()) { // Force the pass context to create at least one new pass if the clear color // is present. pass_context.GetRenderPass(pass_depth); @@ -1140,21 +1140,29 @@ void EntityPass::SetBlendMode(BlendMode blend_mode) { flood_clip_ = Entity::IsBlendModeDestructive(blend_mode); } -Color EntityPass::GetClearColor(ISize target_size) const { - Color result = Color::BlackTransparent(); +Color EntityPass::GetClearColorOrDefault(ISize size) const { + return GetClearColor(size).value_or(Color::BlackTransparent()); +} + +std::optional EntityPass::GetClearColor(ISize target_size) const { if (backdrop_filter_proc_) { - return result; + return std::nullopt; } + std::optional result = std::nullopt; for (const Element& element : elements_) { auto [entity_color, blend_mode] = ElementAsBackgroundColor(element, target_size); if (!entity_color.has_value()) { break; } - result = result.Blend(entity_color.value(), blend_mode); + result = result.value_or(Color::BlackTransparent()) + .Blend(entity_color.value(), blend_mode); } - return result.Premultiply(); + if (result.has_value()) { + return result->Premultiply(); + } + return result; } void EntityPass::SetBackdropFilter(BackdropFilterProc proc) { diff --git a/impeller/entity/entity_pass.h b/impeller/entity/entity_pass.h index d09649abfd9d0..c03a837047eeb 100644 --- a/impeller/entity/entity_pass.h +++ b/impeller/entity/entity_pass.h @@ -135,7 +135,13 @@ class EntityPass { void SetBlendMode(BlendMode blend_mode); - Color GetClearColor(ISize size = ISize::Infinite()) const; + /// @brief Return the premultiplied clear color of the pass entities, if any. + std::optional GetClearColor(ISize size = ISize::Infinite()) const; + + /// @brief Return the premultiplied clear color of the pass entities. + /// + /// If the entity pass has no clear color, this will return transparent black. + Color GetClearColorOrDefault(ISize size = ISize::Infinite()) const; void SetBackdropFilter(BackdropFilterProc proc); diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index ca094aa0fe54f..2b28fa3ede2e7 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -1607,6 +1607,20 @@ TEST_P(EntityTest, SolidFillShouldRenderIsCorrect) { } } +TEST_P(EntityTest, DoesNotCullEntitiesByDefault) { + auto fill = std::make_shared(); + fill->SetColor(Color::CornflowerBlue()); + fill->SetGeometry( + Geometry::MakeRect(Rect::MakeLTRB(-1000, -1000, -900, -900))); + + Entity entity; + entity.SetContents(fill); + + // Even though the entity is offscreen, this should still render because we do + // not compute the coverage intersection by default. + EXPECT_TRUE(entity.ShouldRender(Rect::MakeLTRB(0, 0, 100, 100))); +} + TEST_P(EntityTest, ClipContentsShouldRenderIsCorrect) { // For clip ops, `ShouldRender` should always return true. From 3f3e560236539b7e2702f5ac790b2a4691b32d49 Mon Sep 17 00:00:00 2001 From: Xilai Zhang Date: Tue, 19 Dec 2023 12:48:00 -0800 Subject: [PATCH 28/31] =?UTF-8?q?[cherrypick-stable]Skip=20unexpected=20ev?= =?UTF-8?q?ents=20in=20MultiPlatformViewBackgroundForegroundScenar?= =?UTF-8?q?=E2=80=A6=20(#49247)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …io (#48456) Fixes https://github.com/flutter/flutter/issues/138193. Was first attempted to fix in https://github.com/flutter/engine/pull/48096, but that was not reliable since it's all asynchronous. ------------------------------------------- cherry pick to fix mac unopt failures on stable branch: https://flutter-dashboard.appspot.com/#/build?repo=engine&branch=flutter-3.16-candidate.0 --- testing/scenario_app/lib/src/platform_view.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testing/scenario_app/lib/src/platform_view.dart b/testing/scenario_app/lib/src/platform_view.dart index 7c15465dc9ea8..92679d2a94ae1 100644 --- a/testing/scenario_app/lib/src/platform_view.dart +++ b/testing/scenario_app/lib/src/platform_view.dart @@ -510,6 +510,13 @@ class MultiPlatformViewBackgroundForegroundScenario extends Scenario PlatformMessageResponseCallback? callback, ) { final String message = utf8.decode(data!.buffer.asUint8List()); + + // The expected first event should be 'AppLifecycleState.resumed', but + // occasionally it will receive 'AppLifecycleState.inactive' first. Skip + // any messages until 'AppLifecycleState.resumed' is received. + if (_lastLifecycleState.isEmpty && message != 'AppLifecycleState.resumed') { + return; + } if (_lastLifecycleState == 'AppLifecycleState.inactive' && message == 'AppLifecycleState.resumed') { _nextFrame = _secondFrame; From 4a585b79294e830fa89c24924d58a27cc8fbf406 Mon Sep 17 00:00:00 2001 From: Kevin Chisholm Date: Thu, 11 Jan 2024 10:53:08 -0600 Subject: [PATCH 29/31] [flutter_releases] Flutter stable 3.16.7 Engine Cherrypicks (#49717) # Flutter stable 3.16.7 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@af448832b --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index db781b6642ba9..84101652cd198 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': '7beebdd410282beccfd3a75ae13fd0d288b14a5e', + 'dart_revision': 'af448832b51ebc29d128fb14b4ebbfb77679ad0c', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py From 6e2ea58a5ccbefcfadc2d4b7b8045fc6c20ab812 Mon Sep 17 00:00:00 2001 From: Xilai Zhang Date: Tue, 16 Jan 2024 13:10:05 -0800 Subject: [PATCH 30/31] [flutter_releases] Flutter stable 3.16.8 Engine Cherrypicks (#49795) # Flutter stable 3.16.8 Engine ## Scheduled Cherrypicks - Roll dart revision: dart-lang/sdk@bc253dce3 --- DEPS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS index 84101652cd198..ac5a55bdb9553 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'af448832b51ebc29d128fb14b4ebbfb77679ad0c', + 'dart_revision': 'bc253dce31f81f4f4204e80b9038b77cbb8547df', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py From f40e976bedff57e69e1b3d89a7c2a3c617a03dad Mon Sep 17 00:00:00 2001 From: godofredoc Date: Wed, 24 Jan 2024 18:55:33 -0800 Subject: [PATCH 31/31] Roll 3b128c545 dart sdk. (#50024) Rolls dart sdk to: 3b128c5454834a1aaef37d9bb12595e7c217ab61 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- DEPS | 2 +- ci/licenses_golden/licenses_dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DEPS b/DEPS index ac5a55bdb9553..0386902e6ee43 100644 --- a/DEPS +++ b/DEPS @@ -57,7 +57,7 @@ vars = { # Dart is: https://github.com/dart-lang/sdk/blob/main/DEPS # You can use //tools/dart/create_updated_flutter_deps.py to produce # updated revision list of existing dependencies. - 'dart_revision': 'bc253dce31f81f4f4204e80b9038b77cbb8547df', + 'dart_revision': '3b128c5454834a1aaef37d9bb12595e7c217ab61', # 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_dart b/ci/licenses_golden/licenses_dart index c854fe3533549..60ffd6d8ca5fb 100644 --- a/ci/licenses_golden/licenses_dart +++ b/ci/licenses_golden/licenses_dart @@ -1,4 +1,4 @@ -Signature: 89619e30d21a24727f88927a386e925b +Signature: ca990fb99a9b23dd546b46d46ece34dd ==================================================================================================== LIBRARY: dart