Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDel
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngineGroup.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterHeadlessDartRunner.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h
Expand All @@ -963,6 +964,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartPro
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProjectTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngineGroup.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngineGroupTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEnginePlatformViewTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngineTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h
Expand Down
15 changes: 15 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,21 @@ Shell::~Shell() {
platform_latch.Wait();
}

std::unique_ptr<Shell> Shell::Spawn(
Settings settings,
const CreateCallback<PlatformView>& on_create_platform_view,
const CreateCallback<Rasterizer>& on_create_rasterizer) {
RunConfiguration configuration =
RunConfiguration::InferFromSettings(settings);
TaskRunners task_runners = task_runners_;
FML_DCHECK(task_runners.IsValid());
std::unique_ptr<Shell> result(Shell::Create(std::move(task_runners), settings,
on_create_platform_view,
on_create_rasterizer));
result->RunEngine(std::move(configuration));
return result;
}

void Shell::NotifyLowMemoryWarning() const {
auto trace_id = fml::tracing::TraceNonce();
TRACE_EVENT_ASYNC_BEGIN0("flutter", "Shell::NotifyLowMemoryWarning",
Expand Down
13 changes: 13 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,19 @@ class Shell final : public PlatformView::Delegate,
///
~Shell();

//----------------------------------------------------------------------------
/// @brief Creates one Shell from another Shell where the created Shell
/// takes the opportunity to share any internal components it can.
/// This results is a Shell that has a smaller startup time cost
/// and a smaller memory footprint than an Shell created with a
/// Create function.
///
/// @see http://flutter.dev/go/multiple-engines
std::unique_ptr<Shell> Spawn(
Settings settings,
const CreateCallback<PlatformView>& on_create_platform_view,
const CreateCallback<Rasterizer>& on_create_rasterizer);

//----------------------------------------------------------------------------
/// @brief Starts an isolate for the given RunConfiguration.
///
Expand Down
119 changes: 119 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "flutter/shell/common/vsync_waiter_fallback.h"
#include "flutter/shell/version/version.h"
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "third_party/rapidjson/include/rapidjson/writer.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/tonic/converter/dart_converter.h"
Expand All @@ -42,6 +43,77 @@

namespace flutter {
namespace testing {
namespace {
class MockPlatformViewDelegate : public PlatformView::Delegate {
MOCK_METHOD1(OnPlatformViewCreated, void(std::unique_ptr<Surface> surface));

MOCK_METHOD0(OnPlatformViewDestroyed, void());

MOCK_METHOD1(OnPlatformViewSetNextFrameCallback,
void(const fml::closure& closure));

MOCK_METHOD1(OnPlatformViewSetViewportMetrics,
void(const ViewportMetrics& metrics));

MOCK_METHOD1(OnPlatformViewDispatchPlatformMessage,
void(fml::RefPtr<PlatformMessage> message));

MOCK_METHOD1(OnPlatformViewDispatchPointerDataPacket,
void(std::unique_ptr<PointerDataPacket> packet));

MOCK_METHOD3(OnPlatformViewDispatchSemanticsAction,
void(int32_t id,
SemanticsAction action,
std::vector<uint8_t> args));

MOCK_METHOD1(OnPlatformViewSetSemanticsEnabled, void(bool enabled));

MOCK_METHOD1(OnPlatformViewSetAccessibilityFeatures, void(int32_t flags));

MOCK_METHOD1(OnPlatformViewRegisterTexture,
void(std::shared_ptr<Texture> texture));

MOCK_METHOD1(OnPlatformViewUnregisterTexture, void(int64_t texture_id));

MOCK_METHOD1(OnPlatformViewMarkTextureFrameAvailable,
void(int64_t texture_id));

MOCK_METHOD3(LoadDartDeferredLibrary,
void(intptr_t loading_unit_id,
std::unique_ptr<const fml::Mapping> snapshot_data,
std::unique_ptr<const fml::Mapping> snapshot_instructions));

MOCK_METHOD3(LoadDartDeferredLibraryError,
void(intptr_t loading_unit_id,
const std::string error_message,
bool transient));

MOCK_METHOD1(UpdateAssetManager,
void(std::shared_ptr<AssetManager> asset_manager));
};

class MockSurface : public Surface {
MOCK_METHOD0(IsValid, bool());

MOCK_METHOD1(AcquireFrame,
std::unique_ptr<SurfaceFrame>(const SkISize& size));

MOCK_CONST_METHOD0(GetRootTransformation, SkMatrix());

MOCK_METHOD0(GetContext, GrDirectContext*());

MOCK_METHOD0(MakeRenderContextCurrent, std::unique_ptr<GLContextResult>());

MOCK_METHOD0(ClearRenderContext, bool());
};

class MockPlatformView : public PlatformView {
public:
MockPlatformView(MockPlatformViewDelegate& delegate, TaskRunners task_runners)
: PlatformView(delegate, task_runners) {}
MOCK_METHOD0(CreateRenderingSurface, std::unique_ptr<Surface>());
};
} // namespace

static bool ValidateShell(Shell* shell) {
if (!shell) {
Expand Down Expand Up @@ -2318,5 +2390,52 @@ TEST_F(ShellTest, AssetManagerMulti) {
}
}

TEST_F(ShellTest, Spawn) {
auto settings = CreateSettingsForFixture();
auto shell = CreateShell(settings);
ASSERT_TRUE(ValidateShell(shell.get()));

auto configuration = RunConfiguration::InferFromSettings(settings);
ASSERT_TRUE(configuration.IsValid());
configuration.SetEntrypoint("fixturesAreFunctionalMain");

fml::AutoResetWaitableEvent main_latch;
AddNativeCallback(
"SayHiFromFixturesAreFunctionalMain",
CREATE_NATIVE_ENTRY([&main_latch](auto args) { main_latch.Signal(); }));

RunEngine(shell.get(), std::move(configuration));
main_latch.Wait();
ASSERT_TRUE(DartVMRef::IsInstanceRunning());

{
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetPlatformTaskRunner(),
[this, &spawner = shell, &latch, settings]() {
MockPlatformViewDelegate platform_view_delegate;
auto spawn = spawner->Spawn(
settings,
[&platform_view_delegate](Shell& shell) {
auto result = std::make_unique<MockPlatformView>(
platform_view_delegate, shell.GetTaskRunners());
ON_CALL(*result, CreateRenderingSurface())
.WillByDefault(::testing::Invoke(
[] { return std::make_unique<MockSurface>(); }));
return result;
},
[](Shell& shell) { return std::make_unique<Rasterizer>(shell); });
ASSERT_NE(nullptr, spawn.get());
ASSERT_TRUE(ValidateShell(spawn.get()));
DestroyShell(std::move(spawn));
latch.Signal();
});
latch.Wait();
}

DestroyShell(std::move(shell));
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
}

} // namespace testing
} // namespace flutter
3 changes: 3 additions & 0 deletions shell/platform/darwin/ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ _flutter_framework_headers = [
"framework/Headers/FlutterCallbackCache.h",
"framework/Headers/FlutterDartProject.h",
"framework/Headers/FlutterEngine.h",
"framework/Headers/FlutterEngineGroup.h",
"framework/Headers/FlutterHeadlessDartRunner.h",
"framework/Headers/FlutterPlatformViews.h",
"framework/Headers/FlutterPlugin.h",
Expand All @@ -52,6 +53,7 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterDartProject.mm",
"framework/Source/FlutterDartProject_Internal.h",
"framework/Source/FlutterEngine.mm",
"framework/Source/FlutterEngineGroup.mm",
"framework/Source/FlutterEngine_Internal.h",
"framework/Source/FlutterHeadlessDartRunner.mm",
"framework/Source/FlutterObservatoryPublisher.h",
Expand Down Expand Up @@ -215,6 +217,7 @@ shared_library("ios_test_flutter") {
"framework/Source/FlutterAppDelegateTest.mm",
"framework/Source/FlutterBinaryMessengerRelayTest.mm",
"framework/Source/FlutterDartProjectTest.mm",
"framework/Source/FlutterEngineGroupTest.mm",
"framework/Source/FlutterEngineTest.mm",
"framework/Source/FlutterPluginAppLifeCycleDelegateTest.m",
"framework/Source/FlutterTextInputPluginTest.m",
Expand Down
1 change: 1 addition & 0 deletions shell/platform/darwin/ios/framework/Headers/Flutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#import "FlutterCodecs.h"
#import "FlutterDartProject.h"
#import "FlutterEngine.h"
#import "FlutterEngineGroup.h"
#import "FlutterHeadlessDartRunner.h"
#import "FlutterMacros.h"
#import "FlutterPlatformViews.h"
Expand Down
45 changes: 45 additions & 0 deletions shell/platform/darwin/ios/framework/Headers/FlutterEngineGroup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <Foundation/Foundation.h>

#import "FlutterEngine.h"

NS_ASSUME_NONNULL_BEGIN

/**
* Represents a collection of FlutterEngines who share resources which allows
* them to be created with less time const and occupy less memory than just
* creating multiple FlutterEngines.
*
* Deleting a FlutterEngineGroup doesn't invalidate existing FlutterEngines, but
* it eliminates the possibility to create more FlutterEngines in that group.
*
* @warning This class is a work-in-progress and may change.
* @see https://github.com/flutter/flutter/issues/72009
*/
@interface FlutterEngineGroup : NSObject
- (instancetype)init NS_UNAVAILABLE;

/**
* Initialize a new FlutterEngineGroup.
*
* @param name The name that will present in the threads shared across the
* engines in this group.
* @param project The `FlutterDartProject` that all FlutterEngines in this group
* will be executing.
*/
- (instancetype)initWithName:(NSString*)name
project:(nullable FlutterDartProject*)project NS_DESIGNATED_INITIALIZER;

/**
* Creates a running `FlutterEngine` that shares components with this group.
*
* @see FlutterEngineGroup
*/
- (FlutterEngine*)makeEngineWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI;
@end

NS_ASSUME_NONNULL_END
Loading