Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Switch macOS embedding to proc table embedder API #21811

Merged
merged 10 commits into from
Nov 3, 2020
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
2 changes: 1 addition & 1 deletion ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1048,7 +1048,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterAppDe
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineUnittests.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm
Expand Down
8 changes: 6 additions & 2 deletions shell/platform/darwin/macos/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ source_set("flutter_framework_source") {

public_configs = [ "//flutter:config" ]

defines = [ "FLUTTER_FRAMEWORK" ]
defines = [
"FLUTTER_FRAMEWORK",
"FLUTTER_ENGINE_NO_PROTOTYPES",
Copy link
Member

@cbracken cbracken Oct 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this breaks FlutterEngine.mm due to a few symbols defined in the #infndef FLUTTER_ENGINE_NO_PROTOTYPES block added in #21813:

  • FlutterEngineCollectAOTData
  • FlutterEngineRunsAOTCompiledDartCode
  • FlutterEngineCreateAOTData

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apparently didn't rebuild locally after rebasing on master 😳 The code that's not compiling is new, so hadn't been updated to use the proc table.

]

cflags_objcc = [ "-fobjc-arc" ]

Expand Down Expand Up @@ -113,7 +116,7 @@ executable("flutter_desktop_darwin_unittests") {
testonly = true

sources = [
"framework/Source/FlutterEngineUnittests.mm",
"framework/Source/FlutterEngineTest.mm",
"framework/Source/FlutterViewControllerTest.mm",
]

Expand All @@ -126,6 +129,7 @@ executable("flutter_desktop_darwin_unittests") {
":flutter_framework_source",
"//flutter/shell/platform/darwin/common:framework_shared",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
"//flutter/testing:dart",
"//flutter/testing:skia",
Expand Down
80 changes: 38 additions & 42 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ static FlutterLocale FlutterLocaleFromNSLocale(NSLocale* locale) {
return flutterLocale;
}

namespace {

struct AotDataDeleter {
void operator()(FlutterEngineAOTData aot_data) { FlutterEngineCollectAOTData(aot_data); }
};

using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AotDataDeleter>;

}

/**
* Private interface declaration for FlutterEngine.
*/
Expand Down Expand Up @@ -85,10 +75,10 @@ - (BOOL)populateTextureWithIdentifier:(int64_t)textureID
- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime;

/**
* Loads the AOT snapshots and instructions from the elf bundle (app_elf_snapshot.so) if it is
* present in the assets directory.
* Loads the AOT snapshots and instructions from the elf bundle (app_elf_snapshot.so) into _aotData,
* if it is present in the assets directory.
*/
- (UniqueAotDataPtr)loadAOTData:(NSString*)assetsDir;
- (void)loadAOTData:(NSString*)assetsDir;

@end

Expand All @@ -105,6 +95,7 @@ - (instancetype)initWithPlugin:(nonnull NSString*)pluginKey
@implementation FlutterEngineRegistrar {
NSString* _pluginKey;
FlutterEngine* _flutterEngine;
FlutterEngineProcTable _embedderAPI;
}

- (instancetype)initWithPlugin:(NSString*)pluginKey flutterEngine:(FlutterEngine*)flutterEngine {
Expand Down Expand Up @@ -201,7 +192,7 @@ @implementation FlutterEngine {
NSMutableDictionary<NSNumber*, FlutterExternalTextureGL*>* _textures;

// Pointer to the Dart AOT snapshot and instruction data.
UniqueAotDataPtr _aotData;
_FlutterEngineAOTData* _aotData;
}

- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)project {
Expand All @@ -218,6 +209,8 @@ - (instancetype)initWithName:(NSString*)labelPrefix
_messageHandlers = [[NSMutableDictionary alloc] init];
_textures = [[NSMutableDictionary alloc] init];
_allowHeadlessExecution = allowHeadlessExecution;
_embedderAPI.struct_size = sizeof(FlutterEngineProcTable);
FlutterEngineGetProcAddresses(&_embedderAPI);

NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
Expand All @@ -230,6 +223,9 @@ - (instancetype)initWithName:(NSString*)labelPrefix

- (void)dealloc {
[self shutDownEngine];
if (_aotData) {
_embedderAPI.CollectAOTData(_aotData);
}
}

- (BOOL)runWithEntrypoint:(NSString*)entrypoint {
Expand Down Expand Up @@ -301,19 +297,19 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
};
flutterArguments.custom_task_runners = &custom_task_runners;

_aotData = [self loadAOTData:_project.assetsPath];
[self loadAOTData:_project.assetsPath];
if (_aotData) {
flutterArguments.aot_data = _aotData.get();
flutterArguments.aot_data = _aotData;
}

FlutterEngineResult result = FlutterEngineInitialize(
FlutterEngineResult result = _embedderAPI.Initialize(
FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine);
if (result != kSuccess) {
NSLog(@"Failed to initialize Flutter engine: error %d", result);
return NO;
}

result = FlutterEngineRunInitialized(_engine);
result = _embedderAPI.RunInitialized(_engine);
if (result != kSuccess) {
NSLog(@"Failed to run an initialized engine: error %d", result);
return NO;
Expand All @@ -326,9 +322,9 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
return YES;
}

- (UniqueAotDataPtr)loadAOTData:(NSString*)assetsDir {
if (!FlutterEngineRunsAOTCompiledDartCode()) {
return nullptr;
- (void)loadAOTData:(NSString*)assetsDir {
if (!_embedderAPI.RunsAOTCompiledDartCode()) {
return;
}

BOOL isDirOut = false; // required for NSFileManager fileExistsAtPath.
Expand All @@ -339,21 +335,17 @@ - (UniqueAotDataPtr)loadAOTData:(NSString*)assetsDir {
NSString* elfPath = [NSString pathWithComponents:@[ assetsDir, @"app_elf_snapshot.so" ]];

if (![fileManager fileExistsAtPath:elfPath isDirectory:&isDirOut]) {
return nullptr;
return;
}

FlutterEngineAOTDataSource source = {};
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
source.elf_path = [elfPath cStringUsingEncoding:NSUTF8StringEncoding];

FlutterEngineAOTData data = nullptr;
auto result = FlutterEngineCreateAOTData(&source, &data);
auto result = _embedderAPI.CreateAOTData(&source, &_aotData);
if (result != kSuccess) {
NSLog(@"Failed to load AOT data from: %@", elfPath);
return nullptr;
}

return UniqueAotDataPtr(data);
}

- (void)setViewController:(FlutterViewController*)controller {
Expand Down Expand Up @@ -409,13 +401,17 @@ - (void)updateDisplayConfig {
display.refresh_rate = round(refreshRate);

std::vector<FlutterEngineDisplay> displays = {display};
FlutterEngineNotifyDisplayUpdate(_engine, kFlutterEngineDisplaysUpdateTypeStartup,
_embedderAPI.NotifyDisplayUpdate(_engine, kFlutterEngineDisplaysUpdateTypeStartup,
displays.data(), displays.size());
}

CVDisplayLinkRelease(displayLinkRef);
}

- (FlutterEngineProcTable&)embedderAPI {
return _embedderAPI;
}

- (void)updateWindowMetrics {
if (!_engine) {
return;
Expand All @@ -433,11 +429,11 @@ - (void)updateWindowMetrics {
.left = static_cast<size_t>(scaledBounds.origin.x),
.top = static_cast<size_t>(scaledBounds.origin.y),
};
FlutterEngineSendWindowMetricsEvent(_engine, &windowMetricsEvent);
_embedderAPI.SendWindowMetricsEvent(_engine, &windowMetricsEvent);
}

- (void)sendPointerEvent:(const FlutterPointerEvent&)event {
FlutterEngineSendPointerEvent(_engine, &event, 1);
_embedderAPI.SendPointerEvent(_engine, &event, 1);
}

#pragma mark - Private methods
Expand All @@ -462,7 +458,7 @@ - (void)sendUserLocales {
std::transform(
flutterLocales.begin(), flutterLocales.end(), std::back_inserter(flutterLocaleList),
[](const auto& arg) -> const auto* { return &arg; });
FlutterEngineUpdateLocales(_engine, flutterLocaleList.data(), flutterLocaleList.size());
_embedderAPI.UpdateLocales(_engine, flutterLocaleList.data(), flutterLocaleList.size());
}

- (bool)engineCallbackOnMakeCurrent {
Expand Down Expand Up @@ -500,7 +496,7 @@ - (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message {

FlutterBinaryReply binaryResponseHandler = ^(NSData* response) {
if (responseHandle) {
FlutterEngineSendPlatformMessageResponse(self->_engine, responseHandle,
_embedderAPI.SendPlatformMessageResponse(self->_engine, responseHandle,
static_cast<const uint8_t*>(response.bytes),
response.length);
responseHandle = NULL;
Expand All @@ -527,15 +523,15 @@ - (void)shutDownEngine {
return;
}

FlutterEngineResult result = FlutterEngineDeinitialize(_engine);
FlutterEngineResult result = _embedderAPI.Deinitialize(_engine);
if (result != kSuccess) {
NSLog(@"Could not de-initialize the Flutter engine: error %d", result);
}

// Balancing release for the retain in the task runner dispatch table.
CFRelease((CFTypeRef)self);

result = FlutterEngineShutdown(_engine);
result = _embedderAPI.Shutdown(_engine);
if (result != kSuccess) {
NSLog(@"Failed to shut down Flutter engine: error %d", result);
}
Expand Down Expand Up @@ -568,7 +564,7 @@ - (void)sendOnChannel:(NSString*)channel
delete captures;
};

FlutterEngineResult create_result = FlutterPlatformMessageCreateResponseHandle(
FlutterEngineResult create_result = _embedderAPI.PlatformMessageCreateResponseHandle(
_engine, message_reply, captures.get(), &response_handle);
if (create_result != kSuccess) {
NSLog(@"Failed to create a FlutterPlatformMessageResponseHandle (%d)", create_result);
Expand All @@ -585,15 +581,15 @@ - (void)sendOnChannel:(NSString*)channel
.response_handle = response_handle,
};

FlutterEngineResult message_result = FlutterEngineSendPlatformMessage(_engine, &platformMessage);
FlutterEngineResult message_result = _embedderAPI.SendPlatformMessage(_engine, &platformMessage);
if (message_result != kSuccess) {
NSLog(@"Failed to send message to Flutter engine on channel '%@' (%d).", channel,
message_result);
}

if (response_handle != nullptr) {
FlutterEngineResult release_result =
FlutterPlatformMessageReleaseResponseHandle(_engine, response_handle);
_embedderAPI.PlatformMessageReleaseResponseHandle(_engine, response_handle);
if (release_result != kSuccess) {
NSLog(@"Failed to release the response handle (%d).", release_result);
};
Expand Down Expand Up @@ -628,30 +624,30 @@ - (int64_t)registerTexture:(id<FlutterTexture>)texture {
FlutterExternalTextureGL* FlutterTexture =
[[FlutterExternalTextureGL alloc] initWithFlutterTexture:texture];
int64_t textureID = [FlutterTexture textureID];
FlutterEngineRegisterExternalTexture(_engine, textureID);
_embedderAPI.RegisterExternalTexture(_engine, textureID);
_textures[@(textureID)] = FlutterTexture;
return textureID;
}

- (void)textureFrameAvailable:(int64_t)textureID {
FlutterEngineMarkExternalTextureFrameAvailable(_engine, textureID);
_embedderAPI.MarkExternalTextureFrameAvailable(_engine, textureID);
}

- (void)unregisterTexture:(int64_t)textureID {
FlutterEngineUnregisterExternalTexture(_engine, textureID);
_embedderAPI.UnregisterExternalTexture(_engine, textureID);
[_textures removeObjectForKey:@(textureID)];
}

#pragma mark - Task runner integration

- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime {
const auto engine_time = FlutterEngineGetCurrentTime();
const auto engine_time = _embedderAPI.GetCurrentTime();

__weak FlutterEngine* weak_self = self;
auto worker = ^{
FlutterEngine* strong_self = weak_self;
if (strong_self && strong_self->_engine) {
auto result = FlutterEngineRunTask(strong_self->_engine, &task);
auto result = _embedderAPI.RunTask(strong_self->_engine, &task);
if (result != kSuccess) {
NSLog(@"Could not post a task to the Flutter engine.");
}
Expand Down
53 changes: 53 additions & 0 deletions shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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 "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/testing/testing.h"

namespace flutter::testing {

namespace {
// Returns an engine configured for the text fixture resource configuration.
FlutterEngine* CreateTestEngine() {
NSString* fixtures = @(testing::GetFixturesPath());
FlutterDartProject* project = [[FlutterDartProject alloc]
initWithAssetsPath:fixtures
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
return [[FlutterEngine alloc] initWithName:@"test" project:project allowHeadlessExecution:true];
}
} // namespace

TEST(FlutterEngine, CanLaunch) {
FlutterEngine* engine = CreateTestEngine();
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
EXPECT_TRUE(engine.running);
[engine shutDownEngine];
}

TEST(FlutterEngine, MessengerSend) {
FlutterEngine* engine = CreateTestEngine();
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);

NSData* test_message = [@"a message" dataUsingEncoding:NSUTF8StringEncoding];
bool called = false;

engine.embedderAPI.SendPlatformMessage = MOCK_ENGINE_PROC(
SendPlatformMessage, ([&called, test_message](auto engine, auto message) {
called = true;
EXPECT_STREQ(message->channel, "test");
EXPECT_EQ(memcmp(message->message, test_message.bytes, message->message_size), 0);
return kSuccess;
}));

[engine.binaryMessenger sendOnChannel:@"test" message:test_message];
EXPECT_TRUE(called);

[engine shutDownEngine];
}

} // flutter::testing

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#import <Cocoa/Cocoa.h>

#import "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/embedder.h"

@interface FlutterEngine ()

Expand All @@ -21,6 +21,11 @@
*/
@property(nonatomic, readonly, nullable) NSOpenGLContext* resourceContext;

/**
* Function pointers for interacting with the embedder.h API.
*/
@property(nonatomic) FlutterEngineProcTable& embedderAPI;

/**
* Informs the engine that the associated view controller's view size has changed.
*/
Expand Down
Loading