Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit eab9b7f

Browse files
authored
Call Dart_NotifyLowMemory more on iOS (#19289)
1 parent 0dc86cd commit eab9b7f

File tree

7 files changed

+137
-4
lines changed

7 files changed

+137
-4
lines changed

ci/licenses_golden/licenses_flutter

+1
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbac
898898
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm
899899
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h
900900
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
901+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm
901902
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm
902903
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h
903904
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterHeadlessDartRunner.mm

shell/platform/darwin/ios/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ source_set("ios_test_flutter_mrc") {
167167
"-mios-simulator-version-min=$ios_testing_deployment_target",
168168
]
169169
sources = [
170+
"framework/Source/FlutterEnginePlatformViewTest.mm",
170171
"framework/Source/accessibility_bridge_test.mm",
171172
]
172173
deps = [

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

+18-4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ - (instancetype)initWithName:(NSString*)labelPrefix
117117
name:UIApplicationDidReceiveMemoryWarningNotification
118118
object:nil];
119119

120+
[center addObserver:self
121+
selector:@selector(applicationDidEnterBackground:)
122+
name:UIApplicationDidEnterBackgroundNotification
123+
object:nil];
124+
120125
[center addObserver:self
121126
selector:@selector(applicationBecameActive:)
122127
name:UIApplicationDidBecomeActiveNotification
@@ -232,6 +237,7 @@ - (void)setViewController:(FlutterViewController*)viewController {
232237
}];
233238
} else {
234239
self.flutterViewControllerWillDeallocObserver = nil;
240+
[self notifyLowMemory];
235241
}
236242
}
237243

@@ -558,6 +564,13 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
558564
return [self runWithEntrypoint:entrypoint libraryURI:nil];
559565
}
560566

567+
- (void)notifyLowMemory {
568+
if (_shell) {
569+
_shell->NotifyLowMemoryWarning();
570+
}
571+
[_systemChannel sendMessage:@{@"type" : @"memoryPressure"}];
572+
}
573+
561574
#pragma mark - Text input delegate
562575

