engine.cc 13.5 KB
Newer Older
1 2 3 4
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "flutter/shell/common/engine.h"
6

7
#include <memory>
8 9
#include <utility>

10
#include "flutter/common/settings.h"
11 12 13 14
#include "flutter/fml/eintr_wrapper.h"
#include "flutter/fml/file.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/paths.h"
15
#include "flutter/fml/trace_event.h"
16
#include "flutter/fml/unique_fd.h"
R
Ryan Macnak 已提交
17
#include "flutter/lib/snapshot/snapshot.h"
18
#include "flutter/lib/ui/text/font_collection.h"
19
#include "flutter/shell/common/animator.h"
20
#include "flutter/shell/common/platform_view.h"
21
#include "flutter/shell/common/shell.h"
22
#include "rapidjson/document.h"
A
Adam Barth 已提交
23 24
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
25

26 27
#ifdef ERROR
#undef ERROR
28
#endif
29

30
namespace shell {
31

32 33 34 35 36 37 38
static constexpr char kAssetChannel[] = "flutter/assets";
static constexpr char kLifecycleChannel[] = "flutter/lifecycle";
static constexpr char kNavigationChannel[] = "flutter/navigation";
static constexpr char kLocalizationChannel[] = "flutter/localization";
static constexpr char kSettingsChannel[] = "flutter/settings";

Engine::Engine(Delegate& delegate,
B
Ben Konyi 已提交
39
               blink::DartVM& vm,
40 41
               fml::RefPtr<blink::DartSnapshot> isolate_snapshot,
               fml::RefPtr<blink::DartSnapshot> shared_snapshot,
42 43 44 45
               blink::TaskRunners task_runners,
               blink::Settings settings,
               std::unique_ptr<Animator> animator,
               fml::WeakPtr<GrContext> resource_context,
46
               fml::RefPtr<flow::SkiaUnrefQueue> unref_queue)
47 48 49
    : delegate_(delegate),
      settings_(std::move(settings)),
      animator_(std::move(animator)),
50 51
      activity_running_(false),
      have_surface_(false),
52 53 54 55 56
      weak_factory_(this) {
  // Runtime controller is initialized here because it takes a reference to this
  // object as its delegate. The delegate may be called in the constructor and
  // we want to be fully initilazed by that point.
  runtime_controller_ = std::make_unique<blink::RuntimeController>(
57 58 59 60 61 62 63 64 65
      *this,                                // runtime delegate
      &vm,                                  // VM
      std::move(isolate_snapshot),          // isolate snapshot
      std::move(shared_snapshot),           // shared snapshot
      std::move(task_runners),              // task runners
      std::move(resource_context),          // resource context
      std::move(unref_queue),               // skia unref queue
      settings_.advisory_script_uri,        // advisory script uri
      settings_.advisory_script_entrypoint  // advisory script entrypoint
66
  );
67 68
}

J
Jason Simmons 已提交
69
Engine::~Engine() = default;
70

71
fml::WeakPtr<Engine> Engine::GetWeakPtr() const {
72
  return weak_factory_.GetWeakPtr();
73 74 75
}

bool Engine::UpdateAssetManager(
76
    fml::RefPtr<blink::AssetManager> new_asset_manager) {
77 78
  if (asset_manager_ == new_asset_manager) {
    return false;
R
Ryan Macnak 已提交
79 80
  }

81
  asset_manager_ = new_asset_manager;
82

83 84
  if (!asset_manager_) {
    return false;
85 86
  }

J
Jason Simmons 已提交
87 88
  // Using libTXT as the text engine.
  if (settings_.use_test_fonts) {
89
    font_collection_.RegisterTestFonts();
90
  } else {
91
    font_collection_.RegisterFonts(asset_manager_);
92 93
  }

94 95
  return true;
}
96

97 98 99
bool Engine::Restart(RunConfiguration configuration) {
  TRACE_EVENT0("flutter", "Engine::Restart");
  if (!configuration.IsValid()) {
100
    FML_LOG(ERROR) << "Engine run configuration was invalid.";
101
    return false;
102
  }
103
  delegate_.OnPreEngineRestart();
104 105
  runtime_controller_ = runtime_controller_->Clone();
  UpdateAssetManager(nullptr);
106
  return Run(std::move(configuration)) == Engine::RunStatus::Success;
107
}
108

109
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
110
  if (!configuration.IsValid()) {
111
    FML_LOG(ERROR) << "Engine run configuration was invalid.";
112
    return RunStatus::Failure;
113
  }
R
Ryan Macnak 已提交
114

115 116 117
  auto isolate_launch_status =
      PrepareAndLaunchIsolate(std::move(configuration));
  if (isolate_launch_status == Engine::RunStatus::Failure) {
118
    FML_LOG(ERROR) << "Engine not prepare and launch isolate.";
119 120 121 122
    return isolate_launch_status;
  } else if (isolate_launch_status ==
             Engine::RunStatus::FailureAlreadyRunning) {
    return isolate_launch_status;
123
  }
R
Ryan Macnak 已提交
124

125 126
  std::shared_ptr<blink::DartIsolate> isolate =
      runtime_controller_->GetRootIsolate().lock();
R
Ryan Macnak 已提交
127

128 129
  bool isolate_running =
      isolate && isolate->GetPhase() == blink::DartIsolate::Phase::Running;
R
Ryan Macnak 已提交
130

131 132
  if (isolate_running) {
    tonic::DartState::Scope scope(isolate.get());
133

134 135 136
    if (settings_.root_isolate_create_callback) {
      settings_.root_isolate_create_callback();
    }
137

138 139 140 141
    if (settings_.root_isolate_shutdown_callback) {
      isolate->AddIsolateShutdownCallback(
          settings_.root_isolate_shutdown_callback);
    }
142
  }
143

144 145
  return isolate_running ? Engine::RunStatus::Success
                         : Engine::RunStatus::Failure;
146 147
}

