| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Entrypoint for running a Flutter app on Fuchsia. |
| // |
| // Usage: ./main <path_to_flutter_asset_bundle> |
| |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/syslog/global.h> |
| #include <string> |
| |
| #include "src/embedder/engine/embedder.h" |
| |
| namespace { |
| |
| constexpr char kLogTag[] = "flutter_embedder"; |
| |
| bool FuchsiaPresentSoftwareSurface(void *user_data, const void *allocation, |
| size_t row_bytes, size_t height) { |
| // TODO(akbiggs): Present the surface to the screen. |
| FX_LOGF(ERROR, kLogTag, |
| "surface_present_callback (row_bytes=%lu, height=%lu)", row_bytes, |
| height); |
| return true; |
| } |
| |
| void FuchsiaLogMessage(const char *tag, const char *message, void *user_data) { |
| // TODO(akbiggs): This does not report the file and line number of the Dart |
| // app that the log came from. |
| FX_LOG(INFO, tag, message); |
| } |
| |
| bool RunFlutterApp(const char *assets_path) { |
| FlutterRendererConfig renderer_config = { |
| .type = kSoftware, |
| .software = |
| { |
| .struct_size = sizeof(FlutterSoftwareRendererConfig), |
| .surface_present_callback = FuchsiaPresentSoftwareSurface, |
| // TODO(akbiggs): Add callback for acquiring the software surface. |
| }, |
| }; |
| FlutterProjectArgs project_args = { |
| .struct_size = sizeof(FlutterProjectArgs), |
| .assets_path = assets_path, |
| .log_message_callback = FuchsiaLogMessage, |
| .log_tag = "flutter_app", |
| }; |
| |
| // TODO(akbiggs): Store this FlutterEngine instance somewhere instead of |
| // throwing it away. |
| FlutterEngine engine; |
| FlutterEngineResult result = FlutterEngineRun( |
| FLUTTER_ENGINE_VERSION, &renderer_config, &project_args, |
| // user_data is an arbitrary object that we can pass around to engine |
| // callbacks. When we need to make those callbacks change state in our |
| // embedder we should pass a pointer to a collection of our state here. |
| nullptr /* user_data */, &engine); |
| |
| if (result != kSuccess || engine == nullptr) { |
| FX_LOGF(ERROR, kLogTag, "Could not run the Flutter Engine. Error code: %d", |
| static_cast<int>(result)); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| } // namespace |
| |
| int main(int argc, const char *argv[]) { |
| if (argc != 2) { |
| FX_LOG(ERROR, kLogTag, "usage: executable <path to flutter bundle>"); |
| return EXIT_FAILURE; |
| } |
| const char *assets_path = argv[1]; |
| |
| async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread); |
| RunFlutterApp(assets_path); |
| loop.Run(); |
| |
| return EXIT_SUCCESS; |
| } |