This commit is contained in:
Dan Field
2019-07-30 17:11:04 -07:00
committed by GitHub
parent bdcc59d93d
commit cd18c5ef0b
10 changed files with 211 additions and 211 deletions

View File

@@ -3,7 +3,6 @@
// found in the LICENSE file.
#define RAPIDJSON_HAS_STDSTRING 1
#include "flutter/shell/common/shell.h"
#include <memory>
@@ -372,6 +371,79 @@ void Shell::NotifyLowMemoryWarning() const {
// to purge them.
}
void Shell::RunEngine(RunConfiguration run_configuration) {
RunEngine(std::move(run_configuration), nullptr);
}
void Shell::RunEngine(RunConfiguration run_configuration,
std::function<void(Engine::RunStatus)> result_callback) {
auto result = [platform_runner = task_runners_.GetPlatformTaskRunner(),
result_callback](Engine::RunStatus run_result) {
if (!result_callback) {
return;
}
platform_runner->PostTask(
[result_callback, run_result]() { result_callback(run_result); });
};
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
if (!weak_engine_) {
result(Engine::RunStatus::Failure);
}
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
if (!weak_engine) {
FML_LOG(ERROR)
<< "Could not launch engine with configuration - no engine.";
result(Engine::RunStatus::Failure);
return;
}
auto run_result = weak_engine->Run(std::move(run_configuration));
if (run_result == flutter::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine with configuration.";
}
result(run_result);
}));
}
std::optional<DartErrorCode> Shell::GetUIIsolateLastError() const {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
// We're using the unique_ptr here because we're sure we're on the Platform
// Thread and callers expect this to be synchronous.
if (!engine_) {
return std::nullopt;
}
switch (engine_->GetUIIsolateLastError()) {
case tonic::kCompilationErrorType:
return DartErrorCode::CompilationError;
case tonic::kApiErrorType:
return DartErrorCode::ApiError;
case tonic::kUnknownErrorType:
return DartErrorCode::UnknownError;
case tonic::kNoError:
return DartErrorCode::NoError;
}
return DartErrorCode::UnknownError;
}
bool Shell::EngineHasLivePorts() const {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
// We're using the unique_ptr here because we're sure we're on the Platform
// Thread and callers expect this to be synchronous.
if (!engine_) {
return false;
}
return engine_->UIIsolateHasLivePorts();
}
bool Shell::IsSetup() const {
return is_setup_;
}
@@ -425,10 +497,14 @@ fml::WeakPtr<Rasterizer> Shell::GetRasterizer() {
return weak_rasterizer_;
}
// TODO(dnfield): Remove this when either Topaz is up to date or flutter_runner
// is built out of this repo.
#ifdef OS_FUCHSIA
fml::WeakPtr<Engine> Shell::GetEngine() {
FML_DCHECK(is_setup_);
return weak_engine_;
}
#endif // OS_FUCHSIA
fml::WeakPtr<PlatformView> Shell::GetPlatformView() {
FML_DCHECK(is_setup_);
@@ -907,7 +983,7 @@ void Shell::ReportTimings() {
auto timings = std::move(unreported_timings_);
unreported_timings_ = {};
task_runners_.GetUITaskRunner()->PostTask([timings, engine = GetEngine()] {
task_runners_.GetUITaskRunner()->PostTask([timings, engine = weak_engine_] {
if (engine) {
engine->ReportTimings(std::move(timings));
}

View File

@@ -35,6 +35,18 @@
namespace flutter {
/// Error exit codes for the Dart isolate.
enum class DartErrorCode {
/// No error has occurred.
NoError = 0,
/// The Dart error code for an API error.
ApiError = 253,
/// The Dart error code for a compilation error.
CompilationError = 254,
/// The Dart error code for an unkonwn error.
UnknownError = 255
};
//------------------------------------------------------------------------------
/// Perhaps the single most important class in the Flutter engine repository.
/// When embedders create a Flutter application, they are referring to the
@@ -165,6 +177,19 @@ class Shell final : public PlatformView::Delegate,
///
~Shell();
//----------------------------------------------------------------------------
/// @brief Starts an isolate for the given RunConfiguration.
///
void RunEngine(RunConfiguration run_configuration);
//----------------------------------------------------------------------------
/// @brief Starts an isolate for the given RunConfiguration. The
/// result_callback will be called with the status of the
/// operation.
///
void RunEngine(RunConfiguration run_configuration,
std::function<void(Engine::RunStatus)> result_callback);
//------------------------------------------------------------------------------
/// @return The settings used to launch this shell.
///
@@ -191,12 +216,18 @@ class Shell final : public PlatformView::Delegate,
///
fml::WeakPtr<Rasterizer> GetRasterizer();
// TODO(dnfield): Remove this when either Topaz is up to date or flutter_runner
// is built out of this repo.
#ifdef OS_FUCHSIA
//------------------------------------------------------------------------------
/// @brief Engines may only be accessed on the UI thread.
/// @brief Engines may only be accessed on the UI thread. This method is
/// deprecated, and implementers should instead use other API
/// available on the Shell or the PlatformView.
///
/// @return A weak pointer to the engine.
///
fml::WeakPtr<Engine> GetEngine();
#endif // OS_FUCHSIA
//----------------------------------------------------------------------------
/// @brief Platform views may only be accessed on the platform task
@@ -253,6 +284,25 @@ class Shell final : public PlatformView::Delegate,
///
fml::Status WaitForFirstFrame(fml::TimeDelta timeout);
//----------------------------------------------------------------------------
/// @brief Used by embedders to get the last error from the Dart UI
/// Isolate, if one exists.
///
/// @return Returns the last error code from the UI Isolate.
///
std::optional<DartErrorCode> GetUIIsolateLastError() const;
//----------------------------------------------------------------------------
/// @brief Used by embedders to check if the Engine is running and has
/// any live ports remaining. For example, the Flutter tester uses
/// this method to check whether it should continue to wait for
/// a running test or not.
///
/// @return Returns if the shell has an engine and the engine has any live
/// Dart ports.
///
bool EngineHasLivePorts() const;
private:
using ServiceProtocolHandler =
std::function<bool(const ServiceProtocol::Handler::ServiceProtocolMap&,

View File

@@ -75,13 +75,14 @@ void ShellTest::PlatformViewNotifyCreated(Shell* shell) {
void ShellTest::RunEngine(Shell* shell, RunConfiguration configuration) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&latch, config = std::move(configuration),
engine = shell->GetEngine()]() mutable {
ASSERT_TRUE(engine);
ASSERT_EQ(engine->Run(std::move(config)), Engine::RunStatus::Success);
latch.Signal();
}));
shell->GetTaskRunners().GetPlatformTaskRunner(),
[shell, &latch, &configuration]() {
shell->RunEngine(std::move(configuration),
[&latch](Engine::RunStatus run_status) {
ASSERT_EQ(run_status, Engine::RunStatus::Success);
latch.Signal();
});
});
latch.Wait();
}
@@ -91,7 +92,7 @@ void ShellTest::PumpOneFrame(Shell* shell) {
// won't be rasterized.
fml::AutoResetWaitableEvent latch;
shell->GetTaskRunners().GetUITaskRunner()->PostTask(
[&latch, engine = shell->GetEngine()]() {
[&latch, engine = shell->weak_engine_]() {
engine->SetViewportMetrics({1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0});
engine->animator_->BeginFrame(fml::TimePoint::Now(),
fml::TimePoint::Now());
@@ -101,7 +102,7 @@ void ShellTest::PumpOneFrame(Shell* shell) {
latch.Reset();
// Call |Render| to rasterize a layer tree and trigger |OnFrameRasterized|
fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->GetEngine();
fml::WeakPtr<RuntimeDelegate> runtime_delegate = shell->weak_engine_;
shell->GetTaskRunners().GetUITaskRunner()->PostTask(
[&latch, runtime_delegate]() {
auto layer_tree = std::make_unique<LayerTree>();

View File

@@ -157,53 +157,7 @@ void AndroidShellHolder::Launch(RunConfiguration config) {
return;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = shell_->GetEngine(), //
config = std::move(config) //
]() mutable {
FML_LOG(INFO) << "Attempting to launch engine configuration...";
if (!engine ||
engine->Run(std::move(config)) == Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine in configuration.";
} else {
FML_LOG(INFO) << "Isolate for engine configuration successfully "
"started and run.";
}
}));
}
void AndroidShellHolder::SetViewportMetrics(
const flutter::ViewportMetrics& metrics) {
if (!IsValid()) {
return;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = shell_->GetEngine(), metrics]() {
if (engine) {
engine->SetViewportMetrics(metrics);
}
});
}
void AndroidShellHolder::DispatchPointerDataPacket(
std::unique_ptr<flutter::PointerDataPacket> packet) {
if (!IsValid()) {
return;
}
TRACE_EVENT0("flutter", "AndroidShellHolder::DispatchPointerDataPacket");
TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = shell_->GetEngine(), packet = std::move(packet),
flow_id = next_pointer_flow_id_] {
if (engine) {
engine->DispatchPointerDataPacket(*packet, flow_id);
}
}));
next_pointer_flow_id_++;
shell_->RunEngine(std::move(config));
}
Rasterizer::Screenshot AndroidShellHolder::Screenshot(

View File

@@ -30,11 +30,6 @@ class AndroidShellHolder {
void Launch(RunConfiguration configuration);
void SetViewportMetrics(const flutter::ViewportMetrics& metrics);
void DispatchPointerDataPacket(
std::unique_ptr<flutter::PointerDataPacket> packet);
const flutter::Settings& GetSettings() const;
fml::WeakPtr<PlatformViewAndroid> GetPlatformView();

View File

@@ -276,7 +276,7 @@ static void SetViewportMetrics(JNIEnv* env,
static_cast<double>(physicalViewInsetLeft),
};
ANDROID_SHELL_HOLDER->SetViewportMetrics(metrics);
ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics);
}
static jobject GetBitmap(JNIEnv* env, jobject jcaller, jlong shell_holder) {
@@ -387,7 +387,8 @@ static void DispatchPointerDataPacket(JNIEnv* env,
jint position) {
uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
auto packet = std::make_unique<flutter::PointerDataPacket>(data, position);
ANDROID_SHELL_HOLDER->DispatchPointerDataPacket(std::move(packet));
ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPointerDataPacket(
std::move(packet));
}
static void DispatchSemanticsAction(JNIEnv* env,

View File

@@ -63,8 +63,6 @@
int64_t _nextTextureId;
uint64_t _nextPointerFlowId;
BOOL _allowHeadlessExecution;
FlutterBinaryMessengerRelay* _binaryMessenger;
}
@@ -126,24 +124,17 @@
}
- (void)updateViewportMetrics:(flutter::ViewportMetrics)viewportMetrics {
self.shell.GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = self.shell.GetEngine(), metrics = viewportMetrics]() {
if (engine) {
engine->SetViewportMetrics(std::move(metrics));
}
});
if (!self.platformView) {
return;
}
self.platformView->SetViewportMetrics(std::move(viewportMetrics));
}
- (void)dispatchPointerDataPacket:(std::unique_ptr<flutter::PointerDataPacket>)packet {
TRACE_EVENT0("flutter", "dispatchPointerDataPacket");
TRACE_FLOW_BEGIN("flutter", "PointerEvent", _nextPointerFlowId);
self.shell.GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = self.shell.GetEngine(), packet = std::move(packet), flow_id = _nextPointerFlowId] {
if (engine) {
engine->DispatchPointerDataPacket(*packet, flow_id);
}
}));
_nextPointerFlowId++;
if (!self.platformView) {
return;
}
self.platformView->DispatchPointerDataPacket(std::move(packet));
}
- (fml::WeakPtr<flutter::PlatformView>)platformView {
@@ -312,18 +303,8 @@
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil {
// Launch the Dart application with the inferred run configuration.
self.shell.GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = _shell->GetEngine(),
config = [_dartProject.get() runConfigurationForEntrypoint:entrypoint
libraryOrNil:libraryOrNil] //
]() mutable {
if (engine) {
auto result = engine->Run(std::move(config));
if (result == flutter::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine with configuration.";
}
}
}));
self.shell.RunEngine([_dartProject.get() runConfigurationForEntrypoint:entrypoint
libraryOrNil:libraryOrNil]);
}
- (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryURI {

View File

@@ -63,19 +63,7 @@ bool EmbedderEngine::Run(RunConfiguration run_configuration) {
if (!IsValid() || !run_configuration.IsValid()) {
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = shell_->GetEngine(), // engine
config = std::move(run_configuration) // config
]() mutable {
if (engine) {
auto result = engine->Run(std::move(config));
if (result == Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch the engine with configuration.";
}
}
}));
shell_->RunEngine(std::move(run_configuration));
return true;
}
@@ -84,12 +72,11 @@ bool EmbedderEngine::SetViewportMetrics(flutter::ViewportMetrics metrics) {
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = shell_->GetEngine(), metrics = std::move(metrics)]() {
if (engine) {
engine->SetViewportMetrics(std::move(metrics));
}
});
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetViewportMetrics(std::move(metrics));
return true;
}
@@ -99,18 +86,12 @@ bool EmbedderEngine::DispatchPointerDataPacket(
return false;
}
TRACE_EVENT0("flutter", "EmbedderEngine::DispatchPointerDataPacket");
TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = shell_->GetEngine(), packet = std::move(packet),
flow_id = next_pointer_flow_id_] {
if (engine) {
engine->DispatchPointerDataPacket(*packet, flow_id);
}
}));
next_pointer_flow_id_++;
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchPointerDataPacket(std::move(packet));
return true;
}
@@ -120,13 +101,12 @@ bool EmbedderEngine::SendPlatformMessage(
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = shell_->GetEngine(), message] {
if (engine) {
engine->DispatchPlatformMessage(message);
}
});
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchPlatformMessage(message);
return true;
}
@@ -160,12 +140,12 @@ bool EmbedderEngine::SetSemanticsEnabled(bool enabled) {
if (!IsValid()) {
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = shell_->GetEngine(), enabled] {
if (engine) {
engine->SetSemanticsEnabled(enabled);
}
});
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetSemanticsEnabled(enabled);
return true;
}
@@ -173,12 +153,11 @@ bool EmbedderEngine::SetAccessibilityFeatures(int32_t flags) {
if (!IsValid()) {
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
[engine = shell_->GetEngine(), flags] {
if (engine) {
engine->SetAccessibilityFeatures(flags);
}
});
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->SetAccessibilityFeatures(flags);
return true;
}
@@ -188,16 +167,11 @@ bool EmbedderEngine::DispatchSemanticsAction(int id,
if (!IsValid()) {
return false;
}
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
fml::MakeCopyable([engine = shell_->GetEngine(), // engine
id, // id
action, // action
args = std::move(args) // args
]() mutable {
if (engine) {
engine->DispatchSemanticsAction(id, action, std::move(args));
}
}));
auto platform_view = shell_->GetPlatformView();
if (!platform_view) {
return false;
}
platform_view->DispatchSemanticsAction(id, action, std::move(args));
return true;
}

