未验证 提交 e3c5f482 编写于 作者: C Chinmay Garde 提交者: GitHub

Switch the MacOS Desktop embedder to using a thread configuration where the...

Switch the MacOS Desktop embedder to using a thread configuration where the platform and render task runners are the same. (#13300)

Also creates a new test harness for the desktop embedder framework target and adds a test that launches a headless engine in this new thread configuration.

Fixes https://github.com/flutter/flutter/issues/17579
上级 e6486671
......@@ -58,8 +58,10 @@ group("flutter") {
# If on the host, compile all unittests targets.
if (current_toolchain == host_toolchain) {
if (is_mac) {
public_deps +=
[ "$flutter_root/shell/platform/darwin:flutter_channels_unittests" ]
public_deps += [
"$flutter_root/shell/platform/darwin:flutter_channels_unittests",
"$flutter_root/shell/platform/darwin/macos:flutter_desktop_darwin_unittests",
]
}
public_deps += [
......
......@@ -824,6 +824,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/FlutterEngine_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm
......@@ -835,6 +836,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/fixtures/flutter_desktop_test.dart
FILE: ../../../flutter/shell/platform/darwin/macos/framework/module.modulemap
FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist
FILE: ../../../flutter/shell/platform/embedder/assets/embedder.modulemap
......
......@@ -8,6 +8,7 @@ import("//build/config/mac/mac_sdk.gni")
import("$flutter_root/common/config.gni")
import("$flutter_root/shell/platform/darwin/common/framework_shared.gni")
import("$flutter_root/shell/platform/glfw/config.gni")
import("$flutter_root/testing/testing.gni")
group("macos") {
deps = [
......@@ -41,11 +42,9 @@ _flutter_framework_headers = [
_flutter_framework_headers_copy_dir =
"$_flutter_framework_dir/Versions/A/Headers"
shared_library("create_flutter_framework_dylib") {
source_set("flutter_framework_source") {
visibility = [ ":*" ]
output_name = "$_flutter_framework_name"
sources = [
"framework/Source/FlutterAppDelegate.mm",
"framework/Source/FlutterDartProject.mm",
......@@ -83,6 +82,43 @@ shared_library("create_flutter_framework_dylib") {
]
}
shared_library("flutter_framework_dylib") {
visibility = [ ":*" ]
output_name = "$_flutter_framework_name"
deps = [
":flutter_framework_source",
]
}
test_fixtures("flutter_desktop_darwin_fixtures") {
dart_main = "framework/Source/fixtures/flutter_desktop_test.dart"
fixtures = [ "//third_party/icu/common/icudtl.dat" ]
}
executable("flutter_desktop_darwin_unittests") {
testonly = true
sources = [
"framework/Source/FlutterEngineUnittests.mm",
]
cflags_objcc = [ "-fobjc-arc" ]
deps = [
":flutter_desktop_darwin_fixtures",
":flutter_framework_source",
"$flutter_root/shell/platform/darwin/common:framework_shared",
"$flutter_root/shell/platform/embedder:embedder_with_symbol_prefix",
"$flutter_root/testing",
"$flutter_root/testing:dart",
"$flutter_root/testing:skia",
"$flutter_root/testing:testing_lib",
]
}
action("copy_dylib_and_update_framework_install_name") {
visibility = [ ":*" ]
script = "$flutter_root/sky/tools/change_install_name.py"
......@@ -108,7 +144,7 @@ action("copy_dylib_and_update_framework_install_name") {
]
deps = [
":create_flutter_framework_dylib",
":flutter_framework_dylib",
]
}
......
......@@ -72,6 +72,13 @@ FLUTTER_EXPORT
*/
@property(nonatomic, nonnull, readonly) id<FlutterBinaryMessenger> binaryMessenger;
/**
* Shuts the Flutter engine if it is running. The FlutterEngine instance must always be shutdown
* before it may be collected. Not shutting down the FlutterEngine instance before releasing it will
* result in the leak of that engine instance.
*/
- (void)shutDownEngine;
@end
#endif // FLUTTER_FLUTTERENGINE_H_
......@@ -12,6 +12,8 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
@implementation FlutterDartProject {
NSBundle* _dartBundle;
NSString* _assetsPath;
NSString* _ICUDataPath;
}
- (instancetype)init {
......@@ -26,7 +28,19 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
return self;
}
- (instancetype)initWithAssetsPath:(NSString*)assets ICUDataPath:(NSString*)icuPath {
self = [super init];
NSAssert(self, @"Super init cannot be nil");
_assetsPath = assets;
_ICUDataPath = icuPath;
return self;
}
- (NSString*)assetsPath {
if (_assetsPath) {
return _assetsPath;
}
// If there's no App.framework, fall back to checking the main bundle for assets.
NSBundle* assetBundle = _dartBundle ?: [NSBundle mainBundle];
NSString* flutterAssetsName = [assetBundle objectForInfoDictionaryKey:@"FLTAssetsPath"];
......@@ -41,6 +55,10 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
}
- (NSString*)ICUDataPath {
if (_ICUDataPath) {
return _ICUDataPath;
}
NSString* path = [[NSBundle bundleForClass:[self class]] pathForResource:kICUBundlePath
ofType:nil];
if (!path) {
......
......@@ -33,6 +33,13 @@
*/
@property(nonatomic, readonly) std::vector<const char*> argv;
/**
* Instead of looking up the assets and ICU data path in the application bundle, this initializer
* allows callers to create a Dart project with custom locations specified for the both.
*/
- (nonnull instancetype)initWithAssetsPath:(nonnull NSString*)assets
ICUDataPath:(nonnull NSString*)icuPath NS_DESIGNATED_INITIALIZER;
@end
#endif // SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDARTPROJECT_INTERNAL_H_
......@@ -42,17 +42,18 @@
*/
- (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message;
/**
* Shuts the Flutter engine if it is running.
*/
- (void)shutDownEngine;
/**
* Forwards texture copy request to the corresponding texture via |textureID|.
*/
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID
openGLTexture:(FlutterOpenGLTexture*)openGLTexture;
/**
* Requests that the task be posted back the to the Flutter engine at the target time. The target
* time is in the clock used by the Flutter engine.
*/
- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime;
@end
#pragma mark -
......@@ -218,6 +219,26 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
flutterArguments.command_line_argv = &arguments[0];
flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage;
flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String;
static size_t sTaskRunnerIdentifiers = 0;
const FlutterTaskRunnerDescription cocoa_task_runner_description = {
.struct_size = sizeof(FlutterTaskRunnerDescription),
.user_data = (void*)CFBridgingRetain(self),
.runs_task_on_current_thread_callback = [](void* user_data) -> bool {
return [[NSThread currentThread] isMainThread];
},
.post_task_callback = [](FlutterTask task, uint64_t target_time_nanos,
void* user_data) -> void {
[((__bridge FlutterEngine*)(user_data)) postMainThreadTask:task
targetTimeInNanoseconds:target_time_nanos];
},
.identifier = ++sTaskRunnerIdentifiers,
};
const FlutterCustomTaskRunners custom_task_runners = {
.struct_size = sizeof(FlutterCustomTaskRunners),
.platform_task_runner = &cocoa_task_runner_description,
.render_task_runner = &cocoa_task_runner_description,
};
flutterArguments.custom_task_runners = &custom_task_runners;
FlutterEngineResult result = FlutterEngineInitialize(
FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine);
......@@ -358,6 +379,9 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
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);
if (result != kSuccess) {
NSLog(@"Failed to shut down Flutter engine: error %d", result);
......@@ -459,4 +483,29 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
[_textures removeObjectForKey:@(textureID)];
}
#pragma mark - Task runner integration
- (void)postMainThreadTask:(FlutterTask)task targetTimeInNanoseconds:(uint64_t)targetTime {
const auto engine_time = FlutterEngineGetCurrentTime();
__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);
if (result != kSuccess) {
NSLog(@"Could not post a task to the Flutter engine.");
}
}
};
if (targetTime <= engine_time) {
dispatch_async(dispatch_get_main_queue(), worker);
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, targetTime - engine_time),
dispatch_get_main_queue(), worker);
}
}
@end
// 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.
#include "flutter/shell/platform/darwin/macos/framework/Headers/FlutterEngine.h"
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h"
#include "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
#include "flutter/testing/testing.h"
namespace flutter::testing {
TEST(FlutterEngineTest, FlutterEngineCanLaunch) {
NSString* fixtures = @(testing::GetFixturesPath());
FlutterDartProject* project = [[FlutterDartProject alloc]
initWithAssetsPath:fixtures
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"test"
project:project
allowHeadlessExecution:true];
ASSERT_TRUE([engine runWithEntrypoint:@"main"]);
ASSERT_TRUE(engine.running);
[engine shutDownEngine];
}
} // flutter::testing
// 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.
void main() {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册