Flutter Engine
The Flutter Engine
Macros | Functions | Variables
FlutterDartProject.mm File Reference
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
#import <Metal/Metal.h>
#import <UIKit/UIKit.h>
#include <syslog.h>
#include "flutter/common/constants.h"
#include "flutter/shell/common/switches.h"
#import "flutter/shell/platform/darwin/common/command_line.h"

Go to the source code of this file.

Macros

#define FML_USED_ON_EMBEDDER
 

Functions

static BOOL DoesHardwareSupportWideGamut ()
 
flutter::Settings FLTDefaultSettingsForBundle (NSBundle *bundle, NSProcessInfo *processInfoOrNil)
 

Variables

FLUTTER_ASSERT_ARC const uint8_t kPlatformStrongDill []
 
const intptr_t kPlatformStrongDillSize
 
static const char * kApplicationKernelSnapshotFileName = "kernel_blob.bin"
 

Macro Definition Documentation

◆ FML_USED_ON_EMBEDDER

#define FML_USED_ON_EMBEDDER

Definition at line 5 of file FlutterDartProject.mm.

Function Documentation

◆ DoesHardwareSupportWideGamut()

static BOOL DoesHardwareSupportWideGamut ( )
static

Definition at line 30 of file FlutterDartProject.mm.

30 {
31 static BOOL result = NO;
32 static dispatch_once_t once_token = 0;
33 dispatch_once(&once_token, ^{
34 id<MTLDevice> device = MTLCreateSystemDefaultDevice();
35 if (@available(iOS 13.0, *)) {
36 // MTLGPUFamilyApple2 = A9/A10
37 result = [device supportsFamily:MTLGPUFamilyApple2];
38 } else {
39 // A9/A10 on iOS 10+
40 result = [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
41 }
42 });
43 return result;
44}
VkDevice device
Definition: main.cc:53
GAsyncResult * result
int BOOL
Definition: windows_types.h:37

◆ FLTDefaultSettingsForBundle()

flutter::Settings FLTDefaultSettingsForBundle ( NSBundle *  bundle,
NSProcessInfo *  processInfoOrNil 
)

Definition at line 46 of file FlutterDartProject.mm.

46 {
47 auto command_line = flutter::CommandLineFromNSProcessInfo(processInfoOrNil);
48
49 // Precedence:
50 // 1. Settings from the specified NSBundle (except for enable-impeller).
51 // 2. Settings passed explicitly via command-line arguments.
52 // 3. Settings from the NSBundle with the default bundle ID.
53 // 4. Settings from the main NSBundle and default values.
54
55 NSBundle* mainBundle = FLTGetApplicationBundle();
56 NSBundle* engineBundle = [NSBundle bundleForClass:[FlutterDartProject class]];
57
58 bool hasExplicitBundle = bundle != nil;
59 if (bundle == nil) {
60 bundle = FLTFrameworkBundleWithIdentifier([FlutterDartProject defaultBundleIdentifier]);
61 }
62
63 auto settings = flutter::SettingsFromCommandLine(command_line);
64
65 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
67 };
68
69 settings.task_observer_remove = [](intptr_t key) {
71 };
72
73 settings.log_message_callback = [](const std::string& tag, const std::string& message) {
74 // TODO(cbracken): replace this with os_log-based approach.
75 // https://github.com/flutter/flutter/issues/44030
76 std::stringstream stream;
77 if (!tag.empty()) {
78 stream << tag << ": ";
79 }
80 stream << message;
81 std::string log = stream.str();
82 syslog(LOG_ALERT, "%.*s", (int)log.size(), log.c_str());
83 };
84
85 settings.enable_platform_isolates = true;
86
87 // The command line arguments may not always be complete. If they aren't, attempt to fill in
88 // defaults.
89
90 // Flutter ships the ICU data file in the bundle of the engine. Look for it there.
91 if (settings.icu_data_path.empty()) {
92 NSString* icuDataPath = [engineBundle pathForResource:@"icudtl" ofType:@"dat"];
93 if (icuDataPath.length > 0) {
94 settings.icu_data_path = icuDataPath.UTF8String;
95 }
96 }
97
99 if (hasExplicitBundle) {
100 NSString* executablePath = bundle.executablePath;
101 if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) {
102 settings.application_library_path.push_back(executablePath.UTF8String);
103 }
104 }
105
106 // No application bundle specified. Try a known location from the main bundle's Info.plist.
107 if (settings.application_library_path.empty()) {
108 NSString* libraryName = [mainBundle objectForInfoDictionaryKey:@"FLTLibraryPath"];
109 NSString* libraryPath = [mainBundle pathForResource:libraryName ofType:@""];
110 if (libraryPath.length > 0) {
111 NSString* executablePath = [NSBundle bundleWithPath:libraryPath].executablePath;
112 if (executablePath.length > 0) {
113 settings.application_library_path.push_back(executablePath.UTF8String);
114 }
115 }
116 }
117
118 // In case the application bundle is still not specified, look for the App.framework in the
119 // Frameworks directory.
120 if (settings.application_library_path.empty()) {
121 NSString* applicationFrameworkPath = [mainBundle pathForResource:@"Frameworks/App.framework"
122 ofType:@""];
123 if (applicationFrameworkPath.length > 0) {
124 NSString* executablePath =
125 [NSBundle bundleWithPath:applicationFrameworkPath].executablePath;
126 if (executablePath.length > 0) {
127 settings.application_library_path.push_back(executablePath.UTF8String);
128 }
129 }
130 }
131 }
132
133 // Checks to see if the flutter assets directory is already present.
134 if (settings.assets_path.empty()) {
135 NSString* assetsPath = FLTAssetsPathFromBundle(bundle);
136
137 if (assetsPath.length == 0) {
138 NSLog(@"Failed to find assets path for \"%@\"", bundle);
139 } else {
140 settings.assets_path = assetsPath.UTF8String;
141
142 // Check if there is an application kernel snapshot in the assets directory we could
143 // potentially use. Looking for the snapshot makes sense only if we have a VM that can use
144 // it.
146 NSURL* applicationKernelSnapshotURL =
147 [NSURL URLWithString:@(kApplicationKernelSnapshotFileName)
148 relativeToURL:[NSURL fileURLWithPath:assetsPath]];
149 NSError* error;
150 if ([applicationKernelSnapshotURL checkResourceIsReachableAndReturnError:&error]) {
151 settings.application_kernel_asset = applicationKernelSnapshotURL.path.UTF8String;
152 } else {
153 NSLog(@"Failed to find snapshot at %@: %@", applicationKernelSnapshotURL.path, error);
154 }
155 }
156 }
157 }
158
159 // Domain network configuration
160 // Disabled in https://github.com/flutter/flutter/issues/72723.
161 // Re-enable in https://github.com/flutter/flutter/issues/54448.
162 settings.may_insecurely_connect_to_all_domains = true;
163 settings.domain_network_policy = "";
164
165 // Whether to enable wide gamut colors.
166#if TARGET_OS_SIMULATOR
167 // As of Xcode 14.1, the wide gamut surface pixel formats are not supported by
168 // the simulator.
169 settings.enable_wide_gamut = false;
170 // Removes unused function warning.
172#else
173 NSNumber* nsEnableWideGamut = [mainBundle objectForInfoDictionaryKey:@"FLTEnableWideGamut"];
174 BOOL enableWideGamut =
175 (nsEnableWideGamut ? nsEnableWideGamut.boolValue : YES) && DoesHardwareSupportWideGamut();
176 settings.enable_wide_gamut = enableWideGamut;
177#endif
178
179 // TODO(dnfield): We should reverse the order for all these settings so that command line options
180 // are preferred to plist settings. https://github.com/flutter/flutter/issues/124049
181 // Whether to enable Impeller. If the command line explicitly
182 // specified an option for this, ignore what's in the plist.
183 if (!command_line.HasOption("enable-impeller")) {
184 // Next, look in the app bundle.
185 NSNumber* enableImpeller = [bundle objectForInfoDictionaryKey:@"FLTEnableImpeller"];
186 if (enableImpeller == nil) {
187 // If it isn't in the app bundle, look in the main bundle.
188 enableImpeller = [mainBundle objectForInfoDictionaryKey:@"FLTEnableImpeller"];
189 }
190 // Change the default only if the option is present.
191 if (enableImpeller != nil) {
192 settings.enable_impeller = enableImpeller.boolValue;
193 }
194 }
195
196 settings.warn_on_impeller_opt_out = true;
197
198 NSNumber* enableTraceSystrace = [mainBundle objectForInfoDictionaryKey:@"FLTTraceSystrace"];
199 // Change the default only if the option is present.
200 if (enableTraceSystrace != nil) {
201 settings.trace_systrace = enableTraceSystrace.boolValue;
202 }
203
204 NSNumber* enableDartAsserts = [mainBundle objectForInfoDictionaryKey:@"FLTEnableDartAsserts"];
205 if (enableDartAsserts != nil) {
206 settings.dart_flags.push_back("--enable-asserts");
207 }
208
209 NSNumber* enableDartProfiling = [mainBundle objectForInfoDictionaryKey:@"FLTEnableDartProfiling"];
210 // Change the default only if the option is present.
211 if (enableDartProfiling != nil) {
212 settings.enable_dart_profiling = enableDartProfiling.boolValue;
213 }
214
215 // Leak Dart VM settings, set whether leave or clean up the VM after the last shell shuts down.
216 NSNumber* leakDartVM = [mainBundle objectForInfoDictionaryKey:@"FLTLeakDartVM"];
217 // It will change the default leak_vm value in settings only if the key exists.
218 if (leakDartVM != nil) {
219 settings.leak_vm = leakDartVM.boolValue;
220 }
221
222#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
223 // There are no ownership concerns here as all mappings are owned by the
224 // embedder and not the engine.
225 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
226 return [mapping, size]() { return std::make_unique<fml::NonOwnedMapping>(mapping, size); };
227 };
228
229 settings.dart_library_sources_kernel =
230 make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
231#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
232
233 // If we even support setting this e.g. from the command line or the plist,
234 // we should let the user override it.
235 // Otherwise, we want to set this to a value that will avoid having the OS
236 // kill us. On most iOS devices, that happens somewhere near half
237 // the available memory.
238 // The VM expects this value to be in megabytes.
239 if (settings.old_gen_heap_size <= 0) {
240 settings.old_gen_heap_size = std::round([NSProcessInfo processInfo].physicalMemory * .48 /
242 }
243
244 // This is the formula Android uses.
245 // https://android.googlesource.com/platform/frameworks/base/+/39ae5bac216757bc201490f4c7b8c0f63006c6cd/libs/hwui/renderthread/CacheManager.cpp#45
246 CGFloat scale = [UIScreen mainScreen].scale;
247 CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width * scale;
248 CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height * scale;
249 settings.resource_cache_max_bytes_threshold = screenWidth * screenHeight * 12 * 4;
250
251 // Whether to enable ios embedder api.
252 NSNumber* enable_embedder_api =
253 [mainBundle objectForInfoDictionaryKey:@"FLTEnableIOSEmbedderAPI"];
254 // Change the default only if the option is present.
255 if (enable_embedder_api) {
256 settings.enable_embedder_api = enable_embedder_api.boolValue;
257 }
258
259 return settings;
260}
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
NSBundle * FLTGetApplicationBundle()
static void round(SkPoint *p)
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:205
void RemoveTaskObserver(intptr_t key)
Definition: message_loop.cc:68
void AddTaskObserver(intptr_t key, const fml::closure &callback)
Definition: message_loop.cc:64
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
static const char * kApplicationKernelSnapshotFileName
const intptr_t kPlatformStrongDillSize
FLUTTER_ASSERT_ARC const uint8_t kPlatformStrongDill[]
static BOOL DoesHardwareSupportWideGamut()
Win32Message message
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
Definition: switches.cc:228
fml::CommandLine CommandLineFromNSProcessInfo(NSProcessInfo *processInfoOrNil=nil)
Definition: command_line.mm:11
constexpr double kMegaByteSizeInBytes
Definition: constants.h:9
it will be possible to load the file into Perfetto s trace viewer 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
Definition: switches.h:259
std::function< void()> closure
Definition: closure.h:14
const Scalar scale

Variable Documentation

◆ kApplicationKernelSnapshotFileName

const char* kApplicationKernelSnapshotFileName = "kernel_blob.bin"
static

Definition at line 28 of file FlutterDartProject.mm.

◆ kPlatformStrongDill

FLUTTER_ASSERT_ARC const uint8_t kPlatformStrongDill[]
extern

◆ kPlatformStrongDillSize

const intptr_t kPlatformStrongDillSize
extern