8 #include <wrl/client.h>
11 #include "flutter/fml/synchronization/count_down_latch.h"
12 #include "flutter/fml/synchronization/waitable_event.h"
14 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
17 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
18 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
19 #include "flutter/shell/platform/windows/testing/windows_test.h"
20 #include "flutter/shell/platform/windows/testing/windows_test_config_builder.h"
21 #include "flutter/shell/platform/windows/testing/windows_test_context.h"
23 #include "flutter/testing/stream_capture.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "third_party/tonic/converter/dart_converter.h"
34 class HalfBrokenEGLManager :
public egl::Manager {
38 std::unique_ptr<egl::WindowSurface>
39 CreateWindowSurface(HWND hwnd,
size_t width,
size_t height)
override {
44 class MockWindowsLifecycleManager :
public WindowsLifecycleManager {
56 if (::GetMessage(&msg,
nullptr, 0, 0)) {
57 ::TranslateMessage(&msg);
58 ::DispatchMessage(&msg);
66 TEST(WindowsNoFixtureTest, GetTextureRegistrar) {
71 ASSERT_NE(engine,
nullptr);
73 EXPECT_NE(texture_registrar,
nullptr);
79 auto& context = GetContext();
80 WindowsConfigBuilder builder(context);
81 ViewControllerPtr controller{builder.Run()};
82 ASSERT_NE(controller,
nullptr);
86 TEST_F(WindowsTest, LaunchMainHasNoOutput) {
89 StreamCapture stderr_capture(&std::cerr);
91 auto& context = GetContext();
92 WindowsConfigBuilder builder(context);
93 ViewControllerPtr controller{builder.Run()};
94 ASSERT_NE(controller,
nullptr);
96 stderr_capture.Stop();
99 EXPECT_TRUE(stderr_capture.GetOutput().empty());
103 TEST_F(WindowsTest, LaunchCustomEntrypoint) {
104 auto& context = GetContext();
105 WindowsConfigBuilder builder(context);
106 builder.SetDartEntrypoint(
"customEntrypoint");
107 ViewControllerPtr controller{builder.Run()};
108 ASSERT_NE(controller,
nullptr);
116 TEST_F(WindowsTest, LaunchCustomEntrypointInEngineRunInvocation) {
117 auto& context = GetContext();
118 WindowsConfigBuilder builder(context);
119 EnginePtr engine{builder.InitializeEngine()};
120 ASSERT_NE(engine,
nullptr);
126 TEST_F(WindowsTest, LaunchHeadlessEngine) {
127 auto& context = GetContext();
128 WindowsConfigBuilder builder(context);
129 builder.SetDartEntrypoint(
"signalViewIds");
130 EnginePtr engine{builder.RunHeadless()};
131 ASSERT_NE(engine,
nullptr);
133 std::string view_ids;
134 bool signaled =
false;
135 context.AddNativeFunction(
136 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
137 auto handle = Dart_GetNativeArgument(args, 0);
138 ASSERT_FALSE(Dart_IsError(handle));
139 view_ids = tonic::DartConverter<std::string>::FromDart(handle);
143 ViewControllerPtr controller{builder.Run()};
144 ASSERT_NE(controller,
nullptr);
151 EXPECT_EQ(view_ids,
"View IDs: [0]");
155 TEST_F(WindowsTest, EngineCanTransitionToHeadless) {
156 auto& context = GetContext();
157 WindowsConfigBuilder builder(context);
158 EnginePtr engine{builder.RunHeadless()};
159 ASSERT_NE(engine,
nullptr);
165 ViewControllerPtr controller{
168 ASSERT_NE(controller,
nullptr);
172 ASSERT_NE(engine,
nullptr);
175 ASSERT_TRUE(engine_ptr->running());
179 TEST_F(WindowsTest, LaunchRefreshesAccessibility) {
180 auto& context = GetContext();
181 WindowsConfigBuilder builder(context);
182 EnginePtr engine{builder.InitializeEngine()};
183 EngineModifier modifier{
188 UpdateAccessibilityFeatures, ([&called](
auto engine,
auto flags) {
193 ViewControllerPtr controller{
204 TEST_F(WindowsTest, LaunchConflictingCustomEntrypoints) {
205 auto& context = GetContext();
206 WindowsConfigBuilder builder(context);
207 builder.SetDartEntrypoint(
"customEntrypoint");
208 EnginePtr engine{builder.InitializeEngine()};
209 ASSERT_NE(engine,
nullptr);
215 TEST_F(WindowsTest, VerifyNativeFunction) {
216 auto& context = GetContext();
217 WindowsConfigBuilder builder(context);
218 builder.SetDartEntrypoint(
"verifyNativeFunction");
220 bool signaled =
false;
222 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { signaled =
true; });
223 context.AddNativeFunction(
"Signal", native_entry);
225 ViewControllerPtr controller{builder.Run()};
226 ASSERT_NE(controller,
nullptr);
236 TEST_F(WindowsTest, VerifyNativeFunctionWithParameters) {
237 auto& context = GetContext();
238 WindowsConfigBuilder builder(context);
239 builder.SetDartEntrypoint(
"verifyNativeFunctionWithParameters");
241 bool bool_value =
false;
242 bool signaled =
false;
243 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
244 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value);
245 ASSERT_FALSE(Dart_IsError(handle));
248 context.AddNativeFunction(
"SignalBoolValue", native_entry);
250 ViewControllerPtr controller{builder.Run()};
251 ASSERT_NE(controller,
nullptr);
257 EXPECT_TRUE(bool_value);
261 TEST_F(WindowsTest, PlatformExecutable) {
262 auto& context = GetContext();
263 WindowsConfigBuilder builder(context);
264 builder.SetDartEntrypoint(
"readPlatformExecutable");
266 std::string executable_name;
267 bool signaled =
false;
268 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
269 auto handle = Dart_GetNativeArgument(args, 0);
270 ASSERT_FALSE(Dart_IsError(handle));
271 executable_name = tonic::DartConverter<std::string>::FromDart(handle);
274 context.AddNativeFunction(
"SignalStringValue", native_entry);
276 ViewControllerPtr controller{builder.Run()};
277 ASSERT_NE(controller,
nullptr);
283 EXPECT_EQ(executable_name,
"flutter_windows_unittests.exe");
288 TEST_F(WindowsTest, VerifyNativeFunctionWithReturn) {
289 auto& context = GetContext();
290 WindowsConfigBuilder builder(context);
291 builder.SetDartEntrypoint(
"verifyNativeFunctionWithReturn");
293 bool bool_value_to_return =
true;
295 auto bool_return_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
296 Dart_SetBooleanReturnValue(args, bool_value_to_return);
299 context.AddNativeFunction(
"SignalBoolReturn", bool_return_entry);
301 bool bool_value_passed =
false;
302 auto bool_pass_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
303 auto handle = Dart_GetNativeBooleanArgument(args, 0, &bool_value_passed);
304 ASSERT_FALSE(Dart_IsError(handle));
307 context.AddNativeFunction(
"SignalBoolValue", bool_pass_entry);
309 ViewControllerPtr controller{builder.Run()};
310 ASSERT_NE(controller,
nullptr);
316 EXPECT_TRUE(bool_value_passed);
322 fml::AutoResetWaitableEvent frame_scheduled_latch;
323 std::thread::id thread_id;
328 auto platform_thread = std::make_unique<fml::Thread>(
"test_platform_thread");
329 platform_thread->GetTaskRunner()->PostTask([&]() {
330 captures.thread_id = std::this_thread::get_id();
332 auto& context = GetContext();
333 WindowsConfigBuilder builder(context);
334 builder.SetDartEntrypoint(
"drawHelloWorld");
336 auto native_entry = CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
337 captures.frame_scheduled_latch.Signal();
339 context.AddNativeFunction(
"NotifyFirstFrameScheduled", native_entry);
341 ViewControllerPtr controller{builder.Run()};
342 EXPECT_NE(controller,
nullptr);
349 auto captures =
static_cast<Captures*
>(
user_data);
351 EXPECT_TRUE(captures->frame_scheduled_latch.IsSignaledForTest());
354 EXPECT_EQ(std::this_thread::get_id(), captures->thread_id);
357 captures->done =
true;
362 while (!captures.done) {
368 platform_thread->Join();
374 auto& context = GetContext();
375 WindowsConfigBuilder builder(context);
376 builder.SetDartEntrypoint(
"renderImplicitView");
378 EnginePtr engine{builder.RunHeadless()};
379 ASSERT_NE(engine,
nullptr);
386 auto done = reinterpret_cast<std::atomic<bool>*>(user_data);
395 FlutterWindowMetricsEvent metrics = {};
396 metrics.struct_size =
sizeof(FlutterWindowMetricsEvent);
398 metrics.height = 100;
399 metrics.pixel_ratio = 1.0;
401 engine_ptr->SendWindowMetricsEvent(metrics);
411 auto& context = GetContext();
412 WindowsConfigBuilder builder(context);
413 ViewControllerPtr controller{builder.Run()};
414 ASSERT_NE(controller,
nullptr);
421 TEST_F(WindowsTest, GetGraphicsAdapter) {
422 auto& context = GetContext();
423 WindowsConfigBuilder builder(context);
424 ViewControllerPtr controller{builder.Run()};
425 ASSERT_NE(controller,
nullptr);
428 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
430 ASSERT_NE(dxgi_adapter,
nullptr);
431 DXGI_ADAPTER_DESC desc{};
432 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
435 TEST_F(WindowsTest, GetEngineGraphicsAdapter) {
436 auto& context = GetContext();
437 WindowsConfigBuilder builder(context);
438 ViewControllerPtr controller{builder.Run()};
439 ASSERT_NE(controller,
nullptr);
443 IDXGIAdapter* dxgi_adapter;
445 ASSERT_NE(dxgi_adapter,
nullptr);
446 DXGI_ADAPTER_DESC desc{};
447 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
450 TEST_F(WindowsTest, GetGraphicsAdapterWithLowPowerPreference) {
453 GTEST_SKIP() <<
"Not able to find low power GPU, nothing to check.";
456 auto& context = GetContext();
457 WindowsConfigBuilder builder(context);
459 ViewControllerPtr controller{builder.Run()};
460 ASSERT_NE(controller,
nullptr);
463 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
465 ASSERT_NE(dxgi_adapter,
nullptr);
466 DXGI_ADAPTER_DESC desc{};
467 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
468 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
469 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
472 TEST_F(WindowsTest, GetGraphicsAdapterWithHighPerformancePreference) {
475 GTEST_SKIP() <<
"Not able to find high performance GPU, nothing to check.";
478 auto& context = GetContext();
479 WindowsConfigBuilder builder(context);
480 builder.SetGpuPreference(
482 ViewControllerPtr controller{builder.Run()};
483 ASSERT_NE(controller,
nullptr);
486 Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter;
488 ASSERT_NE(dxgi_adapter,
nullptr);
489 DXGI_ADAPTER_DESC desc{};
490 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
491 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
492 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
495 TEST_F(WindowsTest, GetEngineGraphicsAdapterWithLowPowerPreference) {
498 GTEST_SKIP() <<
"Not able to find low power GPU, nothing to check.";
501 auto& context = GetContext();
502 WindowsConfigBuilder builder(context);
504 ViewControllerPtr controller{builder.Run()};
505 ASSERT_NE(controller,
nullptr);
509 IDXGIAdapter* dxgi_adapter;
511 ASSERT_NE(dxgi_adapter,
nullptr);
512 DXGI_ADAPTER_DESC desc{};
513 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
514 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
515 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
518 TEST_F(WindowsTest, GetEngineGraphicsAdapterWithHighPerformancePreference) {
521 GTEST_SKIP() <<
"Not able to find high performance GPU, nothing to check.";
524 auto& context = GetContext();
525 WindowsConfigBuilder builder(context);
526 builder.SetGpuPreference(
528 ViewControllerPtr controller{builder.Run()};
529 ASSERT_NE(controller,
nullptr);
533 IDXGIAdapter* dxgi_adapter;
535 ASSERT_NE(dxgi_adapter,
nullptr);
536 DXGI_ADAPTER_DESC desc{};
537 ASSERT_TRUE(SUCCEEDED(dxgi_adapter->GetDesc(&desc)));
538 ASSERT_EQ(desc.AdapterLuid.HighPart, luid->HighPart);
539 ASSERT_EQ(desc.AdapterLuid.LowPart, luid->LowPart);
543 TEST_F(WindowsTest, PluginRegistrarGetImplicitView) {
544 auto& context = GetContext();
545 WindowsConfigBuilder builder(context);
546 ViewControllerPtr controller{builder.Run()};
547 ASSERT_NE(controller,
nullptr);
556 ASSERT_NE(implicit_view,
nullptr);
559 TEST_F(WindowsTest, PluginRegistrarGetView) {
560 auto& context = GetContext();
561 WindowsConfigBuilder builder(context);
562 ViewControllerPtr controller{builder.Run()};
563 ASSERT_NE(controller,
nullptr);
578 ASSERT_NE(view,
nullptr);
579 ASSERT_EQ(view_123,
nullptr);
582 TEST_F(WindowsTest, PluginRegistrarGetViewHeadless) {
583 auto& context = GetContext();
584 WindowsConfigBuilder builder(context);
585 EnginePtr engine{builder.RunHeadless()};
586 ASSERT_NE(engine,
nullptr);
596 ASSERT_EQ(implicit_view,
nullptr);
597 ASSERT_EQ(view_123,
nullptr);
603 auto& context = GetContext();
604 WindowsConfigBuilder builder(context);
605 EnginePtr engine{builder.InitializeEngine()};
606 EngineModifier modifier{
609 auto egl_manager = std::make_unique<HalfBrokenEGLManager>();
610 ASSERT_TRUE(egl_manager->IsValid());
611 modifier.SetEGLManager(std::move(egl_manager));
613 ViewControllerPtr controller{
616 ASSERT_NE(controller,
nullptr);
621 auto& context = GetContext();
622 WindowsConfigBuilder builder(context);
623 EnginePtr engine{builder.InitializeEngine()};
625 EngineModifier modifier{windows_engine};
627 auto lifecycle_manager =
628 std::make_unique<MockWindowsLifecycleManager>(windows_engine);
629 auto lifecycle_manager_ptr = lifecycle_manager.get();
630 modifier.SetLifecycleManager(std::move(lifecycle_manager));
632 EXPECT_CALL(*lifecycle_manager_ptr,
635 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
639 EXPECT_CALL(*lifecycle_manager_ptr,
642 lifecycle_manager_ptr->WindowsLifecycleManager::SetLifecycleState(
650 ViewControllerPtr controller{
655 ASSERT_NE(view,
nullptr);
658 ASSERT_NE(hwnd,
nullptr);
663 ::MoveWindow(hwnd, 0, 0, 100, 100,
666 while (lifecycle_manager_ptr->IsUpdateStateScheduled()) {
673 while (lifecycle_manager_ptr->IsUpdateStateScheduled()) {
678 TEST_F(WindowsTest, GetKeyboardStateHeadless) {
679 auto& context = GetContext();
680 WindowsConfigBuilder builder(context);
681 builder.SetDartEntrypoint(
"sendGetKeyboardState");
683 std::atomic<bool> done =
false;
684 context.AddNativeFunction(
685 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
686 auto handle = Dart_GetNativeArgument(args, 0);
687 ASSERT_FALSE(Dart_IsError(handle));
688 auto value = tonic::DartConverter<std::string>::FromDart(handle);
689 EXPECT_EQ(value,
"Success");
693 ViewControllerPtr controller{builder.Run()};
694 ASSERT_NE(controller,
nullptr);
706 std::string view_ids;
708 auto& context = GetContext();
709 WindowsConfigBuilder builder(context);
710 builder.SetDartEntrypoint(
"onMetricsChangedSignalViewIds");
713 context.AddNativeFunction(
715 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { ready =
true; }));
717 context.AddNativeFunction(
718 "SignalStringValue", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
719 auto handle = Dart_GetNativeArgument(args, 0);
720 ASSERT_FALSE(Dart_IsError(handle));
722 std::scoped_lock lock{mutex};
723 view_ids = tonic::DartConverter<std::string>::FromDart(handle);
727 ViewControllerPtr first_controller{builder.Run()};
728 ASSERT_NE(first_controller,
nullptr);
738 properties.
width = 100;
740 ViewControllerPtr second_controller{
742 ASSERT_NE(second_controller,
nullptr);
747 std::scoped_lock lock{mutex};
748 if (view_ids ==
"View IDs: [0, 1]") {
755 second_controller.reset();
758 std::scoped_lock lock{mutex};
759 if (view_ids ==
"View IDs: [0]") {
766 auto& context = GetContext();
767 WindowsConfigBuilder builder(context);
768 builder.SetDartEntrypoint(
"testEngineId");
770 std::optional<int64_t> engineId;
771 context.AddNativeFunction(
772 "NotifyEngineId", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
773 const auto argument = Dart_GetNativeArgument(args, 0);
774 if (!Dart_IsNull(argument)) {
775 const auto handle = tonic::DartConverter<int64_t>::FromDart(argument);
780 ViewControllerPtr first_controller{builder.Run()};
781 ASSERT_NE(first_controller,
nullptr);
783 while (!engineId.has_value()) {
792 auto& context = GetContext();
793 WindowsConfigBuilder builder(context);
794 builder.SetAccessibilityMode(
796 builder.SetDartEntrypoint(
"sendSemanticsTree");
801 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { done =
true; });
802 context.AddNativeFunction(
"Signal", native_entry);
805 ViewControllerPtr controller{builder.Run()};
806 ASSERT_NE(controller,
nullptr);
809 ASSERT_NE(view,
nullptr);
821 ASSERT_NE(hwnd,
nullptr);
823 LRESULT lres = SendMessage(hwnd, WM_GETOBJECT, 0, OBJID_CLIENT);
829 HRESULT hr = ObjectFromLresult(lres, IID_IAccessible, 0, (
void**)&accessible);
830 ASSERT_TRUE(SUCCEEDED(hr));
831 ASSERT_NE(accessible,
nullptr);
834 hr = ObjectFromLresult(lres, IID_IAccessibleEx, 0, (
void**)&accessible_ex);
835 ASSERT_TRUE(FAILED(hr));
836 ASSERT_EQ(accessible_ex,
nullptr);
839 TEST_F(WindowsTest, EnableIAccessibleEx) {
840 auto& context = GetContext();
841 WindowsConfigBuilder builder(context);
842 builder.SetAccessibilityMode(
844 builder.SetDartEntrypoint(
"sendSemanticsTree");
849 CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { done =
true; });
850 context.AddNativeFunction(
"Signal", native_entry);
853 ViewControllerPtr controller{builder.Run()};
854 ASSERT_NE(controller,
nullptr);
857 ASSERT_NE(view,
nullptr);
869 ASSERT_NE(hwnd,
nullptr);
871 LRESULT lres = SendMessage(hwnd, WM_GETOBJECT, 0, OBJID_CLIENT);
878 ObjectFromLresult(lres, IID_IAccessibleEx, 0, (
void**)&accessible_ex);
879 ASSERT_TRUE(SUCCEEDED(hr));
880 ASSERT_NE(accessible_ex,
nullptr);
881 accessible_ex->Release();
void UpdateAccessibilityFeatures()
virtual void OnUpdateSemanticsEnabled(bool enabled) override
WindowsLifecycleManager(FlutterWindowsEngine *engine)
virtual void SetLifecycleState(AppLifecycleState state)
static std::optional< LUID > GetLowPowerGpuLuid()
static std::optional< LUID > GetHighPerformanceGpuLuid()
MOCK_METHOD(void, Quit,(std::optional< HWND >, std::optional< WPARAM >, std::optional< LPARAM >, UINT),(override))
MockWindowsLifecycleManager(FlutterWindowsEngine *engine)
bool FlutterDesktopEngineGetGraphicsAdapter(FlutterDesktopEngineRef engine, IDXGIAdapter **adapter_out)
FlutterDesktopEngineRef FlutterDesktopEngineCreate(const FlutterDesktopEngineProperties *engine_properties)
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopEngineForId(int64_t engine_id)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetViewById(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopViewId view_id)
FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine, const char *plugin_name)
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(int width, int height, FlutterDesktopEngineRef engine)
bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine_ref)
FlutterDesktopTextureRegistrarRef FlutterDesktopEngineGetTextureRegistrar(FlutterDesktopEngineRef engine)
IDXGIAdapter * FlutterDesktopViewGetGraphicsAdapter(FlutterDesktopViewRef view)
FlutterDesktopViewId FlutterDesktopViewControllerGetViewId(FlutterDesktopViewControllerRef ref)
FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(FlutterDesktopViewControllerRef ref)
void FlutterDesktopEngineSetNextFrameCallback(FlutterDesktopEngineRef engine, VoidCallback callback, void *user_data)
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view)
FlutterDesktopViewRef FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef ref)
FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(FlutterDesktopPluginRegistrarRef registrar)
FlutterDesktopViewControllerRef FlutterDesktopEngineCreateViewController(FlutterDesktopEngineRef engine, const FlutterDesktopViewControllerProperties *properties)
bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine, const char *entry_point)
struct FlutterDesktopEngine * FlutterDesktopEngineRef
int64_t FlutterDesktopViewId
struct FlutterDesktopView * FlutterDesktopViewRef
@ HighPerformancePreference
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
TEST(AccessibilityBridgeWindows, GetParent)
constexpr FlutterViewId kImplicitViewId
const wchar_t * icu_data_path
const wchar_t * assets_path