未验证 提交 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") { ...@@ -58,8 +58,10 @@ group("flutter") {
# If on the host, compile all unittests targets. # If on the host, compile all unittests targets.
if (current_toolchain == host_toolchain) { if (current_toolchain == host_toolchain) {
if (is_mac) { if (is_mac) {
public_deps += public_deps += [
[ "$flutter_root/shell/platform/darwin:flutter_channels_unittests" ] "$flutter_root/shell/platform/darwin:flutter_channels_unittests",
"$flutter_root/shell/platform/darwin/macos:flutter_desktop_darwin_unittests",
]
} }
public_deps += [ public_deps += [
......
...@@ -824,6 +824,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterAppDe ...@@ -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.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterDartProject_Internal.h 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/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/FlutterEngine_Internal.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.h
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTextureGL.mm
...@@ -835,6 +836,7 @@ FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterView. ...@@ -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/FlutterView.mm
FILE: ../../../flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController.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/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/darwin/macos/framework/module.modulemap
FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist FILE: ../../../flutter/shell/platform/embedder/assets/EmbedderInfo.plist
FILE: ../../../flutter/shell/platform/embedder/assets/embedder.modulemap FILE: ../../../flutter/shell/platform/embedder/assets/embedder.modulemap
......
...@@ -8,6 +8,7 @@ import("//build/config/mac/mac_sdk.gni") ...@@ -8,6 +8,7 @@ import("//build/config/mac/mac_sdk.gni")
import("$flutter_root/common/config.gni") import("$flutter_root/common/config.gni")
import("$flutter_root/shell/platform/darwin/common/framework_shared.gni") import("$flutter_root/shell/platform/darwin/common/framework_shared.gni")
import("$flutter_root/shell/platform/glfw/config.gni") import("$flutter_root/shell/platform/glfw/config.gni")
import("$flutter_root/testing/testing.gni")
group("macos") { group("macos") {
deps = [ deps = [
...@@ -41,11 +42,9 @@ _flutter_framework_headers = [ ...@@ -41,11 +42,9 @@ _flutter_framework_headers = [
_flutter_framework_headers_copy_dir = _flutter_framework_headers_copy_dir =
"$_flutter_framework_dir/Versions/A/Headers" "$_flutter_framework_dir/Versions/A/Headers"
shared_library("create_flutter_framework_dylib") { source_set("flutter_framework_source") {
visibility = [ ":*" ] visibility = [ ":*" ]
output_name = "$_flutter_framework_name"
sources = [ sources = [
"framework/Source/FlutterAppDelegate.mm", "framework/Source/FlutterAppDelegate.mm",
"framework/Source/FlutterDartProject.mm", "framework/Source/FlutterDartProject.mm",
...@@ -83,6 +82,43 @@ shared_library("create_flutter_framework_dylib") { ...@@ -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") { action("copy_dylib_and_update_framework_install_name") {
visibility = [ ":*" ] visibility = [ ":*" ]
script = "$flutter_root/sky/tools/change_install_name.py" script = "$flutter_root/sky/tools/change_install_name.py"
...@@ -108,7 +144,7 @@ action("copy_dylib_and_update_framework_install_name") { ...@@ -108,7 +144,7 @@ action("copy_dylib_and_update_framework_install_name") {
] ]
deps = [ deps = [
":create_flutter_framework_dylib", ":flutter_framework_dylib",
] ]
} }
......
...@@ -72,6 +72,13 @@ FLUTTER_EXPORT ...@@ -72,6 +72,13 @@ FLUTTER_EXPORT
*/ */
@property(nonatomic, nonnull, readonly) id<FlutterBinaryMessenger> binaryMessenger; @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 @end
#endif // FLUTTER_FLUTTERENGINE_H_ #endif // FLUTTER_FLUTTERENGINE_H_
...@@ -12,6 +12,8 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app"; ...@@ -12,6 +12,8 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
@implementation FlutterDartProject { @implementation FlutterDartProject {
NSBundle* _dartBundle; NSBundle* _dartBundle;
NSString* _assetsPath;
NSString* _ICUDataPath;
} }
- (instancetype)init { - (instancetype)init {
...@@ -26,7 +28,19 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app"; ...@@ -26,7 +28,19 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
return self; 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 { - (NSString*)assetsPath {
if (_assetsPath) {
return _assetsPath;
}
// If there's no App.framework, fall back to checking the main bundle for assets. // If there's no App.framework, fall back to checking the main bundle for assets.
NSBundle* assetBundle = _dartBundle ?: [NSBundle mainBundle]; NSBundle* assetBundle = _dartBundle ?: [NSBundle mainBundle];
NSString* flutterAssetsName = [assetBundle objectForInfoDictionaryKey:@"FLTAssetsPath"]; NSString* flutterAssetsName = [assetBundle objectForInfoDictionaryKey:@"FLTAssetsPath"];
...@@ -41,6 +55,10 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app"; ...@@ -41,6 +55,10 @@ static NSString* const kAppBundleIdentifier = @"io.flutter.flutter.app";
} }
- (NSString*)ICUDataPath { - (NSString*)ICUDataPath {
if (_ICUDataPath) {
return _ICUDataPath;
}
NSString* path = [[NSBundle bundleForClass:[self class]] pathForResource:kICUBundlePath NSString* path = [[NSBundle bundleForClass:[self class]] pathForResource:kICUBundlePath
ofType:nil]; ofType:nil];
if (!path) { if (!path) {
......
...@@ -33,6 +33,13 @@ ...@@ -33,6 +33,13 @@
*/ */
@property(nonatomic, readonly) std::vector<const char*> argv; @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 @end
#endif // SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDARTPROJECT_INTERNAL_H_ #endif // SHELL_PLATFORM_DARWIN_MACOS_FRAMEWORK_SOURCE_FLUTTERDARTPROJECT_INTERNAL_H_
...@@ -42,17 +42,18 @@ ...@@ -42,17 +42,18 @@
*/ */
- (void)engineCallbackOnPlatformMessage:(const FlutterPlatformMessage*)message; - (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|. * Forwards texture copy request to the corresponding texture via |textureID|.
*/ */
- (BOOL)populateTextureWithIdentifier:(int64_t)textureID - (BOOL)populateTextureWithIdentifier:(int64_t)textureID
openGLTexture:(FlutterOpenGLTexture*)openGLTexture; 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 @end
#pragma mark - #pragma mark -
...@@ -218,6 +219,26 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine, ...@@ -218,6 +219,26 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
flutterArguments.command_line_argv = &arguments[0]; flutterArguments.command_line_argv = &arguments[0];
flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage; flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage;
flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String; 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( FlutterEngineResult result = FlutterEngineInitialize(
FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine); FLUTTER_ENGINE_VERSION, &rendererConfig, &flutterArguments, (__bridge void*)(self), &_engine);
...@@ -358,6 +379,9 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine, ...@@ -358,6 +379,9 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
NSLog(@"Could not de-initialize the Flutter engine: error %d", result); 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 = FlutterEngineShutdown(_engine);
if (result != kSuccess) { if (result != kSuccess) {
NSLog(@"Failed to shut down Flutter engine: error %d", result); NSLog(@"Failed to shut down Flutter engine: error %d", result);
...@@ -459,4 +483,29 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine, ...@@ -459,4 +483,29 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
[_textures removeObjectForKey:@(textureID)]; [_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 @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.
先完成此消息的编辑!
想要评论请 注册