5 #define FML_USED_ON_EMBEDDER 7 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" 11 #include "flutter/fml/message_loop.h" 12 #include "flutter/fml/platform/darwin/platform_version.h" 13 #include "flutter/fml/trace_event.h" 14 #include "flutter/runtime/ptrace_check.h" 15 #include "flutter/shell/common/engine.h" 16 #include "flutter/shell/common/platform_view.h" 17 #include "flutter/shell/common/shell.h" 18 #include "flutter/shell/common/switches.h" 19 #include "flutter/shell/common/thread_host.h" 20 #include "flutter/shell/common/variable_refresh_rate_display.h" 21 #import "flutter/shell/platform/darwin/common/command_line.h" 22 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h" 23 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h" 24 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterIndirectScribbleDelegate.h" 25 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h" 26 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h" 27 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" 28 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerDelegate.h" 29 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h" 30 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" 31 #import "flutter/shell/platform/darwin/ios/framework/Source/connection_collection.h" 32 #import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" 33 #import "flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h" 34 #import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" 35 #import "flutter/shell/platform/darwin/ios/platform_view_ios.h" 36 #import "flutter/shell/platform/darwin/ios/rendering_api_selection.h" 37 #include "flutter/shell/profiling/sampling_profiler.h" 48 [[NSThread currentThread] setThreadPriority:0];
52 [[NSThread currentThread] setThreadPriority:0.5];
57 [[NSThread currentThread] setThreadPriority:1.0];
60 pthread_t thread = pthread_self();
61 if (!pthread_getschedparam(thread, &policy, ¶m)) {
62 param.sched_priority = 50;
63 pthread_setschedparam(thread, policy, ¶m);
70 #pragma mark - Public exported constants 75 #pragma mark - Internal constants 87 FlutterUndoManagerDelegate,
88 FlutterTextInputDelegate,
89 FlutterBinaryMessenger>
92 @property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
93 @property(nonatomic, readonly) NSMutableDictionary<NSString*, FlutterEngineRegistrar*>* registrars;
95 @property(nonatomic, readwrite, copy) NSString*
isolateId;
96 @property(nonatomic, copy) NSString* initialRoute;
97 @property(nonatomic, retain) id<NSObject> flutterViewControllerWillDeallocObserver;
140 - (instancetype)init {
144 - (instancetype)initWithName:(NSString*)labelPrefix {
148 - (instancetype)initWithName:(NSString*)labelPrefix project:(
FlutterDartProject*)project {
152 - (instancetype)initWithName:(NSString*)labelPrefix
154 allowHeadlessExecution:(
BOOL)allowHeadlessExecution {
161 - (instancetype)initWithName:(NSString*)labelPrefix
163 allowHeadlessExecution:(
BOOL)allowHeadlessExecution
164 restorationEnabled:(
BOOL)restorationEnabled {
166 NSAssert(
self,
@"Super init cannot be nil");
167 NSAssert(labelPrefix,
@"labelPrefix is required");
173 _weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterEngine>>(
self);
175 if (project == nil) {
178 _dartProject.reset([project retain]);
183 @"Cannot create a FlutterEngine instance in debug mode without Flutter tooling or " 184 @"Xcode.\n\nTo launch in debug mode in iOS 14+, run flutter run from Flutter tools, run " 185 @"from an IDE with a Flutter IDE plugin or run the iOS project from Xcode.\nAlternatively " 186 @"profile and release mode apps can be launched from the home screen.");
191 _pluginPublications = [[NSMutableDictionary alloc] init];
192 _registrars = [[NSMutableDictionary alloc] init];
193 [
self recreatePlatformViewController];
198 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
199 [center addObserver:self
200 selector:@selector(onMemoryWarning:)
201 name:UIApplicationDidReceiveMemoryWarningNotification
204 [center addObserver:self
205 selector:@selector(applicationWillEnterForeground:)
206 name:UIApplicationWillEnterForegroundNotification
209 [center addObserver:self
210 selector:@selector(applicationDidEnterBackground:)
211 name:UIApplicationDidEnterBackgroundNotification
214 [center addObserver:self
215 selector:@selector(onLocaleUpdated:)
216 name:NSCurrentLocaleDidChangeNotification
222 - (void)recreatePlatformViewController {
234 [_pluginPublications enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL* stop) {
235 if ([object respondsToSelector:@selector(detachFromEngineForRegistrar:)]) {
236 NSObject<FlutterPluginRegistrar>* registrar = self.registrars[key];
237 [object detachFromEngineForRegistrar:registrar];
241 [[NSNotificationCenter defaultCenter] postNotificationName:kFlutterEngineWillDealloc
251 enumerateKeysAndObjectsUsingBlock:^(id key, FlutterEngineRegistrar* registrar, BOOL* stop) {
252 registrar.flutterEngine = nil;
255 [_labelPrefix release];
256 [_initialRoute release];
257 [_pluginPublications release];
258 [_registrars release];
260 [_binaryMessenger release];
261 [_isolateId release];
263 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
264 if (_flutterViewControllerWillDeallocObserver) {
265 [center removeObserver:_flutterViewControllerWillDeallocObserver];
266 [_flutterViewControllerWillDeallocObserver release];
268 [center removeObserver:self];
283 if (!
self.platformView) {
286 self.platformView->SetViewportMetrics(std::move(viewportMetrics));
289 - (void)dispatchPointerDataPacket:(std::unique_ptr<flutter::PointerDataPacket>)packet {
290 if (!
self.platformView) {
293 self.platformView->DispatchPointerDataPacket(std::move(packet));
298 return _shell->GetPlatformView();
308 return _shell->GetTaskRunners().GetPlatformTaskRunner();
313 return _shell->GetTaskRunners().GetRasterTaskRunner();
319 if (@available(iOS 13.4, *)) {
323 if (!
self.platformView) {
331 switch (
event.type) {
343 key_data.
logical =
event.logical;
346 auto packet = std::make_unique<flutter::KeyDataPacket>(key_data,
character);
347 NSData*
message = [NSData dataWithBytes:packet->data().data() length:packet->data().size()];
349 auto response = ^(NSData* reply) {
354 if (reply.length == 1 && *reinterpret_cast<const uint8_t*>(reply.bytes) == 1) {
360 [
self sendOnChannel:kFlutterKeyDataChannel message:message binaryReply:response];
363 - (void)ensureSemanticsEnabled {
364 self.iosPlatformView->SetSemanticsEnabled(
true);
372 [
self maybeSetupPlatformViewChannels];
378 self.flutterViewControllerWillDeallocObserver =
379 [[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
380 object:viewController
381 queue:[NSOperationQueue mainQueue]
382 usingBlock:^(NSNotification* note) {
383 [blockSelf notifyViewControllerDeallocated];
386 self.flutterViewControllerWillDeallocObserver = nil;
387 [
self notifyLowMemory];
392 self.iosPlatformView->attachView();
393 [_textInputPlugin.get() setupIndirectScribbleInteraction:self.viewController];
396 - (void)setFlutterViewControllerWillDeallocObserver:(id<NSObject>)observer {
397 if (observer != _flutterViewControllerWillDeallocObserver) {
398 if (_flutterViewControllerWillDeallocObserver) {
399 [[NSNotificationCenter defaultCenter]
400 removeObserver:_flutterViewControllerWillDeallocObserver];
401 [_flutterViewControllerWillDeallocObserver release];
403 _flutterViewControllerWillDeallocObserver = [observer retain];
407 - (void)notifyViewControllerDeallocated {
419 [_textInputPlugin.get() resetViewResponder];
423 - (void)destroyContext {
424 [
self resetChannels];
425 self.isolateId = nil;
442 - (std::shared_ptr<flutter::FlutterPlatformViewsController>&)platformViewsController {
485 - (NSURL*)observatoryUrl {
486 return [_publisher.get() url];
489 - (void)resetChannels {
503 - (void)startProfiler {
506 _profiler = std::make_shared<flutter::SamplingProfiler>(
515 - (void)setupChannels {
519 [_binaryMessenger setMessageHandlerOnChannel:@"flutter/isolate"
520 binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
522 weakSelf.get().isolateId =
528 initWithName:
@"flutter/localization" 529 binaryMessenger:
self.binaryMessenger
533 initWithName:
@"flutter/navigation" 534 binaryMessenger:
self.binaryMessenger
537 if ([_initialRoute
length] > 0) {
539 [_navigationChannel invokeMethod:@"setInitialRoute" arguments:_initialRoute];
540 [_initialRoute release];
545 initWithName:
@"flutter/restoration" 546 binaryMessenger:
self.binaryMessenger
550 initWithName:
@"flutter/platform" 551 binaryMessenger:
self.binaryMessenger
555 initWithName:
@"flutter/platform_views" 556 binaryMessenger:
self.binaryMessenger
560 initWithName:
@"flutter/textinput" 561 binaryMessenger:
self.binaryMessenger
565 initWithName:
@"flutter/undomanager" 566 binaryMessenger:
self.binaryMessenger
570 initWithName:
@"flutter/lifecycle" 571 binaryMessenger:
self.binaryMessenger
575 initWithName:
@"flutter/system" 576 binaryMessenger:
self.binaryMessenger
580 initWithName:
@"flutter/settings" 581 binaryMessenger:
self.binaryMessenger
585 initWithName:
@"flutter/keyevent" 586 binaryMessenger:
self.binaryMessenger
605 - (void)maybeSetupPlatformViewChannels {
606 if (
_shell &&
self.shell.IsSetup()) {
608 [_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
613 [_platformViewsChannel.get()
614 setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
616 weakSelf.get().platformViewsController->OnMethodCall(call, result);
621 [_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
626 [_undoManagerChannel.get()
627 setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
634 base64Encode:(bool)base64Encode {
635 return self.shell.Screenshot(
type, base64Encode);
638 - (void)launchEngine:(NSString*)entrypoint
639 libraryURI:(NSString*)libraryOrNil
640 entrypointArgs:(NSArray<NSString*>*)entrypointArgs {
642 self.shell.RunEngine([_dartProject.get() runConfigurationForEntrypoint:entrypoint
643 libraryOrNil:libraryOrNil
644 entrypointArgs:entrypointArgs]);
647 - (void)setupShell:(std::unique_ptr<flutter::Shell>)shell
648 withObservatoryPublication:(
BOOL)doesObservatoryPublication {
649 _shell = std::move(shell);
650 [
self setupChannels];
651 [
self onLocaleUpdated:nil];
652 [
self initializeDisplays];
654 initWithEnableObservatoryPublication:doesObservatoryPublication]);
655 [
self maybeSetupPlatformViewChannels];
660 + (
BOOL)isProfilerEnabled {
661 bool profilerEnabled =
false;
662 #if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG) || \ 663 (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE) 664 profilerEnabled =
true;
666 return profilerEnabled;
669 + (NSString*)generateThreadLabel:(NSString*)labelPrefix {
670 static size_t s_shellCount = 0;
671 return [NSString stringWithFormat:@"%@.%zu", labelPrefix, ++s_shellCount];
679 uint32_t threadHostType = flutter::ThreadHost::Type::UI | flutter::ThreadHost::Type::RASTER |
680 flutter::ThreadHost::Type::IO;
683 threadHostType = threadHostType | flutter::ThreadHost::Type::Profiler;
691 flutter::ThreadHost::Type::UI, threadLabel.UTF8String),
696 flutter::ThreadHost::Type::RASTER, threadLabel.UTF8String),
701 flutter::ThreadHost::Type::IO, threadLabel.UTF8String),
707 static void SetEntryPoint(
flutter::Settings* settings, NSString* entrypoint, NSString* libraryURI) {
709 FML_DCHECK(entrypoint) <<
"Must specify entrypoint if specifying library";
712 }
else if (entrypoint) {
721 - (
BOOL)createShell:(NSString*)entrypoint
722 libraryURI:(NSString*)libraryURI
723 initialRoute:(NSString*)initialRoute {
725 FML_LOG(WARNING) <<
"This FlutterEngine was already invoked.";
729 self.initialRoute = initialRoute;
731 auto settings = [_dartProject.get() settings];
732 if (initialRoute != nil) {
733 self.initialRoute = initialRoute;
734 }
else if (settings.
route.empty() ==
false) {
735 self.initialRoute = [NSString stringWithCString:settings.route.c_str()
736 encoding:NSUTF8StringEncoding];
741 auto platformData = [_dartProject.get() defaultPlatformData];
743 SetEntryPoint(&settings, entrypoint, libraryURI);
745 NSString* threadLabel = [
FlutterEngine generateThreadLabel:_labelPrefix];
746 _threadHost = std::make_shared<flutter::ThreadHost>();
753 [
self recreatePlatformViewController];
754 return std::make_unique<flutter::PlatformViewIOS>(
755 shell,
self->_renderingApi,
self->_platformViewsController, shell.GetTaskRunners());
759 [](
flutter::Shell& shell) {
return std::make_unique<flutter::Rasterizer>(shell); };
763 _threadHost->raster_thread->GetTaskRunner(),
764 _threadHost->ui_thread->GetTaskRunner(),
765 _threadHost->io_thread->GetTaskRunner()
769 [UIApplication sharedApplication].applicationState == UIApplicationStateBackground;
772 std::move(platformData),
773 std::move(task_runners),
775 on_create_platform_view,
776 on_create_rasterizer,
779 if (shell ==
nullptr) {
780 FML_LOG(ERROR) <<
"Could not start a shell FlutterEngine with entrypoint: " 781 << entrypoint.UTF8String;
783 [
self setupShell:std::move(shell)
784 withObservatoryPublication:settings.enable_observatory_publication];
786 [
self startProfiler];
793 - (void)initializeDisplays {
794 auto vsync_waiter = std::shared_ptr<flutter::VsyncWaiter>(
_shell->GetVsyncWaiter().lock());
796 std::vector<std::unique_ptr<flutter::Display>> displays;
797 displays.push_back(std::make_unique<flutter::VariableRefreshRateDisplay>(vsync_waiter_ios));
807 - (
BOOL)runWithEntrypoint:(NSString*)entrypoint libraryURI:(NSString*)libraryURI {
813 - (
BOOL)runWithEntrypoint:(NSString*)entrypoint {
817 - (
BOOL)runWithEntrypoint:(NSString*)entrypoint initialRoute:(NSString*)initialRoute {
821 - (
BOOL)runWithEntrypoint:(NSString*)entrypoint
822 libraryURI:(NSString*)libraryURI
823 initialRoute:(NSString*)initialRoute {
830 - (
BOOL)runWithEntrypoint:(NSString*)entrypoint
831 libraryURI:(NSString*)libraryURI
832 initialRoute:(NSString*)initialRoute
833 entrypointArgs:(NSArray<NSString*>*)entrypointArgs {
834 if ([
self createShell:entrypoint libraryURI:libraryURI initialRoute:initialRoute]) {
835 [
self launchEngine:entrypoint libraryURI:libraryURI entrypointArgs:entrypointArgs];
841 - (void)notifyLowMemory {
843 _shell->NotifyLowMemoryWarning();
845 [_systemChannel sendMessage:@{@"type" : @"memoryPressure"}];
848 #pragma mark - Text input delegate 851 updateEditingClient:(int)client
852 withState:(NSDictionary*)
state {
853 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingState"
854 arguments:@[ @(client), state ]];
858 updateEditingClient:(int)client
859 withState:(NSDictionary*)
state 860 withTag:(NSString*)tag {
861 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingStateWithTag"
862 arguments:@[ @(client), @{tag : state} ]];
866 updateEditingClient:(int)client
867 withDelta:(NSDictionary*)delta {
868 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateEditingStateWithDeltas"
869 arguments:@[ @(client), delta ]];
873 updateFloatingCursor:(FlutterFloatingCursorDragState)
state 874 withClient:(
int)client
875 withPosition:(NSDictionary*)position {
876 NSString* stateString;
878 case FlutterFloatingCursorDragStateStart:
879 stateString =
@"FloatingCursorDragState.start";
881 case FlutterFloatingCursorDragStateUpdate:
882 stateString =
@"FloatingCursorDragState.update";
884 case FlutterFloatingCursorDragStateEnd:
885 stateString =
@"FloatingCursorDragState.end";
888 [_textInputChannel.get() invokeMethod:@"TextInputClient.updateFloatingCursor"
889 arguments:@[ @(client), stateString, position ]];
893 performAction:(FlutterTextInputAction)
action 894 withClient:(
int)client {
895 NSString* actionString;
897 case FlutterTextInputActionUnspecified:
902 actionString =
@"TextInputAction.unspecified";
904 case FlutterTextInputActionDone:
905 actionString =
@"TextInputAction.done";
907 case FlutterTextInputActionGo:
908 actionString =
@"TextInputAction.go";
910 case FlutterTextInputActionSend:
911 actionString =
@"TextInputAction.send";
913 case FlutterTextInputActionSearch:
914 actionString =
@"TextInputAction.search";
916 case FlutterTextInputActionNext:
917 actionString =
@"TextInputAction.next";
919 case FlutterTextInputActionContinue:
920 actionString =
@"TextInputAction.continue";
922 case FlutterTextInputActionJoin:
923 actionString =
@"TextInputAction.join";
925 case FlutterTextInputActionRoute:
926 actionString =
@"TextInputAction.route";
928 case FlutterTextInputActionEmergencyCall:
929 actionString =
@"TextInputAction.emergencyCall";
931 case FlutterTextInputActionNewline:
932 actionString =
@"TextInputAction.newline";
935 [_textInputChannel.get() invokeMethod:@"TextInputClient.performAction"
936 arguments:@[ @(client), actionString ]];
940 showAutocorrectionPromptRectForStart:(NSUInteger)start
942 withClient:(int)client {
943 [_textInputChannel.get() invokeMethod:@"TextInputClient.showAutocorrectionPromptRect"
944 arguments:@[ @(client), @(start), @(end) ]];
947 #pragma mark - FlutterViewEngineDelegate 950 [_textInputChannel.get() invokeMethod:@"TextInputClient.showToolbar" arguments:@[ @(client) ]];
954 focusElement:(UIScribbleElementIdentifier)elementIdentifier
955 atPoint:(CGPoint)referencePoint
957 [_textInputChannel.get()
958 invokeMethod:@"TextInputClient.focusElement"
959 arguments:@[ elementIdentifier, @(referencePoint.x), @(referencePoint.y) ]
964 requestElementsInRect:(CGRect)rect
966 [_textInputChannel.get()
967 invokeMethod:@"TextInputClient.requestElementsInRect"
968 arguments:@[ @(rect.origin.x), @(rect.origin.y), @(rect.size.width), @(rect.size.height) ]
973 [_textInputChannel.get() invokeMethod:@"TextInputClient.scribbleInteractionBegan" arguments:nil];
977 [_textInputChannel.get() invokeMethod:@"TextInputClient.scribbleInteractionFinished"
982 insertTextPlaceholderWithSize:(CGSize)
size 983 withClient:(
int)client {
984 [_textInputChannel.get() invokeMethod:@"TextInputClient.insertTextPlaceholder"
985 arguments:@[ @(client), @(size.width), @(size.height) ]];
989 removeTextPlaceholder:(int)client {
990 [_textInputChannel.get() invokeMethod:@"TextInputClient.removeTextPlaceholder"
991 arguments:@[ @(client) ]];
1014 dispatch_async(dispatch_get_main_queue(), ^(
void) {
1015 long platform_view_id =
self.platformViewsController->FindFirstResponderPlatformViewId();
1016 if (platform_view_id == -1) {
1020 [_platformViewsChannel.get() invokeMethod:@"viewFocused" arguments:@(platform_view_id)];
1024 #pragma mark - Undo Manager Delegate 1027 handleUndoWithDirection:(FlutterUndoRedoDirection)direction {
1028 NSString*
action = (direction == FlutterUndoRedoDirectionUndo) ?
@"undo" :
@"redo";
1029 [_undoManagerChannel.get() invokeMethod:@"UndoManagerClient.handleUndo" arguments:@[ action ]];
1032 #pragma mark - Screenshot Delegate 1035 asBase64Encoded:(
BOOL)base64Encode {
1037 return _shell->Screenshot(
type, base64Encode);
1040 - (void)flutterViewAccessibilityDidCall {
1046 - (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
1055 [_binaryMessenger release];
1059 #pragma mark - FlutterBinaryMessenger 1061 - (void)sendOnChannel:(NSString*)channel
message:(NSData*)
message {
1062 [
self sendOnChannel:channel message:message binaryReply:nil];
1065 - (void)sendOnChannel:(NSString*)channel
1068 NSParameterAssert(channel);
1070 @"Sending a message before the FlutterEngine has been run.");
1073 : fml::MakeRefCounted<flutter::PlatformMessageResponseDarwin>(
1077 _shell->GetTaskRunners().GetPlatformTaskRunner());
1078 std::unique_ptr<flutter::PlatformMessage> platformMessage =
1079 (
message == nil) ? std::make_unique<flutter::PlatformMessage>(channel.UTF8String, response)
1080 : std::make_unique<flutter::PlatformMessage>(
1083 _shell->GetPlatformView()->DispatchPlatformMessage(std::move(platformMessage));
1088 - (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue {
1093 binaryMessageHandler:
1095 return [
self setMessageHandlerOnChannel:channel binaryMessageHandler:handler taskQueue:nil];
1099 setMessageHandlerOnChannel:(NSString*)channel
1101 taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue {
1102 NSParameterAssert(channel);
1104 self.iosPlatformView->GetPlatformMessageHandlerIos()->SetMessageHandler(channel.UTF8String,
1105 handler, taskQueue);
1106 return _connections->AquireConnection(channel.UTF8String);
1108 NSAssert(!handler,
@"Setting a message handler before the FlutterEngine has been run.");
1116 std::string channel =
_connections->CleanupConnection(connection);
1117 if (!channel.empty()) {
1118 self.iosPlatformView->GetPlatformMessageHandlerIos()->SetMessageHandler(channel.c_str(), nil,
1124 #pragma mark - FlutterTextureRegistry 1126 - (int64_t)registerTexture:(NSObject<FlutterTexture>*)
texture {
1128 self.iosPlatformView->RegisterExternalTexture(textureId,
texture);
1132 - (void)unregisterTexture:(int64_t)textureId {
1133 _shell->GetPlatformView()->UnregisterTexture(textureId);
1136 - (void)textureFrameAvailable:(int64_t)textureId {
1137 _shell->GetPlatformView()->MarkTextureFrameAvailable(textureId);
1140 - (NSString*)lookupKeyForAsset:(NSString*)asset {
1144 - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
1148 - (id<FlutterPluginRegistry>)pluginRegistry {
1152 #pragma mark - FlutterPluginRegistry 1154 - (NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey {
1155 NSAssert(
self.pluginPublications[pluginKey] == nil,
@"Duplicate plugin key: %@", pluginKey);
1156 self.pluginPublications[pluginKey] = [NSNull null];
1158 flutterEngine:self];
1159 self.registrars[pluginKey] =
result;
1160 return [result autorelease];
1163 - (
BOOL)hasPlugin:(NSString*)pluginKey {
1164 return _pluginPublications[pluginKey] != nil;
1167 - (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
1168 return _pluginPublications[pluginKey];
1171 #pragma mark - Notifications 1173 - (void)applicationWillEnterForeground:(NSNotification*)notification {
1174 [
self setIsGpuDisabled:NO];
1177 - (void)applicationDidEnterBackground:(NSNotification*)notification {
1178 [
self setIsGpuDisabled:YES];
1179 [
self notifyLowMemory];
1182 - (void)onMemoryWarning:(NSNotification*)notification {
1183 [
self notifyLowMemory];
1191 _isGpuDisabled =
value;
1194 #pragma mark - Locale updates 1196 - (void)onLocaleUpdated:(NSNotification*)notification {
1198 NSMutableArray<NSString*>* localeData = [[[NSMutableArray alloc] init] autorelease];
1199 NSArray<NSString*>* preferredLocales = [NSLocale preferredLanguages];
1200 for (NSString* localeID in preferredLocales) {
1201 NSLocale* locale = [[[NSLocale alloc] initWithLocaleIdentifier:localeID] autorelease];
1202 NSString* languageCode = [locale objectForKey:NSLocaleLanguageCode];
1203 NSString* countryCode = [locale objectForKey:NSLocaleCountryCode];
1204 NSString* scriptCode = [locale objectForKey:NSLocaleScriptCode];
1205 NSString* variantCode = [locale objectForKey:NSLocaleVariantCode];
1206 if (!languageCode) {
1209 [localeData addObject:languageCode];
1210 [localeData addObject:(countryCode ? countryCode : @"")];
1211 [localeData addObject:(scriptCode ? scriptCode : @"")];
1212 [localeData addObject:(variantCode ? variantCode : @"")];
1214 if (localeData.count == 0) {
1217 [
self.localizationChannel invokeMethod:@"setLocale" arguments:localeData];
1220 - (void)waitForFirstFrame:(NSTimeInterval)timeout
1222 dispatch_queue_t
queue = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0);
1223 dispatch_async(queue, ^{
1227 dispatch_async(dispatch_get_main_queue(), ^{
1233 - (
FlutterEngine*)spawnWithEntrypoint:( NSString*)entrypoint
1234 libraryURI:( NSString*)libraryURI
1235 initialRoute:( NSString*)initialRoute
1236 entrypointArgs:( NSArray<NSString*>*)entrypointArgs {
1237 NSAssert(
_shell,
@"Spawning from an engine without a shell (possibly not run).");
1239 project:_dartProject.get()
1240 allowHeadlessExecution:_allowHeadlessExecution];
1242 [_dartProject.get() runConfigurationForEntrypoint:entrypoint
1243 libraryOrNil:libraryURI
1244 entrypointArgs:entrypointArgs];
1251 std::shared_ptr<flutter::IOSContext> context = ios_platform_view->
GetIosContext();
1258 [result recreatePlatformViewController];
1259 return std::make_unique<flutter::PlatformViewIOS>(
1260 shell, context, result->_platformViewsController, shell.GetTaskRunners());
1264 [](
flutter::Shell& shell) {
return std::make_unique<flutter::Rasterizer>(shell); };
1266 std::string cppInitialRoute;
1268 cppInitialRoute = [initialRoute UTF8String];
1271 std::unique_ptr<flutter::Shell> shell =
_shell->Spawn(
1272 std::move(configuration), cppInitialRoute, on_create_platform_view, on_create_rasterizer);
1277 result->_isGpuDisabled = _isGpuDisabled;
1278 [result setupShell:std::move(shell) withObservatoryPublication:NO];
1279 return [result autorelease];
1289 NSString* _pluginKey;
1292 - (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(
FlutterEngine*)flutterEngine {
1293 self = [
super init];
1294 NSAssert(
self,
@"Super init cannot be nil");
1295 _pluginKey = [pluginKey copy];
1301 [_pluginKey release];
1305 - (NSObject<FlutterBinaryMessenger>*)messenger {
1309 - (NSObject<FlutterTextureRegistry>*)textures {
1313 - (void)publish:(NSObject*)
value {
1317 - (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
1319 [channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
1320 [delegate handleMethodCall:call result:result];
1324 - (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate {
1325 id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
1326 if ([appDelegate conformsToProtocol:
@protocol(FlutterAppLifeCycleProvider)]) {
1327 id<FlutterAppLifeCycleProvider> lifeCycleProvider =
1328 (id<FlutterAppLifeCycleProvider>)appDelegate;
1329 [lifeCycleProvider addApplicationLifeCycleDelegate:delegate];
1333 - (NSString*)lookupKeyForAsset:(NSString*)asset {
1334 return [_flutterEngine lookupKeyForAsset:asset];
1337 - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
1338 return [_flutterEngine lookupKeyForAsset:asset fromPackage:package];
1341 - (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
1342 withId:(NSString*)factoryId {
1343 [
self registerViewFactory:factory
1345 gestureRecognizersBlockingPolicy:FlutterPlatformViewGestureRecognizersBlockingPolicyEager];
1348 - (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
1349 withId:(NSString*)factoryId
1350 gestureRecognizersBlockingPolicy:
1352 [_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId,
1353 gestureRecognizersBlockingPolicy);
BOOL forceSoftwareRendering
fml::scoped_nsobject< FlutterTextInputPlugin > _textInputPlugin
std::string advisory_script_entrypoint
BOOL _allowHeadlessExecution
Maintains a current integer assigned to a name (connections).
void handleMethodCall:result:(FlutterMethodCall *call, [result] FlutterResult result)
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
id< FlutterIndirectScribbleDelegate > indirectScribbleDelegate
std::unique_ptr< fml::WeakPtrFactory< FlutterEngine > > _weakFactory
std::shared_ptr< flutter::SamplingProfiler > _profiler
NSObject< FlutterBinaryMessenger > * binaryMessenger
#define FML_DCHECK(condition)
FlutterViewController * viewController
std::optional< ThreadConfig > io_config
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterBinaryReply)(NSData *_Nullable reply)
std::string advisory_script_uri
static void SetCurrentThreadName(const ThreadConfig &config)
fml::scoped_nsobject< FlutterMethodChannel > _undoManagerChannel
The ThreadConfig is the thread info include thread name, thread priority.
std::unique_ptr< flutter::Shell > _shell
fml::scoped_nsobject< FlutterBasicMessageChannel > _keyEventChannel
std::unique_ptr< flutter::ConnectionCollection > _connections
fml::scoped_nsobject< FlutterPlatformPlugin > _platformPlugin
NSString *const kFlutterEngineWillDealloc
FlutterTextInputPlugin * textInputPlugin
enum flutter::testing::@1969::KeyboardChange::Type type
void reset(NST object=nil)
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static void EnsureInitializedForCurrentThread()
fml::scoped_nsobject< FlutterRestorationPlugin > _restorationPlugin
#define FML_LOG(severity)
fml::scoped_nsobject< FlutterMethodChannel > _platformViewsChannel
fml::scoped_nsobject< FlutterUndoManagerPlugin > _undoManagerPlugin
std::optional< ThreadConfig > raster_config
fml::scoped_nsobject< FlutterObservatoryPublisher > _publisher
fml::scoped_nsobject< FlutterMethodChannel > _localizationChannel
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
void setupIndirectScribbleInteraction:(id< FlutterViewResponder > viewResponder)
void(^ FlutterBinaryMessageHandler)(NSData *_Nullable message, FlutterBinaryReply reply)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data observatory The hostname IP address on which the Dart Observatory should be served If not defaults to or::depending on whether ipv6 is specified disable Disable the Dart Observatory The observatory is never available in release mode Bind to the IPv6 localhost address for the Dart Observatory Ignored if observatory host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent Remove all existing persistent cache This is mainly for debugging purposes such as reproducing the shader compilation jank use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static std::string MakeThreadName(Type type, const std::string &prefix)
Use the prefix and thread type to generator a thread name.
instancetype sharedInstance()
fml::Thread::ThreadConfig ThreadConfig
std::shared_ptr< flutter::FlutterPlatformViewsController > _platformViewsController
Indicates that GPU operations should be permitted.
A POD type used to return the screenshot data along with the size of the frame.
fml::MallocMapping CopyNSDataToMapping(NSData *data)
ScreenshotType
The type of the screenshot to obtain of the previously rendered layer tree.
static constexpr int kNumProfilerSamplesPerSec
Specifies all the configuration required by the runtime library to launch the root isolate...
instancetype initWithName:project:allowHeadlessExecution:restorationEnabled:(NSString *labelPrefix, [project] nullable FlutterDartProject *project, [allowHeadlessExecution] BOOL allowHeadlessExecution, [restorationEnabled] BOOL NS_DESIGNATED_INITIALIZER)
BOOL runWithEntrypoint:libraryURI:initialRoute:(nullable NSString *entrypoint, [libraryURI] nullable NSString *libraryURI, [initialRoute] nullable NSString *initialRoute)
Suitable for threads which generate data for the display.
NSString *const kFlutterKeyDataChannel
The collection of all the threads used by the engine.
NSString *const FlutterDefaultDartEntrypoint
BOOL runWithEntrypoint:libraryURI:initialRoute:entrypointArgs:(nullable NSString *entrypoint, [libraryURI] nullable NSString *libraryURI, [initialRoute] nullable NSString *initialRoute, [entrypointArgs] nullable NSArray< NSString * > *entrypointArgs)
void(^ FlutterResult)(id _Nullable result)
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, TaskRunners task_runners, Settings settings, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer, bool is_gpu_disabled=false)
Creates a shell instance using the provided settings. The callbacks to create the various shell subco...
NSString * lookupKeyForAsset:fromPackage:(NSString *asset, [fromPackage] NSString *package)
fml::scoped_nsobject< FlutterMethodChannel > _platformChannel
void ensureSemanticsEnabled()
bool EnableTracingIfNecessary(const Settings &vm_settings)
Enables tracing in the process so that JIT mode VMs may be launched. Explicitly enabling tracing is n...
NSString * lookupKeyForAsset:(NSString *asset)
IOSRenderingAPI GetRenderingAPIForProcess(bool force_software)
instancetype initWithName:project:allowHeadlessExecution:(NSString *labelPrefix, [project] nullable FlutterDartProject *project, [allowHeadlessExecution] BOOL allowHeadlessExecution)
FlutterPlatformViewGestureRecognizersBlockingPolicy
UITextSmartQuotesType smartQuotesType API_AVAILABLE(ios(11.0))
fml::WeakPtr< FlutterViewController > _viewController
NSString *const FlutterDefaultInitialRoute
static constexpr TimeDelta FromMilliseconds(int64_t millis)
void sendMessage:(id _Nullable message)
fml::scoped_nsobject< FlutterMethodChannel > _textInputChannel
Suitable for thread which raster data.
static Connection MakeErrorConnection(int errCode)
void(* FlutterKeyEventCallback)(bool, void *)
Suitable for threads that shouldn't disrupt high priority work.
std::shared_ptr< flutter::ProfilerMetricsIOS > _profiler_metrics
FlutterBasicMessageChannel * lifecycleChannel
int64_t FlutterBinaryMessengerConnection
fml::scoped_nsobject< FlutterBasicMessageChannel > _lifecycleChannel
std::shared_ptr< flutter::ThreadHost > _threadHost
fml::scoped_nsobject< FlutterMethodChannel > _restorationChannel
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
flutter::IOSRenderingAPI _renderingApi
bool enable_software_rendering
std::optional< ThreadConfig > ui_config
FlutterBinaryMessengerRelay * _binaryMessenger
fml::scoped_nsobject< FlutterBasicMessageChannel > _systemChannel
NSObject< FlutterBinaryMessenger > * parent
static void IOSPlatformThreadConfigSetter(const fml::Thread::ThreadConfig &config)
fml::scoped_nsobject< FlutterMethodChannel > _navigationChannel
void handleMethodCall:result:(FlutterMethodCall *call, [result] FlutterResult result)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data observatory The hostname IP address on which the Dart Observatory should be served If not defaults to or::depending on whether ipv6 is specified disable Disable the Dart Observatory The observatory is never available in release mode Bind to the IPv6 localhost address for the Dart Observatory Ignored if observatory host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent Remove all existing persistent cache This is mainly for debugging purposes such as reproducing the shader compilation jank use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network policy
FlutterViewController * viewController
FlutterEngine * flutterEngine
FlutterEngine * _flutterEngine
fml::scoped_nsobject< FlutterBasicMessageChannel > _settingsChannel