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 6 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 =
Comment thread
gaaclarke marked this conversation as resolved.
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());
Comment thread
gaaclarke marked this conversation as resolved.
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
42 changes: 42 additions & 0 deletions shell/platform/darwin/ios/framework/Headers/FlutterEngineGroup.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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.
Comment thread
gaaclarke marked this conversation as resolved.
*
* Deleting a FlutterEngineGroup doesn't invalidate existing FlutterEngines, but
* it eliminates the possibility to create more FlutterEngines in that group.
*
* @see http://flutter.dev/go/multiple-engines
Comment thread
gaaclarke marked this conversation as resolved.
Outdated
*/
@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 exists in this group.
Comment thread
gaaclarke marked this conversation as resolved.
Outdated
*/
- (FlutterEngine*)makeEngineWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI;
@end

NS_ASSUME_NONNULL_END
Loading