Flutter Engine
embedder_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #define FML_USED_ON_EMBEDDER
6 
7 #include <string>
8 #include <vector>
9 
10 #include "embedder.h"
11 #include "embedder_engine.h"
12 #include "flutter/flow/raster_cache.h"
13 #include "flutter/fml/file.h"
14 #include "flutter/fml/make_copyable.h"
15 #include "flutter/fml/mapping.h"
16 #include "flutter/fml/message_loop.h"
17 #include "flutter/fml/paths.h"
18 #include "flutter/fml/synchronization/count_down_latch.h"
19 #include "flutter/fml/synchronization/waitable_event.h"
20 #include "flutter/fml/thread.h"
21 #include "flutter/runtime/dart_vm.h"
22 #include "flutter/shell/platform/embedder/tests/embedder_assertions.h"
23 #include "flutter/shell/platform/embedder/tests/embedder_config_builder.h"
24 #include "flutter/shell/platform/embedder/tests/embedder_test.h"
25 #include "flutter/shell/platform/embedder/tests/embedder_unittests_util.h"
26 #include "flutter/testing/assertions_skia.h"
27 #include "flutter/testing/testing.h"
28 #include "third_party/skia/include/core/SkSurface.h"
30 
31 namespace flutter {
32 namespace testing {
33 
35 
36 TEST(EmbedderTestNoFixture, MustNotRunWithInvalidArgs) {
38  EmbedderConfigBuilder builder(
40  auto engine = builder.LaunchEngine();
41  ASSERT_FALSE(engine.is_valid());
42 }
43 
44 TEST_F(EmbedderTest, CanLaunchAndShutdownWithValidProjectArgs) {
45  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
47  context.AddIsolateCreateCallback([&latch]() { latch.Signal(); });
48  EmbedderConfigBuilder builder(context);
49  builder.SetSoftwareRendererConfig();
50  auto engine = builder.LaunchEngine();
51  ASSERT_TRUE(engine.is_valid());
52  // Wait for the root isolate to launch.
53  latch.Wait();
54  engine.reset();
55 }
56 
57 // TODO(41999): Disabled because flaky.
58 TEST_F(EmbedderTest, DISABLED_CanLaunchAndShutdownMultipleTimes) {
59  EmbedderConfigBuilder builder(
60  GetEmbedderContext(ContextType::kSoftwareContext));
61  builder.SetSoftwareRendererConfig();
62  for (size_t i = 0; i < 3; ++i) {
63  auto engine = builder.LaunchEngine();
64  ASSERT_TRUE(engine.is_valid());
65  FML_LOG(INFO) << "Engine launch count: " << i + 1;
66  }
67 }
68 
69 TEST_F(EmbedderTest, CanInvokeCustomEntrypoint) {
70  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
71  static fml::AutoResetWaitableEvent latch;
72  Dart_NativeFunction entrypoint = [](Dart_NativeArguments args) {
73  latch.Signal();
74  };
75  context.AddNativeCallback("SayHiFromCustomEntrypoint", entrypoint);
76  EmbedderConfigBuilder builder(context);
77  builder.SetSoftwareRendererConfig();
78  builder.SetDartEntrypoint("customEntrypoint");
79  auto engine = builder.LaunchEngine();
80  latch.Wait();
81  ASSERT_TRUE(engine.is_valid());
82 }
83 
84 TEST_F(EmbedderTest, CanInvokeCustomEntrypointMacro) {
85  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
86 
90 
91  // Can be defined separately.
92  auto entry1 = [&latch1](Dart_NativeArguments args) {
93  FML_LOG(INFO) << "In Callback 1";
94  latch1.Signal();
95  };
96  auto native_entry1 = CREATE_NATIVE_ENTRY(entry1);
97  context.AddNativeCallback("SayHiFromCustomEntrypoint1", native_entry1);
98 
99  // Can be wrapped in in the args.
100  auto entry2 = [&latch2](Dart_NativeArguments args) {
101  FML_LOG(INFO) << "In Callback 2";
102  latch2.Signal();
103  };
104  context.AddNativeCallback("SayHiFromCustomEntrypoint2",
105  CREATE_NATIVE_ENTRY(entry2));
106 
107  // Everything can be inline.
108  context.AddNativeCallback(
109  "SayHiFromCustomEntrypoint3",
110  CREATE_NATIVE_ENTRY([&latch3](Dart_NativeArguments args) {
111  FML_LOG(INFO) << "In Callback 3";
112  latch3.Signal();
113  }));
114 
115  EmbedderConfigBuilder builder(context);
116  builder.SetSoftwareRendererConfig();
117  builder.SetDartEntrypoint("customEntrypoint1");
118  auto engine = builder.LaunchEngine();
119  latch1.Wait();
120  latch2.Wait();
121  latch3.Wait();
122  ASSERT_TRUE(engine.is_valid());
123 }
124 
125 std::atomic_size_t EmbedderTestTaskRunner::sEmbedderTaskRunnerIdentifiers = {};
126 
127 TEST_F(EmbedderTest, CanSpecifyCustomPlatformTaskRunner) {
128  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
130 
131  // Run the test on its own thread with a message loop so that it can safely
132  // pump its event loop while we wait for all the conditions to be checked.
133  auto platform_task_runner = CreateNewThread("test_platform_thread");
134  static std::mutex engine_mutex;
135  static bool signaled_once = false;
137 
138  EmbedderTestTaskRunner test_task_runner(
139  platform_task_runner, [&](FlutterTask task) {
140  std::scoped_lock lock(engine_mutex);
141  if (!engine.is_valid()) {
142  return;
143  }
144  // There may be multiple tasks posted but we only need to check
145  // assertions once.
146  if (signaled_once) {
147  FlutterEngineRunTask(engine.get(), &task);
148  return;
149  }
150 
151  signaled_once = true;
152  ASSERT_TRUE(engine.is_valid());
153  ASSERT_EQ(FlutterEngineRunTask(engine.get(), &task), kSuccess);
154  latch.Signal();
155  });
156 
157  platform_task_runner->PostTask([&]() {
158  EmbedderConfigBuilder builder(context);
159  const auto task_runner_description =
160  test_task_runner.GetFlutterTaskRunnerDescription();
161  builder.SetSoftwareRendererConfig();
162  builder.SetPlatformTaskRunner(&task_runner_description);
163  builder.SetDartEntrypoint("invokePlatformTaskRunner");
164  std::scoped_lock lock(engine_mutex);
165  engine = builder.LaunchEngine();
166  ASSERT_TRUE(engine.is_valid());
167  });
168 
169  // Signaled when all the assertions are checked.
170  latch.Wait();
171  ASSERT_TRUE(engine.is_valid());
172 
173  // Since the engine was started on its own thread, it must be killed there as
174  // well.
175  fml::AutoResetWaitableEvent kill_latch;
176  platform_task_runner->PostTask(fml::MakeCopyable([&]() mutable {
177  std::scoped_lock lock(engine_mutex);
178  engine.reset();
179 
180  // There may still be pending tasks on the platform thread that were queued
181  // by the test_task_runner. Signal the latch after these tasks have been
182  // consumed.
183  platform_task_runner->PostTask([&kill_latch] { kill_latch.Signal(); });
184  }));
185  kill_latch.Wait();
186 
187  ASSERT_TRUE(signaled_once);
188  signaled_once = false;
189 }
190 
191 TEST(EmbedderTestNoFixture, CanGetCurrentTimeInNanoseconds) {
192  auto point1 = fml::TimePoint::FromEpochDelta(
194  auto point2 = fml::TimePoint::Now();
195 
196  ASSERT_LT((point2 - point1), fml::TimeDelta::FromMilliseconds(1));
197 }
198 
199 TEST_F(EmbedderTest, CanReloadSystemFonts) {
200  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
201  EmbedderConfigBuilder builder(context);
202  builder.SetSoftwareRendererConfig();
203  auto engine = builder.LaunchEngine();
204  ASSERT_TRUE(engine.is_valid());
205 
206  auto result = FlutterEngineReloadSystemFonts(engine.get());
207  ASSERT_EQ(result, kSuccess);
208 }
209 
210 TEST_F(EmbedderTest, IsolateServiceIdSent) {
211  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
213 
214  fml::Thread thread;
216  std::string isolate_message;
217 
218  thread.GetTaskRunner()->PostTask([&]() {
219  EmbedderConfigBuilder builder(context);
220  builder.SetSoftwareRendererConfig();
221  builder.SetDartEntrypoint("main");
223  [&](const FlutterPlatformMessage* message) {
224  if (strcmp(message->channel, "flutter/isolate") == 0) {
225  isolate_message = {reinterpret_cast<const char*>(message->message),
226  message->message_size};
227  latch.Signal();
228  }
229  });
230  engine = builder.LaunchEngine();
231  ASSERT_TRUE(engine.is_valid());
232  });
233 
234  // Wait for the isolate ID message and check its format.
235  latch.Wait();
236  ASSERT_EQ(isolate_message.find("isolates/"), 0ul);
237 
238  // Since the engine was started on its own thread, it must be killed there as
239  // well.
240  fml::AutoResetWaitableEvent kill_latch;
241  thread.GetTaskRunner()->PostTask(
242  fml::MakeCopyable([&engine, &kill_latch]() mutable {
243  engine.reset();
244  kill_latch.Signal();
245  }));
246  kill_latch.Wait();
247 }
248 
249 //------------------------------------------------------------------------------
250 /// Creates a platform message response callbacks, does NOT send them, and
251 /// immediately collects the same.
252 ///
253 TEST_F(EmbedderTest, CanCreateAndCollectCallbacks) {
254  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
255  EmbedderConfigBuilder builder(context);
256  builder.SetSoftwareRendererConfig();
257  builder.SetDartEntrypoint("platform_messages_response");
258  context.AddNativeCallback(
259  "SignalNativeTest",
260  CREATE_NATIVE_ENTRY([](Dart_NativeArguments args) {}));
261 
262  auto engine = builder.LaunchEngine();
263  ASSERT_TRUE(engine.is_valid());
264 
265  FlutterPlatformMessageResponseHandle* response_handle = nullptr;
266  auto callback = [](const uint8_t* data, size_t size,
267  void* user_data) -> void {};
269  engine.get(), callback, nullptr, &response_handle);
270  ASSERT_EQ(result, kSuccess);
271  ASSERT_NE(response_handle, nullptr);
272 
274  response_handle);
275  ASSERT_EQ(result, kSuccess);
276 }
277 
278 //------------------------------------------------------------------------------
279 /// Sends platform messages to Dart code than simply echoes the contents of the
280 /// message back to the embedder. The embedder registers a native callback to
281 /// intercept that message.
282 ///
283 TEST_F(EmbedderTest, PlatformMessagesCanReceiveResponse) {
284  struct Captures {
286  std::thread::id thread_id;
287  };
288  Captures captures;
289 
290  CreateNewThread()->PostTask([&]() {
291  captures.thread_id = std::this_thread::get_id();
292  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
293  EmbedderConfigBuilder builder(context);
294  builder.SetSoftwareRendererConfig();
295  builder.SetDartEntrypoint("platform_messages_response");
296 
298  context.AddNativeCallback(
299  "SignalNativeTest",
301  [&ready](Dart_NativeArguments args) { ready.Signal(); }));
302 
303  auto engine = builder.LaunchEngine();
304  ASSERT_TRUE(engine.is_valid());
305 
306  static std::string kMessageData = "Hello from embedder.";
307 
308  FlutterPlatformMessageResponseHandle* response_handle = nullptr;
309  auto callback = [](const uint8_t* data, size_t size,
310  void* user_data) -> void {
311  ASSERT_EQ(size, kMessageData.size());
312  ASSERT_EQ(strncmp(reinterpret_cast<const char*>(kMessageData.data()),
313  reinterpret_cast<const char*>(data), size),
314  0);
315  auto captures = reinterpret_cast<Captures*>(user_data);
316  ASSERT_EQ(captures->thread_id, std::this_thread::get_id());
317  captures->latch.Signal();
318  };
320  engine.get(), callback, &captures, &response_handle);
321  ASSERT_EQ(result, kSuccess);
322 
323  FlutterPlatformMessage message = {};
324  message.struct_size = sizeof(FlutterPlatformMessage);
325  message.channel = "test_channel";
326  message.message = reinterpret_cast<const uint8_t*>(kMessageData.data());
327  message.message_size = kMessageData.size();
328  message.response_handle = response_handle;
329 
330  ready.Wait();
331  result = FlutterEngineSendPlatformMessage(engine.get(), &message);
332  ASSERT_EQ(result, kSuccess);
333 
335  response_handle);
336  ASSERT_EQ(result, kSuccess);
337  });
338 
339  captures.latch.Wait();
340 }
341 
342 //------------------------------------------------------------------------------
343 /// Tests that a platform message can be sent with no response handle. Instead
344 /// of the platform message integrity checked via a response handle, a native
345 /// callback with the response is invoked to assert integrity.
346 ///
347 TEST_F(EmbedderTest, PlatformMessagesCanBeSentWithoutResponseHandles) {
348  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
349  EmbedderConfigBuilder builder(context);
350  builder.SetSoftwareRendererConfig();
351  builder.SetDartEntrypoint("platform_messages_no_response");
352 
353  const std::string message_data = "Hello but don't call me back.";
354 
355  fml::AutoResetWaitableEvent ready, message;
356  context.AddNativeCallback(
357  "SignalNativeTest",
359  [&ready](Dart_NativeArguments args) { ready.Signal(); }));
360  context.AddNativeCallback(
361  "SignalNativeMessage",
363  ([&message, &message_data](Dart_NativeArguments args) {
364  auto received_message = tonic::DartConverter<std::string>::FromDart(
365  Dart_GetNativeArgument(args, 0));
366  ASSERT_EQ(received_message, message_data);
367  message.Signal();
368  })));
369 
370  auto engine = builder.LaunchEngine();
371 
372  ASSERT_TRUE(engine.is_valid());
373  ready.Wait();
374 
375  FlutterPlatformMessage platform_message = {};
376  platform_message.struct_size = sizeof(FlutterPlatformMessage);
377  platform_message.channel = "test_channel";
378  platform_message.message =
379  reinterpret_cast<const uint8_t*>(message_data.data());
380  platform_message.message_size = message_data.size();
381  platform_message.response_handle = nullptr; // No response needed.
382 
383  auto result =
384  FlutterEngineSendPlatformMessage(engine.get(), &platform_message);
385  ASSERT_EQ(result, kSuccess);
386  message.Wait();
387 }
388 
389 //------------------------------------------------------------------------------
390 /// Tests that a null platform message can be sent.
391 ///
392 TEST_F(EmbedderTest, NullPlatformMessagesCanBeSent) {
393  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
394  EmbedderConfigBuilder builder(context);
395  builder.SetSoftwareRendererConfig();
396  builder.SetDartEntrypoint("null_platform_messages");
397 
398  fml::AutoResetWaitableEvent ready, message;
399  context.AddNativeCallback(
400  "SignalNativeTest",
402  [&ready](Dart_NativeArguments args) { ready.Signal(); }));
403  context.AddNativeCallback(
404  "SignalNativeMessage",
405  CREATE_NATIVE_ENTRY(([&message](Dart_NativeArguments args) {
406  auto received_message = tonic::DartConverter<std::string>::FromDart(
407  Dart_GetNativeArgument(args, 0));
408  ASSERT_EQ("true", received_message);
409  message.Signal();
410  })));
411 
412  auto engine = builder.LaunchEngine();
413 
414  ASSERT_TRUE(engine.is_valid());
415  ready.Wait();
416 
417  FlutterPlatformMessage platform_message = {};
418  platform_message.struct_size = sizeof(FlutterPlatformMessage);
419  platform_message.channel = "test_channel";
420  platform_message.message = nullptr;
421  platform_message.message_size = 0;
422  platform_message.response_handle = nullptr; // No response needed.
423 
424  auto result =
425  FlutterEngineSendPlatformMessage(engine.get(), &platform_message);
426  ASSERT_EQ(result, kSuccess);
427  message.Wait();
428 }
429 
430 //------------------------------------------------------------------------------
431 /// Tests that a null platform message cannot be send if the message_size
432 /// isn't equals to 0.
433 ///
434 TEST_F(EmbedderTest, InvalidPlatformMessages) {
435  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
436  EmbedderConfigBuilder builder(context);
437  builder.SetSoftwareRendererConfig();
438  auto engine = builder.LaunchEngine();
439 
440  ASSERT_TRUE(engine.is_valid());
441 
442  FlutterPlatformMessage platform_message = {};
443  platform_message.struct_size = sizeof(FlutterPlatformMessage);
444  platform_message.channel = "test_channel";
445  platform_message.message = nullptr;
446  platform_message.message_size = 1;
447  platform_message.response_handle = nullptr; // No response needed.
448 
449  auto result =
450  FlutterEngineSendPlatformMessage(engine.get(), &platform_message);
451  ASSERT_EQ(result, kInvalidArguments);
452 }
453 
454 //------------------------------------------------------------------------------
455 /// Asserts behavior of FlutterProjectArgs::shutdown_dart_vm_when_done (which is
456 /// set to true by default in these unit-tests).
457 ///
458 TEST_F(EmbedderTest, VMShutsDownWhenNoEnginesInProcess) {
459  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
460  EmbedderConfigBuilder builder(context);
461  builder.SetSoftwareRendererConfig();
462  const auto launch_count = DartVM::GetVMLaunchCount();
463 
464  {
465  auto engine = builder.LaunchEngine();
466  ASSERT_EQ(launch_count + 1u, DartVM::GetVMLaunchCount());
467  }
468 
469  {
470  auto engine = builder.LaunchEngine();
471  ASSERT_EQ(launch_count + 2u, DartVM::GetVMLaunchCount());
472  }
473 }
474 
475 //------------------------------------------------------------------------------
476 ///
477 TEST_F(EmbedderTest, DartEntrypointArgs) {
478  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
479  EmbedderConfigBuilder builder(context);
480  builder.SetSoftwareRendererConfig();
481  builder.AddDartEntrypointArgument("foo");
482  builder.AddDartEntrypointArgument("bar");
483  builder.SetDartEntrypoint("dart_entrypoint_args");
484  fml::AutoResetWaitableEvent callback_latch;
485  std::vector<std::string> callback_args;
486  auto nativeArgumentsCallback = [&callback_args,
487  &callback_latch](Dart_NativeArguments args) {
488  Dart_Handle exception = nullptr;
489  callback_args =
491  args, 0, exception);
492  callback_latch.Signal();
493  };
494  context.AddNativeCallback("NativeArgumentsCallback",
495  CREATE_NATIVE_ENTRY(nativeArgumentsCallback));
496  auto engine = builder.LaunchEngine();
497  callback_latch.Wait();
498  ASSERT_EQ(callback_args[0], "foo");
499  ASSERT_EQ(callback_args[1], "bar");
500 }
501 
502 //------------------------------------------------------------------------------
503 /// These snapshots may be materialized from symbols and the size field may not
504 /// be relevant. Since this information is redundant, engine launch should not
505 /// be gated on a non-zero buffer size.
506 ///
507 TEST_F(EmbedderTest, VMAndIsolateSnapshotSizesAreRedundantInAOTMode) {
509  GTEST_SKIP();
510  return;
511  }
512  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
513  EmbedderConfigBuilder builder(context);
514  builder.SetSoftwareRendererConfig();
515 
516  // The fixture sets this up correctly. Intentionally mess up the args.
521 
522  auto engine = builder.LaunchEngine();
523  ASSERT_TRUE(engine.is_valid());
524 }
525 
526 //------------------------------------------------------------------------------
527 /// Test the layer structure and pixels rendered when using a custom software
528 /// compositor.
529 ///
531  CompositorMustBeAbleToRenderKnownSceneWithSoftwareCompositor) {
532  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
533 
534  EmbedderConfigBuilder builder(context);
535  builder.SetSoftwareRendererConfig(SkISize::Make(800, 600));
536  builder.SetCompositor();
537  builder.SetDartEntrypoint("can_composite_platform_views_with_known_scene");
538 
539  builder.SetRenderTargetType(
541 
542  fml::CountDownLatch latch(5);
543 
544  auto scene_image = context.GetNextSceneImage();
545 
546  context.GetCompositor().SetNextPresentCallback(
547  [&](const FlutterLayer** layers, size_t layers_count) {
548  ASSERT_EQ(layers_count, 5u);
549 
550  // Layer Root
551  {
552  FlutterBackingStore backing_store = *layers[0]->backing_store;
553  backing_store.type = kFlutterBackingStoreTypeSoftware;
554  backing_store.did_update = true;
555  backing_store.software.height = 600;
556 
557  FlutterLayer layer = {};
558  layer.struct_size = sizeof(layer);
560  layer.backing_store = &backing_store;
561  layer.size = FlutterSizeMake(800.0, 600.0);
562  layer.offset = FlutterPointMake(0.0, 0.0);
563 
564  ASSERT_EQ(*layers[0], layer);
565  }
566 
567  // Layer 1
568  {
569  FlutterPlatformView platform_view = *layers[1]->platform_view;
570  platform_view.struct_size = sizeof(platform_view);
571  platform_view.identifier = 1;
572 
573  FlutterLayer layer = {};
574  layer.struct_size = sizeof(layer);
576  layer.platform_view = &platform_view;
577  layer.size = FlutterSizeMake(50.0, 150.0);
578  layer.offset = FlutterPointMake(20.0, 20.0);
579 
580  ASSERT_EQ(*layers[1], layer);
581  }
582 
583  // Layer 2
584  {
585  FlutterBackingStore backing_store = *layers[2]->backing_store;
586  backing_store.type = kFlutterBackingStoreTypeSoftware;
587  backing_store.did_update = true;
588  backing_store.software.height = 600;
589 
590  FlutterLayer layer = {};
591  layer.struct_size = sizeof(layer);
593  layer.backing_store = &backing_store;
594  layer.size = FlutterSizeMake(800.0, 600.0);
595  layer.offset = FlutterPointMake(0.0, 0.0);
596 
597  ASSERT_EQ(*layers[2], layer);
598  }
599 
600  // Layer 3
601  {
602  FlutterPlatformView platform_view = *layers[3]->platform_view;
603  platform_view.struct_size = sizeof(platform_view);
604  platform_view.identifier = 2;
605 
606  FlutterLayer layer = {};
607  layer.struct_size = sizeof(layer);
609  layer.platform_view = &platform_view;
610  layer.size = FlutterSizeMake(50.0, 150.0);
611  layer.offset = FlutterPointMake(40.0, 40.0);
612 
613  ASSERT_EQ(*layers[3], layer);
614  }
615 
616  // Layer 4
617  {
618  FlutterBackingStore backing_store = *layers[4]->backing_store;
619  backing_store.type = kFlutterBackingStoreTypeSoftware;
620  backing_store.did_update = true;
621  backing_store.software.height = 600;
622 
623  FlutterLayer layer = {};
624  layer.struct_size = sizeof(layer);
626  layer.backing_store = &backing_store;
627  layer.size = FlutterSizeMake(800.0, 600.0);
628  layer.offset = FlutterPointMake(0.0, 0.0);
629 
630  ASSERT_EQ(*layers[4], layer);
631  }
632 
633  latch.CountDown();
634  });
635 
636  context.GetCompositor().SetPlatformViewRendererCallback(
637  [&](const FlutterLayer& layer, GrDirectContext*
638  /* don't use because software compositor */) -> sk_sp<SkImage> {
639  auto surface = CreateRenderSurface(
640  layer, nullptr /* null because software compositor */);
641  auto canvas = surface->getCanvas();
642  FML_CHECK(canvas != nullptr);
643 
644  switch (layer.platform_view->identifier) {
645  case 1: {
646  SkPaint paint;
647  // See dart test for total order.
648  paint.setColor(SK_ColorGREEN);
649  paint.setAlpha(127);
650  const auto& rect =
651  SkRect::MakeWH(layer.size.width, layer.size.height);
652  canvas->drawRect(rect, paint);
653  latch.CountDown();
654  } break;
655  case 2: {
656  SkPaint paint;
657  // See dart test for total order.
658  paint.setColor(SK_ColorMAGENTA);
659  paint.setAlpha(127);
660  const auto& rect =
661  SkRect::MakeWH(layer.size.width, layer.size.height);
662  canvas->drawRect(rect, paint);
663  latch.CountDown();
664  } break;
665  default:
666  // Asked to render an unknown platform view.
667  FML_CHECK(false)
668  << "Test was asked to composite an unknown platform view.";
669  }
670 
671  return surface->makeImageSnapshot();
672  });
673 
674  context.AddNativeCallback(
675  "SignalNativeTest",
677  [&latch](Dart_NativeArguments args) { latch.CountDown(); }));
678 
679  auto engine = builder.LaunchEngine();
680 
681  // Send a window metrics events so frames may be scheduled.
682  FlutterWindowMetricsEvent event = {};
683  event.struct_size = sizeof(event);
684  event.width = 800;
685  event.height = 600;
686  event.pixel_ratio = 1.0;
688  kSuccess);
689  ASSERT_TRUE(engine.is_valid());
690 
691  latch.Wait();
692 
693  ASSERT_TRUE(ImageMatchesFixture("compositor_software.png", scene_image));
694 
695  // There should no present calls on the root surface.
696  ASSERT_EQ(context.GetSurfacePresentCount(), 0u);
697 }
698 
699 //------------------------------------------------------------------------------
700 /// Test that an engine can be initialized but not run.
701 ///
702 TEST_F(EmbedderTest, CanCreateInitializedEngine) {
703  EmbedderConfigBuilder builder(
704  GetEmbedderContext(ContextType::kSoftwareContext));
705  builder.SetSoftwareRendererConfig();
706  auto engine = builder.InitializeEngine();
707  ASSERT_TRUE(engine.is_valid());
708  engine.reset();
709 }
710 
711 //------------------------------------------------------------------------------
712 /// Test that an initialized engine can be run exactly once.
713 ///
714 TEST_F(EmbedderTest, CanRunInitializedEngine) {
715  EmbedderConfigBuilder builder(
716  GetEmbedderContext(ContextType::kSoftwareContext));
717  builder.SetSoftwareRendererConfig();
718  auto engine = builder.InitializeEngine();
719  ASSERT_TRUE(engine.is_valid());
720  ASSERT_EQ(FlutterEngineRunInitialized(engine.get()), kSuccess);
721  // Cannot re-run an already running engine.
723  engine.reset();
724 }
725 
726 //------------------------------------------------------------------------------
727 /// Test that an engine can be deinitialized.
728 ///
729 TEST_F(EmbedderTest, CaDeinitializeAnEngine) {
730  EmbedderConfigBuilder builder(
731  GetEmbedderContext(ContextType::kSoftwareContext));
732  builder.SetSoftwareRendererConfig();
733  auto engine = builder.InitializeEngine();
734  ASSERT_TRUE(engine.is_valid());
735  ASSERT_EQ(FlutterEngineRunInitialized(engine.get()), kSuccess);
736  // Cannot re-run an already running engine.
738  ASSERT_EQ(FlutterEngineDeinitialize(engine.get()), kSuccess);
739  // It is ok to deinitialize an engine multiple times.
740  ASSERT_EQ(FlutterEngineDeinitialize(engine.get()), kSuccess);
741 
742  // Sending events to a deinitalized engine fails.
743  FlutterWindowMetricsEvent event = {};
744  event.struct_size = sizeof(event);
745  event.width = 800;
746  event.height = 600;
747  event.pixel_ratio = 1.0;
750  engine.reset();
751 }
752 
753 TEST_F(EmbedderTest, CanUpdateLocales) {
754  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
755  EmbedderConfigBuilder builder(context);
756  builder.SetSoftwareRendererConfig();
757  builder.SetDartEntrypoint("can_receive_locale_updates");
759  context.AddNativeCallback(
760  "SignalNativeTest",
762  [&latch](Dart_NativeArguments args) { latch.Signal(); }));
763 
764  fml::AutoResetWaitableEvent check_latch;
765  context.AddNativeCallback(
766  "SignalNativeCount",
767  CREATE_NATIVE_ENTRY([&check_latch](Dart_NativeArguments args) {
769  Dart_GetNativeArgument(args, 0)),
770  2);
771  check_latch.Signal();
772  }));
773 
774  auto engine = builder.LaunchEngine();
775  ASSERT_TRUE(engine.is_valid());
776 
777  // Wait for the application to attach the listener.
778  latch.Wait();
779 
780  FlutterLocale locale1 = {};
781  locale1.struct_size = sizeof(locale1);
782  locale1.language_code = ""; // invalid
783  locale1.country_code = "US";
784  locale1.script_code = "";
785  locale1.variant_code = nullptr;
786 
787  FlutterLocale locale2 = {};
788  locale2.struct_size = sizeof(locale2);
789  locale2.language_code = "zh";
790  locale2.country_code = "CN";
791  locale2.script_code = "Hans";
792  locale2.variant_code = nullptr;
793 
794  std::vector<const FlutterLocale*> locales;
795  locales.push_back(&locale1);
796  locales.push_back(&locale2);
797 
798  ASSERT_EQ(
799  FlutterEngineUpdateLocales(engine.get(), locales.data(), locales.size()),
801 
802  // Fix the invalid code.
803  locale1.language_code = "en";
804 
805  ASSERT_EQ(
806  FlutterEngineUpdateLocales(engine.get(), locales.data(), locales.size()),
807  kSuccess);
808 
809  check_latch.Wait();
810 }
811 
812 TEST_F(EmbedderTest, LocalizationCallbacksCalled) {
813  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
815  context.AddIsolateCreateCallback([&latch]() { latch.Signal(); });
816  EmbedderConfigBuilder builder(context);
817  builder.SetSoftwareRendererConfig();
818  auto engine = builder.LaunchEngine();
819  ASSERT_TRUE(engine.is_valid());
820  // Wait for the root isolate to launch.
821  latch.Wait();
822 
823  flutter::Shell& shell = ToEmbedderEngine(engine.get())->GetShell();
824  std::vector<std::string> supported_locales;
825  supported_locales.push_back("es");
826  supported_locales.push_back("MX");
827  supported_locales.push_back("");
828  auto result = shell.GetPlatformView()->ComputePlatformResolvedLocales(
829  supported_locales);
830 
831  ASSERT_EQ((*result).size(), supported_locales.size()); // 3
832  ASSERT_EQ((*result)[0], supported_locales[0]);
833  ASSERT_EQ((*result)[1], supported_locales[1]);
834  ASSERT_EQ((*result)[2], supported_locales[2]);
835 
836  engine.reset();
837 }
838 
839 TEST_F(EmbedderTest, CanQueryDartAOTMode) {
842 }
843 
844 TEST_F(EmbedderTest, VerifyB143464703WithSoftwareBackend) {
845  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
846 
847  EmbedderConfigBuilder builder(context);
848  builder.SetSoftwareRendererConfig(SkISize::Make(1024, 600));
849  builder.SetCompositor();
850  builder.SetDartEntrypoint("verify_b143464703");
851 
852  builder.SetRenderTargetType(
854 
855  fml::CountDownLatch latch(1);
856  context.GetCompositor().SetNextPresentCallback(
857  [&](const FlutterLayer** layers, size_t layers_count) {
858  ASSERT_EQ(layers_count, 3u);
859 
860  // Layer 0 (Root)
861  {
862  FlutterBackingStore backing_store = *layers[0]->backing_store;
863  backing_store.type = kFlutterBackingStoreTypeSoftware;
864  backing_store.did_update = true;
865 
866  FlutterLayer layer = {};
867  layer.struct_size = sizeof(layer);
869  layer.backing_store = &backing_store;
870  layer.size = FlutterSizeMake(1024.0, 600.0);
871  layer.offset = FlutterPointMake(0.0, 0.0);
872 
873  ASSERT_EQ(*layers[0], layer);
874  }
875 
876  // Layer 1
877  {
878  FlutterPlatformView platform_view = *layers[1]->platform_view;
879  platform_view.struct_size = sizeof(platform_view);
880  platform_view.identifier = 42;
881 
882  FlutterLayer layer = {};
883  layer.struct_size = sizeof(layer);
885  layer.platform_view = &platform_view;
886  layer.size = FlutterSizeMake(1024.0, 540.0);
887  layer.offset = FlutterPointMake(135.0, 60.0);
888 
889  ASSERT_EQ(*layers[1], layer);
890  }
891 
892  // Layer 2
893  {
894  FlutterBackingStore backing_store = *layers[2]->backing_store;
895  backing_store.type = kFlutterBackingStoreTypeSoftware;
896  backing_store.did_update = true;
897 
898  FlutterLayer layer = {};
899  layer.struct_size = sizeof(layer);
901  layer.backing_store = &backing_store;
902  layer.size = FlutterSizeMake(1024.0, 600.0);
903  layer.offset = FlutterPointMake(0.0, 0.0);
904 
905  ASSERT_EQ(*layers[2], layer);
906  }
907 
908  latch.CountDown();
909  });
910 
911  context.GetCompositor().SetPlatformViewRendererCallback(
912  [](const FlutterLayer& layer,
913  GrDirectContext* context) -> sk_sp<SkImage> {
914  auto surface = CreateRenderSurface(
915  layer, nullptr /* null because software compositor */);
916  auto canvas = surface->getCanvas();
917  FML_CHECK(canvas != nullptr);
918 
919  switch (layer.platform_view->identifier) {
920  case 42: {
921  SkPaint paint;
922  // See dart test for total order.
923  paint.setColor(SK_ColorGREEN);
924  paint.setAlpha(127);
925  const auto& rect =
926  SkRect::MakeWH(layer.size.width, layer.size.height);
927  canvas->drawRect(rect, paint);
928  } break;
929  default:
930  // Asked to render an unknown platform view.
931  FML_CHECK(false)
932  << "Test was asked to composite an unknown platform view.";
933  }
934 
935  return surface->makeImageSnapshot();
936  });
937 
938  auto engine = builder.LaunchEngine();
939 
940  // Send a window metrics events so frames may be scheduled.
941  FlutterWindowMetricsEvent event = {};
942  event.struct_size = sizeof(event);
943  event.width = 1024;
944  event.height = 600;
945  event.pixel_ratio = 1.0;
947  kSuccess);
948  ASSERT_TRUE(engine.is_valid());
949 
950  auto renderered_scene = context.GetNextSceneImage();
951 
952  latch.Wait();
953 
954  // TODO(https://github.com/flutter/flutter/issues/53784): enable this on all
955  // platforms.
956 #if !defined(OS_LINUX)
957  GTEST_SKIP() << "Skipping golden tests on non-Linux OSes";
958 #endif // OS_LINUX
959  ASSERT_TRUE(ImageMatchesFixture("verifyb143464703_soft_noxform.png",
960  renderered_scene));
961 }
962 
963 TEST_F(EmbedderTest, CanSendLowMemoryNotification) {
964  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
965 
966  EmbedderConfigBuilder builder(context);
967  builder.SetSoftwareRendererConfig();
968 
969  auto engine = builder.LaunchEngine();
970 
971  ASSERT_TRUE(engine.is_valid());
972 
973  // TODO(chinmaygarde): The shell ought to have a mechanism for notification
974  // dispatch that engine subsystems can register handlers to. This would allow
975  // the raster cache and the secondary context caches to respond to
976  // notifications. Once that is in place, this test can be updated to actually
977  // ensure that the dispatched message is visible to engine subsystems.
979 }
980 
981 TEST_F(EmbedderTest, CanPostTaskToAllNativeThreads) {
983  size_t worker_count = 0;
984  fml::AutoResetWaitableEvent sync_latch;
985 
986  // One of the threads that the callback will be posted to is the platform
987  // thread. So we cannot wait for assertions to complete on the platform
988  // thread. Create a new thread to manage the engine instance and wait for
989  // assertions on the test thread.
990  auto platform_task_runner = CreateNewThread("platform_thread");
991 
992  platform_task_runner->PostTask([&]() {
993  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
994 
995  EmbedderConfigBuilder builder(context);
996  builder.SetSoftwareRendererConfig();
997 
998  engine = builder.LaunchEngine();
999 
1000  ASSERT_TRUE(engine.is_valid());
1001 
1002  worker_count = ToEmbedderEngine(engine.get())
1003  ->GetShell()
1004  .GetDartVM()
1005  ->GetConcurrentMessageLoop()
1006  ->GetWorkerCount();
1007 
1008  sync_latch.Signal();
1009  });
1010 
1011  sync_latch.Wait();
1012 
1013  const auto engine_threads_count = worker_count + 4u;
1014 
1015  struct Captures {
1016  // Waits the adequate number of callbacks to fire.
1017  fml::CountDownLatch latch;
1018 
1019  // This class will be accessed from multiple threads concurrently to track
1020  // thread specific information that is later checked. All updates to fields
1021  // in this struct must be made with this mutex acquired.
1022 
1023  std::mutex captures_mutex;
1024  // Ensures that the expect number of distinct threads were serviced.
1025  std::set<std::thread::id> thread_ids;
1026 
1027  size_t platform_threads_count = 0;
1028  size_t render_threads_count = 0;
1029  size_t ui_threads_count = 0;
1030  size_t worker_threads_count = 0;
1031 
1032  Captures(size_t count) : latch(count) {}
1033  };
1034 
1035  Captures captures(engine_threads_count);
1036 
1037  platform_task_runner->PostTask([&]() {
1039  engine.get(),
1040  [](FlutterNativeThreadType type, void* baton) {
1041  auto captures = reinterpret_cast<Captures*>(baton);
1042  {
1043  std::scoped_lock lock(captures->captures_mutex);
1044  switch (type) {
1046  captures->render_threads_count++;
1047  break;
1049  captures->worker_threads_count++;
1050  break;
1052  captures->ui_threads_count++;
1053  break;
1055  captures->platform_threads_count++;
1056  break;
1057  }
1058  captures->thread_ids.insert(std::this_thread::get_id());
1059  }
1060  captures->latch.CountDown();
1061  },
1062  &captures),
1063  kSuccess);
1064  });
1065 
1066  captures.latch.Wait();
1067  ASSERT_EQ(captures.thread_ids.size(), engine_threads_count);
1068  ASSERT_EQ(captures.platform_threads_count, 1u);
1069  ASSERT_EQ(captures.render_threads_count, 1u);
1070  ASSERT_EQ(captures.ui_threads_count, 1u);
1071  ASSERT_EQ(captures.worker_threads_count, worker_count + 1u /* for IO */);
1072 
1073  platform_task_runner->PostTask([&]() {
1074  engine.reset();
1075  sync_latch.Signal();
1076  });
1077  sync_latch.Wait();
1078 
1079  // The engine should have already been destroyed on the platform task runner.
1080  ASSERT_FALSE(engine.is_valid());
1081 }
1082 
1083 TEST_F(EmbedderTest, InvalidAOTDataSourcesMustReturnError) {
1085  GTEST_SKIP();
1086  return;
1087  }
1088  FlutterEngineAOTDataSource data_in = {};
1089  FlutterEngineAOTData data_out = nullptr;
1090 
1091  // Null source specified.
1092  ASSERT_EQ(FlutterEngineCreateAOTData(nullptr, &data_out), kInvalidArguments);
1093  ASSERT_EQ(data_out, nullptr);
1094 
1095  // Null data_out specified.
1096  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, nullptr), kInvalidArguments);
1097 
1098  // Invalid FlutterEngineAOTDataSourceType type specified.
1099  data_in.type = FlutterEngineAOTDataSourceType(-1);
1100  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, &data_out), kInvalidArguments);
1101  ASSERT_EQ(data_out, nullptr);
1102 
1103  // Invalid ELF path specified.
1105  data_in.elf_path = nullptr;
1106  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, &data_out), kInvalidArguments);
1107  ASSERT_EQ(data_in.type, kFlutterEngineAOTDataSourceTypeElfPath);
1108  ASSERT_EQ(data_in.elf_path, nullptr);
1109  ASSERT_EQ(data_out, nullptr);
1110 
1111  // Invalid ELF path specified.
1112  data_in.elf_path = "";
1113  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, &data_out), kInvalidArguments);
1114  ASSERT_EQ(data_in.type, kFlutterEngineAOTDataSourceTypeElfPath);
1115  ASSERT_EQ(data_in.elf_path, "");
1116  ASSERT_EQ(data_out, nullptr);
1117 
1118  // Could not find VM snapshot data.
1119  data_in.elf_path = "/bin/true";
1120  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, &data_out), kInvalidArguments);
1121  ASSERT_EQ(data_in.type, kFlutterEngineAOTDataSourceTypeElfPath);
1122  ASSERT_EQ(data_in.elf_path, "/bin/true");
1123  ASSERT_EQ(data_out, nullptr);
1124 }
1125 
1126 TEST_F(EmbedderTest, MustNotRunWithMultipleAOTSources) {
1128  GTEST_SKIP();
1129  return;
1130  }
1131  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
1132 
1133  EmbedderConfigBuilder builder(
1134  context,
1136 
1137  builder.SetSoftwareRendererConfig();
1138 
1139  auto engine = builder.LaunchEngine();
1140  ASSERT_FALSE(engine.is_valid());
1141 }
1142 
1143 TEST_F(EmbedderTest, CanCreateAndCollectAValidElfSource) {
1145  GTEST_SKIP();
1146  return;
1147  }
1148  FlutterEngineAOTDataSource data_in = {};
1149  FlutterEngineAOTData data_out = nullptr;
1150 
1151  // Collecting a null object should be allowed
1152  ASSERT_EQ(FlutterEngineCollectAOTData(data_out), kSuccess);
1153 
1154  const auto elf_path =
1156 
1158  data_in.elf_path = elf_path.c_str();
1159 
1160  ASSERT_EQ(FlutterEngineCreateAOTData(&data_in, &data_out), kSuccess);
1161  ASSERT_EQ(data_in.type, kFlutterEngineAOTDataSourceTypeElfPath);
1162  ASSERT_EQ(data_in.elf_path, elf_path.c_str());
1163  ASSERT_NE(data_out, nullptr);
1164 
1165  ASSERT_EQ(FlutterEngineCollectAOTData(data_out), kSuccess);
1166 }
1167 
1168 TEST_F(EmbedderTest, CanLaunchAndShutdownWithAValidElfSource) {
1170  GTEST_SKIP();
1171  return;
1172  }
1173  auto& context = GetEmbedderContext(ContextType::kSoftwareContext);
1174 
1176  context.AddIsolateCreateCallback([&latch]() { latch.Signal(); });
1177 
1178  EmbedderConfigBuilder builder(
1179  context,
1181 
1182  builder.SetSoftwareRendererConfig();
1183 
1184  auto engine = builder.LaunchEngine();
1185  ASSERT_TRUE(engine.is_valid());
1186 
1187  // Wait for the root isolate to launch.
1188  latch.Wait();
1189  engine.reset();
1190 }
1191 
1192 } // namespace testing
1193 } // namespace flutter
size_t struct_size
This size of this struct. Must be sizeof(FlutterLocale).
Definition: embedder.h:940
Specified an software allocation for Flutter to render into using the CPU.
Definition: embedder.h:842
const char * channel
Definition: embedder.h:563
FLUTTER_EXPORT FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Stops running the Flutter engine instance. After this call, the embedder is also guaranteed that no m...
Definition: embedder.cc:1206
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition: embedder.cc:1483
static constexpr TimeDelta FromNanoseconds(int64_t nanos)
Definition: time_delta.h:40
FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterTask *task)
Inform the engine to run the specified task. This task has been given to the engine via the FlutterTa...
Definition: embedder.cc:1717
FlutterEngineAOTDataSourceType
AOT data source type.
Definition: embedder.h:1115
const FlutterBackingStore * backing_store
Definition: embedder.h:889
const FlutterPlatformMessageResponseHandle * response_handle
Definition: embedder.h:572
size_t vm_snapshot_instructions_size
Definition: embedder.h:1234
FlutterPlatformViewIdentifier identifier
Definition: embedder.h:818
FlutterSize size
The size of the layer (in physical pixels).
Definition: embedder.h:898
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: thread.cc:45
void reset(const T &value=Traits::InvalidValue())
Definition: unique_object.h:62
sk_sp< SkSurface > CreateRenderSurface(const FlutterLayer &layer, GrDirectContext *context)
FlutterSize FlutterSizeMake(double width, double height)
const char * variant_code
Definition: embedder.h:959
virtual void PostTask(const fml::closure &task)
Definition: task_runner.cc:24
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
A task runner that we expect the embedder to provide but whose implementation is a real FML task runn...
#define FML_LOG(severity)
Definition: logging.h:65
static constexpr TimePoint FromEpochDelta(TimeDelta ticks)
Definition: time_point.h:36
FlutterPoint offset
Definition: embedder.h:896
void SetPlatformMessageCallback(const std::function< void(const FlutterPlatformMessage *)> &callback)
const T & get() const
Definition: unique_object.h:87
FlutterEngineResult FlutterEngineNotifyLowMemoryWarning(FLUTTER_API_SYMBOL(FlutterEngine) raw_engine)
Posts a low memory notification to a running engine instance. The engine will do its best to release ...
Definition: embedder.cc:1950
bool is_valid() const
Definition: unique_object.h:89
const char * script_code
Definition: embedder.h:954
const char * country_code
Definition: embedder.h:949
FlutterEngineResult FlutterEngineReloadSystemFonts(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Reloads the system fonts in engine.
Definition: embedder.cc:1662
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
std::string JoinPaths(std::initializer_list< std::string > components)
Definition: paths.cc:14
Indicates that the contents of this layer are determined by the embedder.
Definition: embedder.h:877
FlutterSoftwareBackingStore software
The description of the software backing store.
Definition: embedder.h:861
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition: embedder.cc:651
const uint8_t * message
Definition: embedder.h:564
FlutterPoint FlutterPointMake(double x, double y)
#define CREATE_NATIVE_ENTRY(native_entry)
const FlutterPlatformView * platform_view
Definition: embedder.h:892
FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterLocale **locales, size_t locales_count)
Notify a running engine instance that the locale has been updated. The preferred locale must be the f...
Definition: embedder.cc:1761
FlutterLayerContentType type
Definition: embedder.h:885
const char * GetFixturesPath()
Returns the directory containing the test fixture for the target if this target has fixtures configur...
void SetPlatformTaskRunner(const FlutterTaskRunnerDescription *runner)
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:199
double width
Definition: embedder.h:311
flutter::EmbedderEngine * ToEmbedderEngine(const FlutterEngine &engine)
testing::EmbedderTest EmbedderTest
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition: embedder.h:457
G_BEGIN_DECLS FlMethodCall gpointer user_data
GdkEventButton * event
Definition: fl_view.cc:62
FlutterEngineResult FlutterEnginePostCallbackOnAllNativeThreads(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterNativeThreadCallback callback, void *user_data)
Schedule a callback to be run on all engine managed threads. The engine will attempt to service this ...
Definition: embedder.cc:1973
size_t height
The number of rows in the allocation.
Definition: embedder.h:776
fml::WeakPtr< PlatformView > GetPlatformView()
Platform views may only be accessed on the platform task runner.
Definition: shell.cc:597
size_t isolate_snapshot_instructions_size
Definition: embedder.h:1250
FlutterBackingStoreType type
Specifies the type of backing store.
Definition: embedder.h:853
static size_t GetVMLaunchCount()
The number of times the VM has been launched in the process. This call is inherently racy because the...
Definition: dart_vm.cc:261
#define FML_CHECK(condition)
Definition: logging.h:68
static constexpr TimeDelta FromMilliseconds(int64_t millis)
Definition: time_delta.h:46
double height
Definition: embedder.h:312
FlutterNativeThreadType
Definition: embedder.h:1092
FlutterEngineAOTDataSourceType type
Definition: embedder.h:1122
size_t isolate_snapshot_data_size
Definition: embedder.h:1242
int32_t id
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformView).
Definition: embedder.h:814
bool ImageMatchesFixture(const std::string &fixture_file_name, sk_sp< SkImage > scene_image)
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition: embedder.h:562
constexpr const char * kAOTAppELFFileName
Definition: elf_loader.h:17
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition: embedder.cc:1229
const char * language_code
Definition: embedder.h:944
FlutterEngineResult FlutterEngineRunInitialized(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Runs an initialized engine instance. An engine can be initialized via FlutterEngineInitialize. An initialized instance can only be run once. During and after this call, custom task runners supplied by the embedder are expected to start servicing tasks.
Definition: embedder.cc:1167
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition: embedder.cc:1821
size_t vm_snapshot_data_size
Definition: embedder.h:1226
const char * elf_path
Absolute path to an ELF library file.
Definition: embedder.h:1125
uint64_t FlutterEngineGetCurrentTime()
Get the current time in nanoseconds from the clock used by the flutter engine. This is the system mon...
Definition: embedder.cc:1713
size_t struct_size
This size of this struct. Must be sizeof(FlutterLayer).
Definition: embedder.h:882
static TimePoint Now()
Definition: time_point.cc:26
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition: embedder.cc:1396
void SetRenderTargetType(EmbedderTestBackingStoreProducer::RenderTargetType type)
FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterDataCallback data_callback, void *user_data, FlutterPlatformMessageResponseHandle **response_out)
Creates a platform message response handle that allows the embedder to set a native callback for a re...
Definition: embedder.cc:1448
void SetSoftwareRendererConfig(SkISize surface_size=SkISize::Make(1, 1))
TEST(EmbeddedViewParams, GetBoundingRectAfterMutationsWithNoMutations)
FlutterEngineResult FlutterEngineCreateAOTData(const FlutterEngineAOTDataSource *source, FlutterEngineAOTData *data_out)
Creates the necessary data structures to launch a Flutter Dart application in AOT mode...
Definition: embedder.cc:597