5#define FML_USED_ON_EMBEDDER
7#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
10#import <UIKit/UIKit.h>
14#include "flutter/common/constants.h"
15#include "flutter/shell/common/switches.h"
16#import "flutter/shell/platform/darwin/common/command_line.h"
21#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
32 static dispatch_once_t once_token = 0;
33 dispatch_once(&once_token, ^{
34 id<MTLDevice>
device = MTLCreateSystemDefaultDevice();
35 if (@available(iOS 13.0, *)) {
40 result = [
device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
58 bool hasExplicitBundle = bundle != nil;
73 settings.log_message_callback = [](
const std::string& tag,
const std::string&
message) {
82 syslog(LOG_ALERT,
"%.*s", (
int)
log.size(),
log.c_str());
85 settings.enable_platform_isolates =
true;
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;
99 if (hasExplicitBundle) {
100 NSString* executablePath = bundle.executablePath;
101 if ([[NSFileManager defaultManager] fileExistsAtPath:executablePath]) {
102 settings.application_library_path.push_back(executablePath.UTF8String);
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);
120 if (
settings.application_library_path.empty()) {
121 NSString* applicationFrameworkPath = [mainBundle pathForResource:
@"Frameworks/App.framework"
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);
137 if (assetsPath.length == 0) {
138 NSLog(
@"Failed to find assets path for \"%@\
"", bundle);
140 settings.assets_path = assetsPath.UTF8String;
146 NSURL* applicationKernelSnapshotURL =
148 relativeToURL:[NSURL fileURLWithPath:assetsPath]];
150 if ([applicationKernelSnapshotURL checkResourceIsReachableAndReturnError:&
error]) {
151 settings.application_kernel_asset = applicationKernelSnapshotURL.path.UTF8String;
153 NSLog(
@"Failed to find snapshot at %@: %@", applicationKernelSnapshotURL.path,
error);
162 settings.may_insecurely_connect_to_all_domains =
true;
163 settings.domain_network_policy =
"";
166#if TARGET_OS_SIMULATOR
173 NSNumber* nsEnableWideGamut = [mainBundle objectForInfoDictionaryKey:
@"FLTEnableWideGamut"];
174 BOOL enableWideGamut =
176 settings.enable_wide_gamut = enableWideGamut;
183 if (!command_line.HasOption(
"enable-impeller")) {
185 NSNumber* enableImpeller = [bundle objectForInfoDictionaryKey:
@"FLTEnableImpeller"];
186 if (enableImpeller == nil) {
188 enableImpeller = [mainBundle objectForInfoDictionaryKey:
@"FLTEnableImpeller"];
191 if (enableImpeller != nil) {
192 settings.enable_impeller = enableImpeller.boolValue;
196 settings.warn_on_impeller_opt_out =
true;
198 NSNumber* enableTraceSystrace = [mainBundle objectForInfoDictionaryKey:
@"FLTTraceSystrace"];
200 if (enableTraceSystrace != nil) {
201 settings.trace_systrace = enableTraceSystrace.boolValue;
204 NSNumber* enableDartAsserts = [mainBundle objectForInfoDictionaryKey:
@"FLTEnableDartAsserts"];
205 if (enableDartAsserts != nil) {
206 settings.dart_flags.push_back(
"--enable-asserts");
209 NSNumber* enableDartProfiling = [mainBundle objectForInfoDictionaryKey:
@"FLTEnableDartProfiling"];
211 if (enableDartProfiling != nil) {
212 settings.enable_dart_profiling = enableDartProfiling.boolValue;
216 NSNumber* leakDartVM = [mainBundle objectForInfoDictionaryKey:
@"FLTLeakDartVM"];
218 if (leakDartVM != nil) {
219 settings.leak_vm = leakDartVM.boolValue;
222#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
225 auto make_mapping_callback = [](
const uint8_t* mapping,
size_t size) {
226 return [mapping,
size]() {
return std::make_unique<fml::NonOwnedMapping>(mapping,
size); };
229 settings.dart_library_sources_kernel =
239 if (
settings.old_gen_heap_size <= 0) {
240 settings.old_gen_heap_size =
std::round([NSProcessInfo processInfo].physicalMemory * .48 /
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;
252 NSNumber* enable_embedder_api =
253 [mainBundle objectForInfoDictionaryKey:
@"FLTEnableIOSEmbedderAPI"];
255 if (enable_embedder_api) {
256 settings.enable_embedder_api = enable_embedder_api.boolValue;
269@dynamic dartEntrypointArguments;
271#pragma mark - Override base class designated initializers
273- (instancetype)
init {
274 return [
self initWithPrecompiledDartBundle:nil];
277#pragma mark - Designated initializers
279- (instancetype)initWithPrecompiledDartBundle:(nullable NSBundle*)bundle {
289- (instancetype)initWithSettings:(const
flutter::Settings&)settings {
290 self = [
self initWithPrecompiledDartBundle:nil];
299#pragma mark - PlatformData accessors
301- (const
flutter::PlatformData)defaultPlatformData {
303 PlatformData.
lifecycle_state = std::string(
"AppLifecycleState.detached");
307#pragma mark - Settings accessors
309- (const
flutter::Settings&)settings {
313- (
flutter::RunConfiguration)runConfiguration {
314 return [
self runConfigurationForEntrypoint:nil];
317- (
flutter::RunConfiguration)runConfigurationForEntrypoint:(nullable NSString*)entrypointOrNil {
318 return [
self runConfigurationForEntrypoint:entrypointOrNil libraryOrNil:nil];
321- (
flutter::RunConfiguration)runConfigurationForEntrypoint:(nullable NSString*)entrypointOrNil
322 libraryOrNil:(nullable NSString*)dartLibraryOrNil {
323 return [
self runConfigurationForEntrypoint:entrypointOrNil
324 libraryOrNil:dartLibraryOrNil
328- (
flutter::RunConfiguration)runConfigurationForEntrypoint:(nullable NSString*)entrypointOrNil
329 libraryOrNil:(nullable NSString*)dartLibraryOrNil
331 (nullable NSArray<NSString*>*)entrypointArgs {
333 if (dartLibraryOrNil && entrypointOrNil) {
334 config.SetEntrypointAndLibrary(std::string([entrypointOrNil UTF8String]),
335 std::string([dartLibraryOrNil UTF8String]));
337 }
else if (entrypointOrNil) {
338 config.SetEntrypoint(std::string([entrypointOrNil UTF8String]));
341 if (entrypointArgs.count) {
342 std::vector<std::string> cppEntrypointArgs;
343 for (NSString* arg in entrypointArgs) {
344 cppEntrypointArgs.push_back(std::string([arg UTF8String]));
346 config.SetEntrypointArgs(std::move(cppEntrypointArgs));
352#pragma mark - Assets-related utilities
354+ (NSString*)flutterAssetsName:(NSBundle*)bundle {
361+ (NSString*)domainNetworkPolicy:(NSDictionary*)appTransportSecurity {
363 NSDictionary* exceptionDomains = appTransportSecurity[@"NSExceptionDomains"];
364 if (exceptionDomains == nil) {
367 NSMutableArray* networkConfigArray = [[NSMutableArray alloc] init];
368 for (NSString* domain in exceptionDomains) {
369 NSDictionary* domainConfiguration = exceptionDomains[domain];
371 bool includesSubDomains = [domainConfiguration[@"NSIncludesSubdomains"] boolValue];
372 bool allowsCleartextCommunication =
373 [domainConfiguration[@"NSExceptionAllowsInsecureHTTPLoads"] boolValue];
374 [networkConfigArray addObject:@[
375 domain, includesSubDomains ? @YES : @NO, allowsCleartextCommunication ? @YES : @NO
378 NSData* jsonData = [NSJSONSerialization dataWithJSONObject:networkConfigArray
381 return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
384+ (bool)allowsArbitraryLoads:(NSDictionary*)appTransportSecurity {
385 return [appTransportSecurity[@"NSAllowsArbitraryLoads"] boolValue];
388+ (NSString*)lookupKeyForAsset:(NSString*)asset {
389 return [
self lookupKeyForAsset:asset fromBundle:nil];
392+ (NSString*)lookupKeyForAsset:(NSString*)asset fromBundle:(nullable NSBundle*)bundle {
394 return [NSString stringWithFormat:@"%@/%@", flutterAssetsName, asset];
397+ (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
398 return [
self lookupKeyForAsset:asset fromPackage:package fromBundle:nil];
401+ (NSString*)lookupKeyForAsset:(NSString*)asset
402 fromPackage:(NSString*)package
403 fromBundle:(nullable NSBundle*)bundle {
404 return [
self lookupKeyForAsset:[NSString stringWithFormat:@"packages/%@/%@", package, asset]
408+ (NSString*)defaultBundleIdentifier {
409 return @"io.flutter.flutter.app";
412- (
BOOL)isWideGamutEnabled {
413 return _settings.enable_wide_gamut;
416- (
BOOL)isImpellerEnabled {
417 return _settings.enable_impeller;
NSBundle * FLTFrameworkBundleWithIdentifier(NSString *flutterFrameworkBundleID)
NSString * FLTAssetsPathFromBundle(NSBundle *bundle)
NSBundle * FLTGetApplicationBundle()
NSString * FLTAssetPath(NSBundle *bundle)
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...
static RunConfiguration InferFromSettings(const Settings &settings, const fml::RefPtr< fml::TaskRunner > &io_worker=nullptr, IsolateLaunchType launch_type=IsolateLaunchType::kNewGroup)
Attempts to infer a run configuration from the settings object. This tries to create a run configurat...
void RemoveTaskObserver(intptr_t key)
void AddTaskObserver(intptr_t key, const fml::closure &callback)
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
NSString * flutterAssetsName:(NSBundle *bundle)
static const char * kApplicationKernelSnapshotFileName
const intptr_t kPlatformStrongDillSize
FLUTTER_ASSERT_ARC const uint8_t kPlatformStrongDill[]
flutter::Settings FLTDefaultSettingsForBundle(NSBundle *bundle, NSProcessInfo *processInfoOrNil)
static BOOL DoesHardwareSupportWideGamut()
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
fml::CommandLine CommandLineFromNSProcessInfo(NSProcessInfo *processInfoOrNil=nil)
constexpr double kMegaByteSizeInBytes
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
std::function< void()> closure