148 149
shell::Engine::RunStatus Engine::PrepareAndLaunchIsolate(
    RunConfiguration configuration) {
150
  TRACE_EVENT0("flutter", "Engine::PrepareAndLaunchIsolate");
151

152
  UpdateAssetManager(configuration.GetAssetManager());
153

154 155
  auto isolate_configuration = configuration.TakeIsolateConfiguration();

156 157
  std::shared_ptr<blink::DartIsolate> isolate =
      runtime_controller_->GetRootIsolate().lock();
158

159
  if (!isolate) {
160 161 162 163 164 165 166 167
    return RunStatus::Failure;
  }

  // This can happen on iOS after a plugin shows a native window and returns to
  // the Flutter ViewController.
  if (isolate->GetPhase() == blink::DartIsolate::Phase::Running) {
    FML_DLOG(WARNING) << "Isolate was already running!";
    return RunStatus::FailureAlreadyRunning;
168 169 170
  }

  if (!isolate_configuration->PrepareIsolate(*isolate)) {
171
    FML_LOG(ERROR) << "Could not prepare to run the isolate.";
172
    return RunStatus::Failure;
173 174
  }

175 176
  if (configuration.GetEntrypointLibrary().empty()) {
    if (!isolate->Run(configuration.GetEntrypoint())) {
177
      FML_LOG(ERROR) << "Could not run the isolate.";
178
      return RunStatus::Failure;
179 180 181 182
    }
  } else {
    if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(),
                                 configuration.GetEntrypoint())) {
183
      FML_LOG(ERROR) << "Could not run the isolate.";
184
      return RunStatus::Failure;
185
    }
186
  }
187

188
  return RunStatus::Success;
189 190
}

191
void Engine::BeginFrame(fml::TimePoint frame_time) {
192
  TRACE_EVENT0("flutter", "Engine::BeginFrame");
193
  runtime_controller_->BeginFrame(frame_time);
A
Adam Barth 已提交
194 195
}

196 197
void Engine::NotifyIdle(int64_t deadline) {
  TRACE_EVENT0("flutter", "Engine::NotifyIdle");
198
  runtime_controller_->NotifyIdle(deadline);
199 200
}

201 202
std::pair<bool, uint32_t> Engine::GetUIIsolateReturnCode() {
  return runtime_controller_->GetRootIsolateReturnCode();
203 204
}

205
Dart_Port Engine::GetUIIsolateMainPort() {
206
  return runtime_controller_->GetMainPort();
207 208
}

