Skip to content

Commit f18858b

Browse files
committed
Introduce spawn API at embedder
* This uses Shell's Spawn. Signed-off-by: MuHong Byun <[email protected]>
1 parent 638c395 commit f18858b

9 files changed

+378
-3
lines changed

shell/platform/embedder/embedder.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,24 @@ FlutterEngineResult FlutterEngineRun(size_t version,
839839
return FlutterEngineRunInitialized(*engine_out);
840840
}
841841

842+
FlutterEngineResult FlutterEngineSpawn(size_t version,
843+
const FlutterRendererConfig* config,
844+
const FlutterProjectArgs* args,
845+
void* user_data,
846+
FLUTTER_API_SYMBOL(FlutterEngine) *
847+
engine_out,
848+
FLUTTER_API_SYMBOL(FlutterEngine)
849+
engine_main) {
850+
auto result =
851+
FlutterEngineInitialize(version, config, args, user_data, engine_out);
852+
853+
if (result != kSuccess) {
854+
return result;
855+
}
856+
857+
return FlutterEngineSpawnInitialized(*engine_out, engine_main);
858+
}
859+
842860
FlutterEngineResult FlutterEngineInitialize(size_t version,
843861
const FlutterRendererConfig* config,
844862
const FlutterProjectArgs* args,
@@ -1309,6 +1327,44 @@ FlutterEngineResult FlutterEngineRunInitialized(
13091327
return kSuccess;
13101328
}
13111329

1330+
FlutterEngineResult FlutterEngineSpawnInitialized(
1331+
FLUTTER_API_SYMBOL(FlutterEngine) engine,
1332+
FLUTTER_API_SYMBOL(FlutterEngine) engine_main) {
1333+
if (!engine || !engine_main) {
1334+
return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
1335+
}
1336+
1337+
auto embedder_engine = reinterpret_cast<flutter::EmbedderEngine*>(engine);
1338+
auto embedder_engine_main =
1339+
reinterpret_cast<flutter::EmbedderEngine*>(engine_main);
1340+
1341+
// The engine must not already be running. Initialize may only be called
1342+
// once on an engine instance.
1343+
if (embedder_engine->IsValid()) {
1344+
return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
1345+
}
1346+
1347+
// The main engine must be running.
1348+
if (!embedder_engine_main->IsValid()) {
1349+
return LOG_EMBEDDER_ERROR(kInvalidArguments, "Engine handle was invalid.");
1350+
}
1351+
1352+
// Spawn the shell.
1353+
if (!embedder_engine->SpawnShell(embedder_engine_main)) {
1354+
return LOG_EMBEDDER_ERROR(kInvalidArguments,
1355+
"Could not launch the engine using supplied "
1356+
"initialization arguments.");
1357+
}
1358+
1359+
// Step 2: Tell the platform view to initialize itself.
1360+
if (!embedder_engine->NotifyCreated()) {
1361+
return LOG_EMBEDDER_ERROR(kInternalInconsistency,
1362+
"Could not create platform view components.");
1363+
}
1364+
1365+
return kSuccess;
1366+
}
1367+
13121368
FLUTTER_EXPORT
13131369
FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine)
13141370
engine) {
@@ -2220,6 +2276,7 @@ FlutterEngineResult FlutterEngineGetProcAddresses(
22202276
SET_PROC(CreateAOTData, FlutterEngineCreateAOTData);
22212277
SET_PROC(CollectAOTData, FlutterEngineCollectAOTData);
22222278
SET_PROC(Run, FlutterEngineRun);
2279+
SET_PROC(Spawn, FlutterEngineSpawn);
22232280
SET_PROC(Shutdown, FlutterEngineShutdown);
22242281
SET_PROC(Initialize, FlutterEngineInitialize);
22252282
SET_PROC(Deinitialize, FlutterEngineDeinitialize);

shell/platform/embedder/embedder.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,42 @@ FlutterEngineResult FlutterEngineRun(size_t version,
15981598
FLUTTER_API_SYMBOL(FlutterEngine) *
15991599
engine_out);
16001600

1601+
//------------------------------------------------------------------------------
1602+
/// @brief Initialize and run a Flutter engine instance and return a handle
1603+
/// to it. This is a convenience method for the pair of calls to
1604+
/// `FlutterEngineInitialize` and `FlutterEngineRunInitialized`.
1605+
///
1606+
/// @note This method of running a Flutter engine works well except in
1607+
/// cases where the embedder specifies custom task runners via
1608+
/// `FlutterProjectArgs::custom_task_runners`. In such cases, the
1609+
/// engine may need the embedder to post tasks back to it before
1610+
/// `FlutterEngineRun` has returned. Embedders can only post tasks
1611+
/// to the engine if they have a handle to the engine. In such
1612+
/// cases, embedders are advised to get the engine handle via the
1613+
/// `FlutterInitializeCall`. Then they can call
1614+
/// `FlutterEngineRunInitialized` knowing that they will be able to
1615+
/// service custom tasks on other threads with the engine handle.
1616+
///
1617+
/// @param[in] version The Flutter embedder API version. Must be
1618+
/// FLUTTER_ENGINE_VERSION.
1619+
/// @param[in] config The renderer configuration.
1620+
/// @param[in] args The Flutter project arguments.
1621+
/// @param user_data A user data baton passed back to embedders in
1622+
/// callbacks.
1623+
/// @param[out] engine_out The engine handle on successful engine creation.
1624+
///
1625+
/// @return The result of the call to run the Flutter engine.
1626+
///
1627+
FLUTTER_EXPORT
1628+
FlutterEngineResult FlutterEngineSpawn(size_t version,
1629+
const FlutterRendererConfig* config,
1630+
const FlutterProjectArgs* args,
1631+
void* user_data,
1632+
FLUTTER_API_SYMBOL(FlutterEngine) *
1633+
engine_out,
1634+
FLUTTER_API_SYMBOL(FlutterEngine)
1635+
engine_main);
1636+
16011637
//------------------------------------------------------------------------------
16021638
/// @brief Shuts down a Flutter engine instance. The engine handle is no
16031639
/// longer valid for any calls in the embedder API after this point.
@@ -1673,6 +1709,24 @@ FLUTTER_EXPORT
16731709
FlutterEngineResult FlutterEngineRunInitialized(
16741710
FLUTTER_API_SYMBOL(FlutterEngine) engine);
16751711

1712+
//------------------------------------------------------------------------------
1713+
/// @brief Runs an initialized engine instance. An engine can be
1714+
/// initialized via `FlutterEngineInitialize`. An initialized
1715+
/// instance can only be run once. During and after this call,
1716+
/// custom task runners supplied by the embedder are expected to
1717+
/// start servicing tasks.
1718+
///
1719+
/// @param[in] engine An initialized engine instance that has not previously
1720+
/// been run.
1721+
///
1722+
/// @return The result of the call to run the initialized Flutter
1723+
/// engine instance.
1724+
///
1725+
FLUTTER_EXPORT
1726+
FlutterEngineResult FlutterEngineSpawnInitialized(
1727+
FLUTTER_API_SYMBOL(FlutterEngine) engine,
1728+
FLUTTER_API_SYMBOL(FlutterEngine) engine_main);
1729+
16761730
FLUTTER_EXPORT
16771731
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
16781732
FLUTTER_API_SYMBOL(FlutterEngine) engine,
@@ -2204,6 +2258,13 @@ typedef FlutterEngineResult (*FlutterEngineRunFnPtr)(
22042258
const FlutterProjectArgs* args,
22052259
void* user_data,
22062260
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
2261+
typedef FlutterEngineResult (*FlutterEngineSpawnFnPtr)(
2262+
size_t version,
2263+
const FlutterRendererConfig* config,
2264+
const FlutterProjectArgs* args,
2265+
void* user_data,
2266+
FLUTTER_API_SYMBOL(FlutterEngine) * engine_out,
2267+
FLUTTER_API_SYMBOL(FlutterEngine) engine_main);
22072268
typedef FlutterEngineResult (*FlutterEngineShutdownFnPtr)(
22082269
FLUTTER_API_SYMBOL(FlutterEngine) engine);
22092270
typedef FlutterEngineResult (*FlutterEngineInitializeFnPtr)(
@@ -2315,6 +2376,7 @@ typedef struct {
23152376
FlutterEngineCreateAOTDataFnPtr CreateAOTData;
23162377
FlutterEngineCollectAOTDataFnPtr CollectAOTData;
23172378
FlutterEngineRunFnPtr Run;
2379+
FlutterEngineSpawnFnPtr Spawn;
23182380
FlutterEngineShutdownFnPtr Shutdown;
23192381
FlutterEngineInitializeFnPtr Initialize;
23202382
FlutterEngineDeinitializeFnPtr Deinitialize;

shell/platform/embedder/embedder_engine.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,39 @@ bool EmbedderEngine::LaunchShell() {
6060
return IsValid();
6161
}
6262

63+
bool EmbedderEngine::SpawnShell(EmbedderEngine* main) {
64+
if (!shell_args_) {
65+
FML_DLOG(ERROR) << "Invalid shell arguments.";
66+
return false;
67+
}
68+
69+
if (shell_) {
70+
FML_DLOG(ERROR) << "Shell already initialized";
71+
}
72+
73+
if (!run_configuration_.IsValid()) {
74+
FML_DLOG(ERROR) << "Invalid Configration";
75+
}
76+
77+
shell_ = main->SpawnShell(std::move(run_configuration_),
78+
shell_args_->on_create_platform_view,
79+
shell_args_->on_create_rasterizer);
80+
81+
// // Reset the args no matter what. They will never be used to initialize a
82+
// // shell again.
83+
shell_args_.reset();
84+
85+
return IsValid();
86+
}
87+
88+
std::unique_ptr<Shell> EmbedderEngine::SpawnShell(
89+
RunConfiguration run_configuration,
90+
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
91+
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
92+
return shell_->Spawn(std::move(run_configuration), on_create_platform_view,
93+
on_create_rasterizer);
94+
}
95+
6396
bool EmbedderEngine::CollectShell() {
6497
shell_.reset();
6598
return IsValid();

shell/platform/embedder/embedder_engine.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ class EmbedderEngine {
3535

3636
bool LaunchShell();
3737

38+
bool SpawnShell(EmbedderEngine* main);
39+
40+
std::unique_ptr<Shell> SpawnShell(
41+
RunConfiguration run_configuration,
42+
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
43+
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer);
44+
3845
bool CollectShell();
3946

4047
const TaskRunners& GetTaskRunners() const;

shell/platform/embedder/tests/embedder_unittests.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,5 +1434,39 @@ TEST_F(EmbedderTest, KeyDataResponseIsCorrectlyInvoked) {
14341434
EXPECT_TRUE(user_data3.returned);
14351435
}
14361436

1437+
//------------------------------------------------------------------------------
1438+
///
1439+
TEST_F(EmbedderTest, CabRunFlutterEngineSpawnInitialized) {
1440+
EmbedderConfigBuilder builder(
1441+
GetEmbedderContext(EmbedderTestContextType::kSoftwareContext));
1442+
builder.SetSoftwareRendererConfig();
1443+
auto engine = builder.InitializeEngine();
1444+
auto main_engine = builder.InitializeEngine();
1445+
1446+
ASSERT_TRUE(engine.is_valid());
1447+
ASSERT_TRUE(main_engine.is_valid());
1448+
1449+
// Spawn with invalid parameter
1450+
ASSERT_EQ(FlutterEngineSpawnInitialized(nullptr, nullptr), kInvalidArguments);
1451+
ASSERT_EQ(FlutterEngineSpawnInitialized(engine.get(), nullptr),
1452+
kInvalidArguments);
1453+
ASSERT_EQ(FlutterEngineSpawnInitialized(nullptr, main_engine.get()),
1454+
kInvalidArguments);
1455+
1456+
// Test with the main engine not running
1457+
ASSERT_EQ(FlutterEngineSpawnInitialized(engine.get(), main_engine.get()),
1458+
kInvalidArguments);
1459+
1460+
// Execute main engine
1461+
ASSERT_EQ(FlutterEngineRunInitialized(main_engine.get()), kSuccess);
1462+
1463+
// Test spawn API
1464+
ASSERT_EQ(FlutterEngineSpawnInitialized(engine.get(), main_engine.get()),
1465+
kSuccess);
1466+
1467+
engine.reset();
1468+
main_engine.reset();
1469+
}
1470+
14371471
} // namespace testing
14381472
} // namespace flutter

shell/platform/tizen/flutter_tizen.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ FlutterDesktopEngineRef FlutterDesktopRunEngine(
3838
return HandleForEngine(engine.release());
3939
}
4040

41+
FlutterDesktopEngineRef FlutterDesktopSpawnEngine(
42+
FlutterDesktopEngineRef engine_ref,
43+
const FlutterDesktopEngineProperties& engine_properties,
44+
bool headed) {
45+
auto engine = EngineFromHandle(engine_ref);
46+
auto spawned_engine = engine->SpawnEngine(headed, engine_properties);
47+
return HandleForEngine(spawned_engine);
48+
}
49+
4150
void FlutterDesktopShutdownEngine(FlutterDesktopEngineRef engine_ref) {
4251
auto engine = EngineFromHandle(engine_ref);
4352
engine->StopEngine();

0 commit comments

Comments
 (0)