View File

@@ -78,7 +78,6 @@ class EmbedderEngine {
const EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback_;
bool is_valid_ = false;
uint64_t next_pointer_flow_id_ = 0;
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderEngine);
};

View File

@@ -20,6 +20,7 @@
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/thread_host.h"
#include "third_party/dart/runtime/include/bin/dart_io_api.h"
#include "third_party/dart/runtime/include/dart_api.h"
namespace flutter {
@@ -30,35 +31,20 @@ class ScriptCompletionTaskObserver {
ScriptCompletionTaskObserver(Shell& shell,
fml::RefPtr<fml::TaskRunner> main_task_runner,
bool run_forever)
: engine_(shell.GetEngine()),
: shell_(shell),
main_task_runner_(std::move(main_task_runner)),
run_forever_(run_forever) {}
int GetExitCodeForLastError() const {
// Exit codes used by the Dart command line tool.
const int kApiErrorExitCode = 253;
const int kCompilationErrorExitCode = 254;
const int kErrorExitCode = 255;
switch (last_error_) {
case tonic::kCompilationErrorType:
return kCompilationErrorExitCode;
case tonic::kApiErrorType:
return kApiErrorExitCode;
case tonic::kUnknownErrorType:
return kErrorExitCode;
default:
return 0;
}
return static_cast<int>(last_error_.value_or(DartErrorCode::NoError));
}
void DidProcessTask() {
if (engine_) {
last_error_ = engine_->GetUIIsolateLastError();
if (engine_->UIIsolateHasLivePorts()) {
// The UI isolate still has live ports and is running. Nothing to do
// just yet.
return;
}
last_error_ = shell_.GetUIIsolateLastError();
if (shell_.EngineHasLivePorts()) {
// The UI isolate still has live ports and is running. Nothing to do
// just yet.
return;
}
if (run_forever_) {
@@ -76,10 +62,10 @@ class ScriptCompletionTaskObserver {
}
private:
fml::WeakPtr<Engine> engine_;
Shell& shell_;
fml::RefPtr<fml::TaskRunner> main_task_runner_;
bool run_forever_ = false;
tonic::DartErrorHandleType last_error_ = tonic::kUnknownErrorType;
std::optional<DartErrorCode> last_error_;
bool has_terminated = false;
FML_DISALLOW_COPY_AND_ASSIGN(ScriptCompletionTaskObserver);
@@ -175,47 +161,30 @@ int RunTester(const flutter::Settings& settings, bool run_forever) {
bool engine_did_run = false;
fml::AutoResetWaitableEvent sync_run_latch;
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&sync_run_latch, &completion_observer,
engine = shell->GetEngine(),
config = std::move(run_configuration),
&engine_did_run]() mutable {
fml::MessageLoop::GetCurrent().AddTaskObserver(
reinterpret_cast<intptr_t>(&completion_observer),
[&completion_observer]() { completion_observer.DidProcessTask(); });
if (engine->Run(std::move(config)) !=
flutter::Engine::RunStatus::Failure) {
engine_did_run = true;
fml::MessageLoop::GetCurrent().AddTaskObserver(
reinterpret_cast<intptr_t>(&completion_observer),
[&completion_observer]() { completion_observer.DidProcessTask(); });
flutter::ViewportMetrics metrics;
metrics.device_pixel_ratio = 3.0;
metrics.physical_width = 2400; // 800 at 3x resolution
metrics.physical_height = 1800; // 600 at 3x resolution
engine->SetViewportMetrics(metrics);
shell->RunEngine(std::move(run_configuration),
[&engine_did_run](Engine::RunStatus run_status) mutable {
if (run_status != flutter::Engine::RunStatus::Failure) {
engine_did_run = true;
}
});
} else {
FML_DLOG(ERROR) << "Could not launch the engine with configuration.";
}
sync_run_latch.Signal();
}));
sync_run_latch.Wait();
flutter::ViewportMetrics metrics;
metrics.device_pixel_ratio = 3.0;
metrics.physical_width = 2400; // 800 at 3x resolution
metrics.physical_height = 1800; // 600 at 3x resolution
shell->GetPlatformView()->SetViewportMetrics(metrics);
// Run the message loop and wait for the script to do its thing.
fml::MessageLoop::GetCurrent().Run();
// Cleanup the completion observer synchronously as it is living on the
// stack.
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
[&latch, &completion_observer] {
fml::MessageLoop::GetCurrent().RemoveTaskObserver(
reinterpret_cast<intptr_t>(&completion_observer));
latch.Signal();
});
latch.Wait();
fml::MessageLoop::GetCurrent().RemoveTaskObserver(
reinterpret_cast<intptr_t>(&completion_observer));
if (!engine_did_run) {
// If the engine itself didn't have a chance to run, there is no point in