209
std::string Engine::GetUIIsolateName() {
210
  return runtime_controller_->GetIsolateName();
211 212
}

213
bool Engine::UIIsolateHasLivePorts() {
214
  return runtime_controller_->HasLivePorts();
215 216
}

217
tonic::DartErrorHandleType Engine::GetUIIsolateLastError() {
218
  return runtime_controller_->GetLastError();
219 220
}

221
void Engine::OnOutputSurfaceCreated() {
222 223
  have_surface_ = true;
  StartAnimatorIfPossible();
224
  ScheduleFrame();
225 226
}

227
void Engine::OnOutputSurfaceDestroyed() {
228 229
  have_surface_ = false;
  StopAnimator();
230 231
}

232
void Engine::SetViewportMetrics(const blink::ViewportMetrics& metrics) {
233 234 235
  bool dimensions_changed =
      viewport_metrics_.physical_height != metrics.physical_height ||
      viewport_metrics_.physical_width != metrics.physical_width;
236
  viewport_metrics_ = metrics;
237
  runtime_controller_->SetViewportMetrics(viewport_metrics_);
238
  if (animator_) {
239 240
    if (dimensions_changed)
      animator_->SetDimensionChangePending();
241 242 243
    if (have_surface_)
      ScheduleFrame();
  }
244 245
}

246
void Engine::DispatchPlatformMessage(
247
    fml::RefPtr<blink::PlatformMessage> message) {
248 249 250 251
  if (message->channel() == kLifecycleChannel) {
    if (HandleLifecyclePlatformMessage(message.get()))
      return;
  } else if (message->channel() == kLocalizationChannel) {
252 253
    if (HandleLocalizationPlatformMessage(message.get()))
      return;
254 255 256
  } else if (message->channel() == kSettingsChannel) {
    HandleSettingsPlatformMessage(message.get());
    return;
257 258
  }

259 260
  if (runtime_controller_->IsRootIsolateRunning() &&
      runtime_controller_->DispatchPlatformMessage(std::move(message))) {
261 262 263
    return;
  }

264
  // If there's no runtime_, we may still need to set the initial route.
265 266
  if (message->channel() == kNavigationChannel)
    HandleNavigationPlatformMessage(std::move(message));
267 268
}

269 270 271
bool Engine::HandleLifecyclePlatformMessage(blink::PlatformMessage* message) {
  const auto& data = message->data();
  std::string state(reinterpret_cast<const char*>(data.data()), data.size());
272 273
  if (state == "AppLifecycleState.paused" ||
      state == "AppLifecycleState.suspending") {
274 275
    activity_running_ = false;
    StopAnimator();
276
  } else if (state == "AppLifecycleState.resumed" ||
277
             state == "AppLifecycleState.inactive") {
278 279 280
    activity_running_ = true;
    StartAnimatorIfPossible();
  }
281 282

  // Always schedule a frame when the app does become active as per API
283 284
  // recommendation
  // https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive?language=objc
285 286 287
  if (state == "AppLifecycleState.resumed" && have_surface_) {
    ScheduleFrame();
  }
288 289 290 291
  return false;
}

bool Engine::HandleNavigationPlatformMessage(
292
    fml::RefPtr<blink::PlatformMessage> message) {
293 294 295 296 297 298 299 300
  const auto& data = message->data();

  rapidjson::Document document;
  document.Parse(reinterpret_cast<const char*>(data.data()), data.size());
  if (document.HasParseError() || !document.IsObject())
    return false;
  auto root = document.GetObject();
  auto method = root.FindMember("method");
301
  if (method->value != "setInitialRoute")
302
    return false;
303 304
  auto route = root.FindMember("args");
  initial_route_ = std::move(route->value.GetString());
305 306 307 308
  return true;
}

bool Engine::HandleLocalizationPlatformMessage(
309
    blink::PlatformMessage* message) {
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
  const auto& data = message->data();

  rapidjson::Document document;
  document.Parse(reinterpret_cast<const char*>(data.data()), data.size());
  if (document.HasParseError() || !document.IsObject())
    return false;
  auto root = document.GetObject();
  auto method = root.FindMember("method");
  if (method == root.MemberEnd() || method->value != "setLocale")
    return false;

  auto args = root.FindMember("args");
  if (args == root.MemberEnd() || !args->value.IsArray())
    return false;

  const auto& language = args->value[0];
  const auto& country = args->value[1];

  if (!language.IsString() || !country.IsString())
    return false;

331 332
  return runtime_controller_->SetLocale(language.GetString(),
                                        country.GetString());
A
Adam Barth 已提交
333 334
}