563576
- (void)updateEditingClient:(int)client withState:(NSDictionary*)state {
@@ -748,11 +761,12 @@ - (void)applicationWillResignActive:(NSNotification*)notification {
748761
[self setIsGpuDisabled:YES];
749762
}
750763

764+
- (void)applicationDidEnterBackground:(NSNotification*)notification {
765+
[self notifyLowMemory];
766+
}
767+
751768
- (void)onMemoryWarning:(NSNotification*)notification {
752-
if (_shell) {
753-
_shell->NotifyLowMemoryWarning();
754-
}
755-
[_systemChannel sendMessage:@{@"type" : @"memoryPressure"}];
769+
[self notifyLowMemory];
756770
}
757771

758772
- (void)setIsGpuDisabled:(BOOL)value {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#define FML_USED_ON_EMBEDDER
6+
7+
#import <OCMock/OCMock.h>
8+
#import <XCTest/XCTest.h>
9+
10+
#import "flutter/fml/message_loop.h"
11+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
12+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
13+
#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
14+
15+
FLUTTER_ASSERT_NOT_ARC
16+
17+
namespace flutter {
18+
namespace {
19+
20+
class MockDelegate : public PlatformView::Delegate {
21+
void OnPlatformViewCreated(std::unique_ptr<Surface> surface) override {}
22+
void OnPlatformViewDestroyed() override {}
23+
void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override {}
24+
void OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) override {}
25+
void OnPlatformViewDispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) override {}
26+
void OnPlatformViewDispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet) override {
27+
}
28+
void OnPlatformViewDispatchSemanticsAction(int32_t id,
29+
SemanticsAction action,
30+
std::vector<uint8_t> args) override {}
31+
void OnPlatformViewSetSemanticsEnabled(bool enabled) override {}
32+
void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override {}
33+
void OnPlatformViewRegisterTexture(std::shared_ptr<Texture> texture) override {}
34+
void OnPlatformViewUnregisterTexture(int64_t texture_id) override {}
35+
void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override {}
36+
37+
std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
38+
const std::vector<std::string>& supported_locale_data) override {
39+
std::unique_ptr<std::vector<std::string>> out = std::make_unique<std::vector<std::string>>();
40+
return out;
41+
}
42+
};
43+
44+
} // namespace
45+
} // namespace flutter
46+
47+
@interface FlutterEnginePlatformViewTest : XCTestCase
48+
@end
49+
50+
@implementation FlutterEnginePlatformViewTest
51+
52+
- (void)setUp {
53+
fml::MessageLoop::EnsureInitializedForCurrentThread();
54+
}
55+
56+
- (void)tearDown {
57+
}
58+
59+
- (void)testCallsNotifyLowMemory {
60+
flutter::MockDelegate mock_delegate;
61+
auto thread_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
62+
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
63+
/*platform=*/thread_task_runner,
64+
/*raster=*/thread_task_runner,
65+
/*ui=*/thread_task_runner,
66+
/*io=*/thread_task_runner);
67+
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
68+
/*delegate=*/mock_delegate,
69+
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
70+
/*task_runners=*/runners);
71+
72+
id project = OCMClassMock([FlutterDartProject class]);
73+
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"tester" project:project];
74+
XCTAssertNotNil(engine);
75+
id mockEngine = OCMPartialMock(engine);
76+
OCMStub([mockEngine notifyLowMemory]);
77+
OCMStub([mockEngine iosPlatformView]).andReturn(platform_view.get());
78+
79+
[engine setViewController:nil];
80+
OCMVerify([mockEngine notifyLowMemory]);
81+
OCMReject([mockEngine notifyLowMemory]);
82+
83+
[[NSNotificationCenter defaultCenter]
84+
postNotificationName:UIApplicationDidReceiveMemoryWarningNotification
85+
object:nil];
86+
OCMVerify([mockEngine notifyLowMemory]);
87+
OCMReject([mockEngine notifyLowMemory]);
88+
89+
[[NSNotificationCenter defaultCenter]
90+
postNotificationName:UIApplicationDidEnterBackgroundNotification
91+
object:nil];
92+
93+
OCMVerify([mockEngine notifyLowMemory]);
94+
}
95+
96+
@end

shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;
4646
- (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;
4747
- (void)attachView;
48+
- (void)notifyLowMemory;
49+
- (flutter::PlatformViewIOS*)iosPlatformView;
4850

4951
@end
5052

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

+1
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,7 @@ - (void)viewDidDisappear:(BOOL)animated {
557557
[self surfaceUpdated:NO];
558558
[[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
559559
[self flushOngoingTouches];
560+
[_engine.get() notifyLowMemory];
560561
}
561562

562563
[super viewDidDisappear:animated];

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

+18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ @interface FlutterEngine ()
1616
- (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI;
1717
@end
1818

19+
@interface FlutterEngine (TestLowMemory)
20+
- (void)notifyLowMemory;
21+
@end
22+
1923
extern NSNotificationName const FlutterViewControllerWillDealloc;
2024

2125
/// A simple mock class for FlutterEngine.
@@ -529,4 +533,18 @@ - (void)testHideOverlay {
529533
XCTAssertTrue(realVC.prefersHomeIndicatorAutoHidden, @"");
530534
}
531535

536+
- (void)testNotifyLowMemory {
537+
id engine = OCMClassMock([FlutterEngine class]);
538+
FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine
539+
nibName:nil
540+
bundle:nil];
541+
OCMStub([engine viewController]).andReturn(viewController);
542+
id viewControllerMock = OCMPartialMock(viewController);
543+
OCMStub([viewControllerMock surfaceUpdated:NO]);
544+
545+
[viewController beginAppearanceTransition:NO animated:NO];
546+
[viewController endAppearanceTransition];
547+
OCMVerify([engine notifyLowMemory]);
548+
}
549+
532550
@end

0 commit comments

Comments
 (0)