@@ -1979,6 +1979,381 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
1979
1979
return kSuccess ;
1980
1980
}
1981
1981
1982
+ FlutterEngineResult FlutterEngineSpawn (size_t version,
1983
+ const FlutterRendererConfig* config,
1984
+ const FlutterProjectArgs* args,
1985
+ void * user_data,
1986
+ FLUTTER_API_SYMBOL (FlutterEngine)
1987
+ engine_spawner,
1988
+ FLUTTER_API_SYMBOL(FlutterEngine) *
1989
+ engine_out) {
1990
+ // Step 0. Figure out arguments for shell spawn.
1991
+ if (version != FLUTTER_ENGINE_VERSION) {
1992
+ return LOG_EMBEDDER_ERROR (
1993
+ kInvalidLibraryVersion ,
1994
+ " Flutter embedder version mismatch. There has been a breaking change. "
1995
+ " Please consult the changelog and update the embedder." );
1996
+ }
1997
+
1998
+ if (engine_out == nullptr ) {
1999
+ return LOG_EMBEDDER_ERROR (kInvalidArguments ,
2000
+ " The engine out parameter was missing." );
2001
+ }
2002
+
2003
+ if (args == nullptr ) {
2004
+ return LOG_EMBEDDER_ERROR (kInvalidArguments ,
2005
+ " The Flutter project arguments were missing." );
2006
+ }
2007
+
2008
+ if (SAFE_ACCESS (args, assets_path, nullptr ) == nullptr ) {
2009
+ return LOG_EMBEDDER_ERROR (
2010
+ kInvalidArguments ,
2011
+ " The assets path in the Flutter project arguments was missing." );
2012
+ }
2013
+
2014
+ if (SAFE_ACCESS (args, main_path__unused__, nullptr ) != nullptr ) {
2015
+ FML_LOG (WARNING)
2016
+ << " FlutterProjectArgs.main_path is deprecated and should be set null." ;
2017
+ }
2018
+
2019
+ if (SAFE_ACCESS (args, packages_path__unused__, nullptr ) != nullptr ) {
2020
+ FML_LOG (WARNING) << " FlutterProjectArgs.packages_path is deprecated and "
2021
+ " should be set null." ;
2022
+ }
2023
+
2024
+ if (!IsRendererValid (config)) {
2025
+ return LOG_EMBEDDER_ERROR (kInvalidArguments ,
2026
+ " The renderer configuration was invalid." );
2027
+ }
2028
+
2029
+ std::string icu_data_path;
2030
+ if (SAFE_ACCESS (args, icu_data_path, nullptr ) != nullptr ) {
2031
+ icu_data_path = SAFE_ACCESS (args, icu_data_path, nullptr );
2032
+ }
2033
+
2034
+ if (SAFE_ACCESS (args, persistent_cache_path, nullptr ) != nullptr ) {
2035
+ std::string persistent_cache_path =
2036
+ SAFE_ACCESS (args, persistent_cache_path, nullptr );
2037
+ flutter::PersistentCache::SetCacheDirectoryPath (persistent_cache_path);
2038
+ }
2039
+
2040
+ if (SAFE_ACCESS (args, is_persistent_cache_read_only, false )) {
2041
+ flutter::PersistentCache::gIsReadOnly = true ;
2042
+ }
2043
+
2044
+ fml::CommandLine command_line;
2045
+ if (SAFE_ACCESS (args, command_line_argc, 0 ) != 0 &&
2046
+ SAFE_ACCESS (args, command_line_argv, nullptr ) != nullptr ) {
2047
+ command_line = fml::CommandLineFromArgcArgv (
2048
+ SAFE_ACCESS (args, command_line_argc, 0 ),
2049
+ SAFE_ACCESS (args, command_line_argv, nullptr ));
2050
+ }
2051
+
2052
+ flutter::Settings settings = flutter::SettingsFromCommandLine (command_line);
2053
+
2054
+ if (SAFE_ACCESS (args, aot_data, nullptr )) {
2055
+ if (SAFE_ACCESS (args, vm_snapshot_data, nullptr ) ||
2056
+ SAFE_ACCESS (args, vm_snapshot_instructions, nullptr ) ||
2057
+ SAFE_ACCESS (args, isolate_snapshot_data, nullptr ) ||
2058
+ SAFE_ACCESS (args, isolate_snapshot_instructions, nullptr )) {
2059
+ return LOG_EMBEDDER_ERROR (
2060
+ kInvalidArguments ,
2061
+ " Multiple AOT sources specified. Embedders should provide either "
2062
+ " *_snapshot_* buffers or aot_data, not both." );
2063
+ }
2064
+ }
2065
+
2066
+ if (flutter::DartVM::IsRunningPrecompiledCode ()) {
2067
+ PopulateAOTSnapshotMappingCallbacks (args, settings);
2068
+ } else {
2069
+ PopulateJITSnapshotMappingCallbacks (args, settings);
2070
+ }
2071
+
2072
+ settings.icu_data_path = icu_data_path;
2073
+ settings.assets_path = args->assets_path ;
2074
+ settings.leak_vm = !SAFE_ACCESS (args, shutdown_dart_vm_when_done, false );
2075
+ settings.old_gen_heap_size = SAFE_ACCESS (args, dart_old_gen_heap_size, -1 );
2076
+
2077
+ if (!flutter::DartVM::IsRunningPrecompiledCode ()) {
2078
+ // Verify the assets path contains Dart 2 kernel assets.
2079
+ const std::string kApplicationKernelSnapshotFileName = " kernel_blob.bin" ;
2080
+ std::string application_kernel_path = fml::paths::JoinPaths (
2081
+ {settings.assets_path , kApplicationKernelSnapshotFileName });
2082
+ if (!fml::IsFile (application_kernel_path)) {
2083
+ return LOG_EMBEDDER_ERROR (
2084
+ kInvalidArguments ,
2085
+ " Not running in AOT mode but could not resolve the kernel binary." );
2086
+ }
2087
+ settings.application_kernel_asset = kApplicationKernelSnapshotFileName ;
2088
+ }
2089
+
2090
+ settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
2091
+ fml::MessageLoop::GetCurrent ().AddTaskObserver (key, callback);
2092
+ };
2093
+ settings.task_observer_remove = [](intptr_t key) {
2094
+ fml::MessageLoop::GetCurrent ().RemoveTaskObserver (key);
2095
+ };
2096
+ if (SAFE_ACCESS (args, root_isolate_create_callback, nullptr ) != nullptr ) {
2097
+ VoidCallback callback =
2098
+ SAFE_ACCESS (args, root_isolate_create_callback, nullptr );
2099
+ settings.root_isolate_create_callback =
2100
+ [callback, user_data](const auto & isolate) { callback (user_data); };
2101
+ }
2102
+ if (SAFE_ACCESS (args, log_message_callback, nullptr ) != nullptr ) {
2103
+ FlutterLogMessageCallback callback =
2104
+ SAFE_ACCESS (args, log_message_callback, nullptr );
2105
+ settings.log_message_callback = [callback, user_data](
2106
+ const std::string& tag,
2107
+ const std::string& message) {
2108
+ callback (tag.c_str (), message.c_str (), user_data);
2109
+ };
2110
+ }
2111
+ if (SAFE_ACCESS (args, log_tag, nullptr ) != nullptr ) {
2112
+ settings.log_tag = SAFE_ACCESS (args, log_tag, nullptr );
2113
+ }
2114
+
2115
+ bool has_update_semantics_2_callback =
2116
+ SAFE_ACCESS (args, update_semantics_callback2, nullptr ) != nullptr ;
2117
+ bool has_update_semantics_callback =
2118
+ SAFE_ACCESS (args, update_semantics_callback, nullptr ) != nullptr ;
2119
+ bool has_legacy_update_semantics_callback =
2120
+ SAFE_ACCESS (args, update_semantics_node_callback, nullptr ) != nullptr ||
2121
+ SAFE_ACCESS (args, update_semantics_custom_action_callback, nullptr ) !=
2122
+ nullptr ;
2123
+
2124
+ int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0 ) +
2125
+ (has_update_semantics_callback ? 1 : 0 ) +
2126
+ (has_legacy_update_semantics_callback ? 1 : 0 );
2127
+
2128
+ if (semantic_callback_count > 1 ) {
2129
+ return LOG_EMBEDDER_ERROR (
2130
+ kInvalidArguments ,
2131
+ " Multiple semantics update callbacks provided. "
2132
+ " Embedders should provide either `update_semantics_callback2`, "
2133
+ " `update_semantics_callback`, or both "
2134
+ " `update_semantics_node_callback` and "
2135
+ " `update_semantics_custom_action_callback`." );
2136
+ }
2137
+
2138
+ flutter::PlatformViewEmbedder::UpdateSemanticsCallback
2139
+ update_semantics_callback =
2140
+ CreateEmbedderSemanticsUpdateCallback (args, user_data);
2141
+
2142
+ flutter::PlatformViewEmbedder::PlatformMessageResponseCallback
2143
+ platform_message_response_callback = nullptr ;
2144
+ if (SAFE_ACCESS (args, platform_message_callback, nullptr ) != nullptr ) {
2145
+ platform_message_response_callback =
2146
+ [ptr = args->platform_message_callback ,
2147
+ user_data](std::unique_ptr<flutter::PlatformMessage> message) {
2148
+ auto handle = new FlutterPlatformMessageResponseHandle ();
2149
+ const FlutterPlatformMessage incoming_message = {
2150
+ sizeof (FlutterPlatformMessage), // struct_size
2151
+ message->channel ().c_str (), // channel
2152
+ message->data ().GetMapping (), // message
2153
+ message->data ().GetSize (), // message_size
2154
+ handle, // response_handle
2155
+ };
2156
+ handle->message = std::move (message);
2157
+ return ptr (&incoming_message, user_data);
2158
+ };
2159
+ }
2160
+
2161
+ flutter::VsyncWaiterEmbedder::VsyncCallback vsync_callback = nullptr ;
2162
+ if (SAFE_ACCESS (args, vsync_callback, nullptr ) != nullptr ) {
2163
+ vsync_callback = [ptr = args->vsync_callback , user_data](intptr_t baton) {
2164
+ return ptr (user_data, baton);
2165
+ };
2166
+ }
2167
+
2168
+ flutter::PlatformViewEmbedder::ComputePlatformResolvedLocaleCallback
2169
+ compute_platform_resolved_locale_callback = nullptr ;
2170
+ if (SAFE_ACCESS (args, compute_platform_resolved_locale_callback, nullptr ) !=
2171
+ nullptr ) {
2172
+ compute_platform_resolved_locale_callback =
2173
+ [ptr = args->compute_platform_resolved_locale_callback ](
2174
+ const std::vector<std::string>& supported_locales_data) {
2175
+ const size_t number_of_strings_per_locale = 3 ;
2176
+ size_t locale_count =
2177
+ supported_locales_data.size () / number_of_strings_per_locale;
2178
+ std::vector<FlutterLocale> supported_locales;
2179
+ std::vector<const FlutterLocale*> supported_locales_ptr;
2180
+ for (size_t i = 0 ; i < locale_count; ++i) {
2181
+ supported_locales.push_back (
2182
+ {.struct_size = sizeof (FlutterLocale),
2183
+ .language_code =
2184
+ supported_locales_data[i * number_of_strings_per_locale +
2185
+ 0 ]
2186
+ .c_str (),
2187
+ .country_code =
2188
+ supported_locales_data[i * number_of_strings_per_locale +
2189
+ 1 ]
2190
+ .c_str (),
2191
+ .script_code =
2192
+ supported_locales_data[i * number_of_strings_per_locale +
2193
+ 2 ]
2194
+ .c_str (),
2195
+ .variant_code = nullptr });
2196
+ supported_locales_ptr.push_back (&supported_locales[i]);
2197
+ }
2198
+
2199
+ const FlutterLocale* result =
2200
+ ptr (supported_locales_ptr.data (), locale_count);
2201
+
2202
+ std::unique_ptr<std::vector<std::string>> out =
2203
+ std::make_unique<std::vector<std::string>>();
2204
+ if (result) {
2205
+ std::string language_code (SAFE_ACCESS (result, language_code, " " ));
2206
+ if (language_code != " " ) {
2207
+ out->push_back (language_code);
2208
+ out->emplace_back (SAFE_ACCESS (result, country_code, " " ));
2209
+ out->emplace_back (SAFE_ACCESS (result, script_code, " " ));
2210
+ }
2211
+ }
2212
+ return out;
2213
+ };
2214
+ }
2215
+
2216
+ flutter::PlatformViewEmbedder::OnPreEngineRestartCallback
2217
+ on_pre_engine_restart_callback = nullptr ;
2218
+ if (SAFE_ACCESS (args, on_pre_engine_restart_callback, nullptr ) != nullptr ) {
2219
+ on_pre_engine_restart_callback = [ptr =
2220
+ args->on_pre_engine_restart_callback ,
2221
+ user_data]() { return ptr (user_data); };
2222
+ }
2223
+
2224
+ auto external_view_embedder_result =
2225
+ InferExternalViewEmbedderFromArgs (SAFE_ACCESS (args, compositor, nullptr ));
2226
+ if (external_view_embedder_result.second ) {
2227
+ return LOG_EMBEDDER_ERROR (kInvalidArguments ,
2228
+ " Compositor arguments were invalid." );
2229
+ }
2230
+
2231
+ flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table =
2232
+ {
2233
+ update_semantics_callback, //
2234
+ platform_message_response_callback, //
2235
+ vsync_callback, //
2236
+ compute_platform_resolved_locale_callback, //
2237
+ on_pre_engine_restart_callback, //
2238
+ };
2239
+
2240
+ auto on_create_platform_view = InferPlatformViewCreationCallback (
2241
+ config, user_data, platform_dispatch_table,
2242
+ std::move (external_view_embedder_result.first ));
2243
+
2244
+ if (!on_create_platform_view) {
2245
+ return LOG_EMBEDDER_ERROR (
2246
+ kInternalInconsistency ,
2247
+ " Could not infer platform view creation callback." );
2248
+ }
2249
+
2250
+ flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
2251
+ [](flutter::Shell& shell) {
2252
+ return std::make_unique<flutter::Rasterizer>(shell);
2253
+ };
2254
+
2255
+ using ExternalTextureResolver = flutter::EmbedderExternalTextureResolver;
2256
+ std::unique_ptr<ExternalTextureResolver> external_texture_resolver;
2257
+ external_texture_resolver = std::make_unique<ExternalTextureResolver>();
2258
+
2259
+ #ifdef SHELL_ENABLE_GL
2260
+ flutter::EmbedderExternalTextureGL::ExternalTextureCallback
2261
+ external_texture_callback;
2262
+ if (config->type == kOpenGL ) {
2263
+ const FlutterOpenGLRendererConfig* open_gl_config = &config->open_gl ;
2264
+ if (SAFE_ACCESS (open_gl_config, gl_external_texture_frame_callback,
2265
+ nullptr ) != nullptr ) {
2266
+ external_texture_callback =
2267
+ [ptr = open_gl_config->gl_external_texture_frame_callback , user_data](
2268
+ int64_t texture_identifier, size_t width,
2269
+ size_t height) -> std::unique_ptr<FlutterOpenGLTexture> {
2270
+ std::unique_ptr<FlutterOpenGLTexture> texture =
2271
+ std::make_unique<FlutterOpenGLTexture>();
2272
+ if (!ptr (user_data, texture_identifier, width, height, texture.get ())) {
2273
+ return nullptr ;
2274
+ }
2275
+ return texture;
2276
+ };
2277
+ external_texture_resolver =
2278
+ std::make_unique<ExternalTextureResolver>(external_texture_callback);
2279
+ }
2280
+ }
2281
+ #endif
2282
+ #ifdef SHELL_ENABLE_METAL
2283
+ flutter::EmbedderExternalTextureMetal::ExternalTextureCallback
2284
+ external_texture_metal_callback;
2285
+ if (config->type == kMetal ) {
2286
+ const FlutterMetalRendererConfig* metal_config = &config->metal ;
2287
+ if (SAFE_ACCESS (metal_config, external_texture_frame_callback, nullptr )) {
2288
+ external_texture_metal_callback =
2289
+ [ptr = metal_config->external_texture_frame_callback , user_data](
2290
+ int64_t texture_identifier, size_t width,
2291
+ size_t height) -> std::unique_ptr<FlutterMetalExternalTexture> {
2292
+ std::unique_ptr<FlutterMetalExternalTexture> texture =
2293
+ std::make_unique<FlutterMetalExternalTexture>();
2294
+ texture->struct_size = sizeof (FlutterMetalExternalTexture);
2295
+ if (!ptr (user_data, texture_identifier, width, height, texture.get ())) {
2296
+ return nullptr ;
2297
+ }
2298
+ return texture;
2299
+ };
2300
+ external_texture_resolver = std::make_unique<ExternalTextureResolver>(
2301
+ external_texture_metal_callback);
2302
+ }
2303
+ }
2304
+ #endif
2305
+
2306
+ auto run_configuration =
2307
+ flutter::RunConfiguration::InferFromSettings (settings);
2308
+
2309
+ if (SAFE_ACCESS (args, custom_dart_entrypoint, nullptr ) != nullptr ) {
2310
+ auto dart_entrypoint = std::string{args->custom_dart_entrypoint };
2311
+ if (!dart_entrypoint.empty ()) {
2312
+ run_configuration.SetEntrypoint (std::move (dart_entrypoint));
2313
+ }
2314
+ }
2315
+
2316
+ if (SAFE_ACCESS (args, dart_entrypoint_argc, 0 ) > 0 ) {
2317
+ if (SAFE_ACCESS (args, dart_entrypoint_argv, nullptr ) == nullptr ) {
2318
+ return LOG_EMBEDDER_ERROR (kInvalidArguments ,
2319
+ " Could not determine Dart entrypoint arguments "
2320
+ " as dart_entrypoint_argc "
2321
+ " was set, but dart_entrypoint_argv was null." );
2322
+ }
2323
+ std::vector<std::string> arguments (args->dart_entrypoint_argc );
2324
+ for (int i = 0 ; i < args->dart_entrypoint_argc ; ++i) {
2325
+ arguments[i] = std::string{args->dart_entrypoint_argv [i]};
2326
+ }
2327
+ run_configuration.SetEntrypointArgs (std::move (arguments));
2328
+ }
2329
+
2330
+ if (!run_configuration.IsValid ()) {
2331
+ return LOG_EMBEDDER_ERROR (
2332
+ kInvalidArguments ,
2333
+ " Could not infer the Flutter project to run from given arguments." );
2334
+ }
2335
+
2336
+ // Spawn the engine by using spawner
2337
+ auto embedder_engine_spawner =
2338
+ reinterpret_cast <flutter::EmbedderEngine*>(engine_spawner);
2339
+ auto embedder_engine = embedder_engine_spawner->SpawnEmbedderEngine (
2340
+ std::move (settings), //
2341
+ std::move (run_configuration), //
2342
+ on_create_platform_view, //
2343
+ on_create_rasterizer, //
2344
+ std::move (external_texture_resolver));
2345
+
2346
+ if (!embedder_engine->NotifyCreated ()) {
2347
+ return LOG_EMBEDDER_ERROR (kInternalInconsistency ,
2348
+ " Could not create platform view components." );
2349
+ }
2350
+
2351
+ // Release the ownership of the embedder engine to the caller.
2352
+ *engine_out = reinterpret_cast <FLUTTER_API_SYMBOL (FlutterEngine)>(
2353
+ embedder_engine.release ());
2354
+ return kSuccess ;
2355
+ }
2356
+
1982
2357
FlutterEngineResult FlutterEngineRunInitialized (
1983
2358
FLUTTER_API_SYMBOL (FlutterEngine) engine) {
1984
2359
if (!engine) {
@@ -3074,6 +3449,7 @@ FlutterEngineResult FlutterEngineGetProcAddresses(
3074
3449
SET_PROC (CreateAOTData, FlutterEngineCreateAOTData);
3075
3450
SET_PROC (CollectAOTData, FlutterEngineCollectAOTData);
3076
3451
SET_PROC (Run, FlutterEngineRun);
3452
+ SET_PROC (Spawn, FlutterEngineSpawn);
3077
3453
SET_PROC (Shutdown, FlutterEngineShutdown);
3078
3454
SET_PROC (Initialize, FlutterEngineInitialize);
3079
3455
SET_PROC (Deinitialize, FlutterEngineDeinitialize);
0 commit comments