335
void Engine::HandleSettingsPlatformMessage(blink::PlatformMessage* message) {
336
  const auto& data = message->data();
337
  std::string jsonData(reinterpret_cast<const char*>(data.data()), data.size());
338 339 340
  if (runtime_controller_->SetUserSettingsData(std::move(jsonData)) &&
      have_surface_) {
    ScheduleFrame();
341 342 343
  }
}

344 345
void Engine::DispatchPointerDataPacket(const blink::PointerDataPacket& packet) {
  runtime_controller_->DispatchPointerDataPacket(packet);
346 347
}

348 349 350
void Engine::DispatchSemanticsAction(int id,
                                     blink::SemanticsAction action,
                                     std::vector<uint8_t> args) {
351
  runtime_controller_->DispatchSemanticsAction(id, action, std::move(args));
352 353 354
}

void Engine::SetSemanticsEnabled(bool enabled) {
355
  runtime_controller_->SetSemanticsEnabled(enabled);
356 357
}

358 359
void Engine::SetAccessibilityFeatures(int32_t flags) {
  runtime_controller_->SetAccessibilityFeatures(flags);
360 361
}

362 363 364 365 366 367 368 369 370
void Engine::StopAnimator() {
  animator_->Stop();
}

void Engine::StartAnimatorIfPossible() {
  if (activity_running_ && have_surface_)
    animator_->Start();
}

371 372 373 374 375 376 377
std::string Engine::DefaultRouteName() {
  if (!initial_route_.empty()) {
    return initial_route_;
  }
  return "/";
}

378 379
void Engine::ScheduleFrame(bool regenerate_layer_tree) {
  animator_->RequestFrame(regenerate_layer_tree);
A
Adam Barth 已提交
380 381
}

382 383 384
void Engine::Render(std::unique_ptr<flow::LayerTree> layer_tree) {
  if (!layer_tree)
    return;
385

386 387
  SkISize frame_size = SkISize::Make(viewport_metrics_.physical_width,
                                     viewport_metrics_.physical_height);
388 389 390 391
  if (frame_size.isEmpty())
    return;

  layer_tree->set_frame_size(frame_size);
392 393
  animator_->Render(std::move(layer_tree));
}
394

395 396
void Engine::UpdateSemantics(blink::SemanticsNodeUpdates update,
                             blink::CustomAccessibilityActionUpdates actions) {
397
  delegate_.OnEngineUpdateSemantics(std::move(update), std::move(actions));
398
}
399

400
void Engine::HandlePlatformMessage(
401
    fml::RefPtr<blink::PlatformMessage> message) {
402
  if (message->channel() == kAssetChannel) {
A
Adam Barth 已提交
403
    HandleAssetPlatformMessage(std::move(message));
404
  } else {
405
    delegate_.OnEngineHandlePlatformMessage(std::move(message));
A
Adam Barth 已提交
406
  }
407 408
}

409 410 411 412
blink::FontCollection& Engine::GetFontCollection() {
  return font_collection_;
}

A
Adam Barth 已提交
413
void Engine::HandleAssetPlatformMessage(
414 415
    fml::RefPtr<blink::PlatformMessage> message) {
  fml::RefPtr<blink::PlatformMessageResponse> response = message->response();
416
  if (!response) {
A
Adam Barth 已提交
417
    return;
418
  }
A
Adam Barth 已提交
419 420 421
  const auto& data = message->data();
  std::string asset_name(reinterpret_cast<const char*>(data.data()),
                         data.size());
422

423 424 425 426 427 428 429
  if (asset_manager_) {
    std::unique_ptr<fml::Mapping> asset_mapping =
        asset_manager_->GetAsMapping(asset_name);
    if (asset_mapping) {
      response->Complete(std::move(asset_mapping));
      return;
    }
A
Adam Barth 已提交
430
  }
431 432

  response->CompleteEmpty();
A
Adam Barth 已提交
433 434
}

435
}  // namespace shell