diff --git a/CMakeLists.txt b/CMakeLists.txt index 40efee21..1ce8dea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,11 @@ option(ENABLE_TSAN "True to build & link with -fsanitize=thread" OFF) option(ENABLE_ASAN "True to build & link with -fsanitize=address" OFF) option(ENABLE_UBSAN "True to build & link with -fsanitize=undefined" OFF) option(ENABLE_MTRACE "True if flutter-pi should call GNU mtrace() on startup." OFF) + +set(FILESYSTEM_LAYOUTS default meta-flutter) +set(FILESYSTEM_LAYOUT "default" CACHE STRING "Where to look for the icudtl.dat, app.so/libapp.so, flutter asset bundle.") +set_property(CACHE FILESYSTEM_LAYOUT PROPERTY STRINGS ${FILESYSTEM_LAYOUTS}) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(NOT FLUTTER_EMBEDDER_HEADER) @@ -124,6 +129,7 @@ add_executable(flutter-pi src/locales.c src/notifier_listener.c src/pixel_format.c + src/filesystem_layout.c src/plugins/services.c ) @@ -171,6 +177,18 @@ target_compile_options(flutter-pi PRIVATE # TODO: Just unconditionally define those, make them optional later target_compile_definitions(flutter-pi PRIVATE HAS_KMS HAS_EGL HAS_GBM HAS_FBDEV) +if(NOT FILESYSTEM_LAYOUT IN_LIST FILESYSTEM_LAYOUTS) + message(FATAL_ERROR "FILESYSTEM_LAYOUT must be one of ${FILESYSTEM_LAYOUTS}") +endif() + +message(STATUS "Filesystem Layout ...... ${FILESYSTEM_LAYOUT}") + +if(FILESYSTEM_LAYOUT STREQUAL default) + target_compile_definitions(flutter-pi PRIVATE "FILESYSTEM_LAYOUT_DEFAULT") +elseif(FILESYSTEM_LAYOUT STREQUAL meta-flutter) + target_compile_definitions(flutter-pi PRIVATE "FILESYSTEM_LAYOUT_METAFLUTTER") +endif() + # TODO: We actually don't need the compile definitions anymore, except for # text input and raw keyboard plugin (because those have special treatment # in flutter-pi.c) diff --git a/include/filesystem_layout.h b/include/filesystem_layout.h new file mode 100644 index 00000000..533cd240 --- /dev/null +++ b/include/filesystem_layout.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +/* + * Filesystem Layout + * + * - implements different filesystem layouts for flutter artifacts + * + * Copyright (c) 2022, Hannes Winkler + */ + + +#ifndef _FLUTTERPI_INCLUDE_FILESYSTEM_LAYOUT_H +#define _FLUTTERPI_INCLUDE_FILESYSTEM_LAYOUT_H + +#include + +typedef struct flutter_paths *(*resolve_paths_t)(const char *app_bundle_path, enum flutter_runtime_mode runtime_mode); + +struct flutter_paths *fs_layout_flutterpi_resolve(const char *app_bundle_path, enum flutter_runtime_mode runtime_mode); +struct flutter_paths *fs_layout_metaflutter_resolve(const char *app_bundle_path, enum flutter_runtime_mode runtime_mode); + +#endif // _FLUTTERPI_INCLUDE_FILESYSTEM_LAYOUT_H diff --git a/include/flutter-pi.h b/include/flutter-pi.h index ad95ad36..a44348b2 100644 --- a/include/flutter-pi.h +++ b/include/flutter-pi.h @@ -218,9 +218,23 @@ enum flutter_runtime_mode { kDebug, kProfile, kRelease }; +#define FLUTTER_RUNTIME_MODE_IS_JIT(runtime_mode) ((runtime_mode) == kDebug) +#define FLUTTER_RUNTIME_MODE_IS_AOT(runtime_mode) ((runtime_mode) == kProfile || (runtime_mode) == kRelease) + struct plugin_registry; struct texture_registry; +struct flutter_paths { + char *app_bundle_path; + char *asset_bundle_path; + char *app_elf_path; + char *icudtl_path; + char *kernel_blob_path; + char *flutter_engine_path; + char *flutter_engine_dlopen_name; + char *flutter_engine_dlopen_name_fallback; +}; + struct flutterpi { /// graphics stuff struct { @@ -336,11 +350,9 @@ struct flutterpi { /// flutter stuff struct { - char *asset_bundle_path; - char *kernel_blob_path; - char *app_elf_path; + char *bundle_path; + struct flutter_paths *paths; void *app_elf_handle; - char *icu_data_path; FlutterLocale **locales; size_t n_locales; diff --git a/src/filesystem_layout.c b/src/filesystem_layout.c new file mode 100644 index 00000000..0b31cec4 --- /dev/null +++ b/src/filesystem_layout.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: MIT +/* + * Filesystem Layout + * + * - implements different filesystem layouts for flutter artifacts + * (libflutter_engine, icudtl, asset bundle, etc) + * + * Copyright (c) 2022, Hannes Winkler + */ + +#define _GNU_SOURCE +#include +#include +#include + +#include +#include + +FILE_DESCR("fs layout") + +static bool path_exists(const char *path) { + return access(path, R_OK) == 0; +} + +static struct flutter_paths *resolve( + const char *app_bundle_path, + enum flutter_runtime_mode runtime_mode, + const char *asset_bundle_subpath, + const char *icudtl_subpath, + const char *icudtl_system_path, + const char *icudtl_system_path_fallback, + const char *kernel_blob_subpath, + const char *app_elf_subpath, + const char *app_engine_subpath, + const char *engine_dlopen_name, + const char *engine_dlopen_name_fallback +) { + struct flutter_paths *paths; + char *dlopen_name_fallback_duped; + char *app_bundle_path_real; + char *dlopen_name_duped; + char *asset_bundle_path; + char *kernel_blob_path; + char *app_elf_path; + char *icudtl_path; + char *engine_path; + int ok; + + DEBUG_ASSERT_NOT_NULL(app_bundle_path); + DEBUG_ASSERT(icudtl_subpath || icudtl_system_path || icudtl_system_path_fallback); + DEBUG_ASSERT_MSG(!icudtl_system_path_fallback || icudtl_system_path, "icudtl.dat fallback system path is given, but no non-fallback system path."); + DEBUG_ASSERT_NOT_NULL(asset_bundle_subpath); + DEBUG_ASSERT_NOT_NULL(kernel_blob_subpath); + DEBUG_ASSERT_NOT_NULL(app_elf_subpath); + DEBUG_ASSERT(app_engine_subpath || engine_dlopen_name || engine_dlopen_name_fallback); + DEBUG_ASSERT_MSG(!engine_dlopen_name_fallback || engine_dlopen_name, "flutter engine fallback dlopen name is given, but no non-fallback dlopen name."); + + paths = malloc(sizeof *paths); + if (paths == NULL) { + return NULL; + } + + if (path_exists(app_bundle_path) == false) { + LOG_ERROR("App bundle directory \"%s\" does not exist.\n", app_bundle_path); + goto fail_free_paths; + } + + // Seems like the realpath will always not end with a slash. + app_bundle_path_real = realpath(app_bundle_path, NULL); + if (app_bundle_path_real == NULL) { + goto fail_free_paths; + } + + DEBUG_ASSERT(path_exists(app_bundle_path_real)); + + // Asset bundle path is the same as the app bundle path in the default filesystem layout, + // or /flutter_assets in meta-flutter dunfell / kirkstone layout. + ok = asprintf(&asset_bundle_path, "%s/%s", app_bundle_path_real, asset_bundle_subpath); + if (ok == -1) { + goto fail_free_app_bundle_path_real; + } + + if (path_exists(asset_bundle_path) == false) { + LOG_ERROR("Asset bundle directory \"%s\" does not exist.\n", asset_bundle_path); + goto fail_free_asset_bundle_path; + } + + // Find the icudtl.dat file. + // Mostly we look in /icudtl.dat or /data/icudtl.dat, /usr/share/flutter/icudtl.dat + // or /usr/lib/icudtl.dat. + icudtl_path = NULL; + + if (icudtl_subpath != NULL) { + ok = asprintf(&icudtl_path, "%s/%s", app_bundle_path_real, icudtl_subpath); + if (ok == -1) { + goto fail_free_asset_bundle_path; + } + } + + if (icudtl_system_path != NULL && (icudtl_path == NULL || path_exists(icudtl_path) == false)) { + LOG_DEBUG("icudtl file not found at %s.\n", icudtl_path); + free(icudtl_path); + + icudtl_path = strdup(icudtl_system_path); + if (icudtl_path == NULL) { + goto fail_free_asset_bundle_path; + } + } + + DEBUG_ASSERT_NOT_NULL(icudtl_path); + + if (icudtl_system_path_fallback != NULL || path_exists(icudtl_path) == false) { + LOG_DEBUG("icudtl file not found at %s.\n", icudtl_path); + free(icudtl_path); + + icudtl_path = strdup(icudtl_system_path_fallback); + if (icudtl_path == NULL) { + goto fail_free_asset_bundle_path; + } + } + + DEBUG_ASSERT_NOT_NULL(icudtl_path); + + // We still haven't found it. Fail because we need it to run flutter. + if (path_exists(icudtl_path) == false) { + LOG_DEBUG("icudtl file not found at %s.\n", icudtl_path); + free(icudtl_path); + + LOG_ERROR("icudtl file not found!\n"); + goto fail_free_asset_bundle_path; + } + + // Find the kernel_blob.bin file. Only necessary for JIT (debug) mode. + ok = asprintf(&kernel_blob_path, "%s/%s", app_bundle_path_real, kernel_blob_subpath); + if (ok == -1) { + goto fail_free_asset_bundle_path; + } + + if (FLUTTER_RUNTIME_MODE_IS_JIT(runtime_mode) && !path_exists(kernel_blob_path)) { + LOG_ERROR("kernel blob file \"%s\" does not exist, but is necessary for debug mode.\n", kernel_blob_path); + goto fail_free_kernel_blob_path; + } + + // Find the app.so/libapp.so file. Only necessary for AOT (release/profile) mode. + ok = asprintf(&app_elf_path, "%s/%s", app_bundle_path_real, app_elf_subpath); + if (ok == -1) { + goto fail_free_kernel_blob_path; + } + + if (FLUTTER_RUNTIME_MODE_IS_AOT(runtime_mode) && !path_exists(app_elf_path)) { + LOG_ERROR("app elf file \"%s\" does not exist, but is necessary for release/profile mode.\n", app_elf_path); + goto fail_free_app_elf_path; + } + + // Try to find the engine inside the asset bundle. If we don't find it, that's not an error because + // it could still be inside /usr/lib and we can just dlopen it using the filename. + ok = asprintf(&engine_path, "%s/%s", app_bundle_path_real, app_engine_subpath); + if (ok == -1) { + goto fail_free_app_elf_path; + } + + if (path_exists(engine_path) == false) { + if (engine_dlopen_name == NULL && engine_dlopen_name_fallback == NULL) { + LOG_ERROR("flutter engine file \"%s\" does not exist.\n", engine_path); + goto fail_maybe_free_engine_path; + } + + free(engine_path); + engine_path = NULL; + } + + if (engine_dlopen_name != NULL) { + dlopen_name_duped = strdup(engine_dlopen_name); + if (dlopen_name_duped == NULL) { + goto fail_maybe_free_engine_path; + } + } else { + dlopen_name_duped = NULL; + } + + if (engine_dlopen_name_fallback != NULL) { + dlopen_name_fallback_duped = strdup(engine_dlopen_name_fallback); + if (dlopen_name_fallback_duped == NULL) { + goto fail_free_dlopen_name_duped; + } + } else { + dlopen_name_fallback_duped = NULL; + } + + + paths->app_bundle_path = app_bundle_path_real; + paths->asset_bundle_path = asset_bundle_path; + paths->icudtl_path = icudtl_path; + paths->kernel_blob_path = kernel_blob_path; + paths->app_elf_path = app_elf_path; + paths->flutter_engine_path = engine_path; + paths->flutter_engine_dlopen_name = dlopen_name_duped; + paths->flutter_engine_dlopen_name_fallback = dlopen_name_fallback_duped; + return paths; + + + fail_free_dlopen_name_duped: + free(dlopen_name_duped); + + fail_maybe_free_engine_path: + if (engine_path != NULL) { + free(engine_path); + } + + fail_free_app_elf_path: + free(app_elf_path); + + fail_free_kernel_blob_path: + free(kernel_blob_path); + + fail_free_asset_bundle_path: + free(asset_bundle_path); + + fail_free_app_bundle_path_real: + free(app_bundle_path_real); + + fail_free_paths: + free(paths); + return NULL; +} + +void flutter_paths_free(struct flutter_paths *paths) { + free(paths->app_bundle_path); + free(paths->asset_bundle_path); + free(paths->icudtl_path); + free(paths->kernel_blob_path); + free(paths->app_elf_path); + if (paths->flutter_engine_path != NULL) { + free(paths->flutter_engine_path); + } + if (paths->flutter_engine_dlopen_name != NULL) { + free(paths->flutter_engine_dlopen_name); + } + if (paths->flutter_engine_dlopen_name_fallback != NULL) { + free(paths->flutter_engine_dlopen_name_fallback); + } + free(paths); +} + +struct flutter_paths *fs_layout_flutterpi_resolve(const char *app_bundle_path, enum flutter_runtime_mode runtime_mode) { + return resolve( + app_bundle_path, + runtime_mode, + /* asset bundle subpath */ "", + /* icudtl subpath */ "icudtl.dat", + /* icudtl system path */ "/usr/share/flutter/icudtl.dat", + /* icudtl system path fallback */ "/usr/lib/icudtl.dat", + /* kernel blob subpath */ "kernel_blob.bin", + /* app elf subpath */ "app.so", + /* flutter engine subpath */ "libflutter_engine.so", + /* engine dlopen name */ runtime_mode == kDebug ? "libflutter_engine.so.debug" : + runtime_mode == kProfile ? "libflutter_engine.so.profile" : + "libflutter_engine.so.release", + /* engine dlopen name fallback */ "libflutter_engine.so" + ); +} + +struct flutter_paths *fs_layout_metaflutter_resolve(const char *app_bundle_path, enum flutter_runtime_mode runtime_mode) { + return resolve( + app_bundle_path, + runtime_mode, + /* asset bundle subpath */ "data/flutter_assets/", + /* icudtl subpath */ "data/icudtl.dat", + /* icudtl system path */ "/usr/share/flutter/icudtl.dat", + /* icudtl system path fallback */ NULL, + /* kernel blob subpath */ "flutter_assets/kernel_blob.bin", + /* app elf subpath */ "lib/libapp.so", + /* flutter engine subpath */ "lib/libflutter_engine.so", + /* engine dlopen name */ "libflutter_engine.so", + /* engine dlopen name fallback */ NULL + ); +} diff --git a/src/flutter-pi.c b/src/flutter-pi.c index 0a5b24df..ebac3b01 100644 --- a/src/flutter-pi.c +++ b/src/flutter-pi.c @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef ENABLE_MTRACE # include @@ -66,18 +67,16 @@ const char *const usage ="\ flutter-pi - run flutter apps on your Raspberry Pi.\n\ \n\ USAGE:\n\ - flutter-pi [options] [flutter engine options]\n\ + flutter-pi [options] [flutter engine options]\n\ \n\ OPTIONS:\n\ --release Run the app in release mode. The AOT snapshot\n\ - of the app (\"app.so\") must be located inside the\n\ - asset bundle directory.\n\ + of the app must be located inside the bundle directory.\n\ This also requires a libflutter_engine.so that was\n\ built with --runtime-mode=release.\n\ \n\ --profile Run the app in profile mode. The AOT snapshot\n\ - of the app (\"app.so\") must be located inside the\n\ - asset bundle directory.\n\ + of the app must be located inside the bundle directory.\n\ This also requires a libflutter_engine.so that was\n\ built with --runtime-mode=profile.\n\ \n\ @@ -936,7 +935,7 @@ struct texture *flutterpi_create_texture(struct flutterpi *flutterpi) { const char *flutterpi_get_asset_bundle_path( struct flutterpi *flutterpi ) { - return flutterpi->flutter.asset_bundle_path; + return flutterpi->flutter.paths->asset_bundle_path; } /// TODO: Make this refcounted if we're gonna use it from multiple threads. @@ -1824,6 +1823,7 @@ static int init_display(void) { **************************/ static int init_application(void) { FlutterEngineAOTDataSource aot_source; + enum flutter_runtime_mode runtime_mode; struct libflutter_engine *libflutter_engine; struct texture_registry *texture_registry; struct plugin_registry *plugin_registry; @@ -1831,61 +1831,54 @@ static int init_application(void) { FlutterEngineAOTData aot_data; FlutterEngineResult engine_result; FlutterProjectArgs project_args = {0}; - void *libflutter_engine_handle; - char *libflutter_engine_path; + void *engine_handle; int ok; - asprintf(&libflutter_engine_path, "%s/libflutter_engine.so", flutterpi.flutter.asset_bundle_path); + runtime_mode = flutterpi.flutter.runtime_mode; - libflutter_engine_handle = NULL; - - libflutter_engine_handle = dlopen(libflutter_engine_path, RTLD_LOCAL | RTLD_NOW); - - if (libflutter_engine_handle == NULL) { - LOG_ERROR( - "Warning: Could not load libflutter_engine.so from the asset bundle. dlopen: %s. Trying to open libflutter_engine.so.%s...\n", - dlerror(), - flutterpi.flutter.runtime_mode == kDebug ? "debug" : - flutterpi.flutter.runtime_mode == kProfile ? "profile" : - "release" - ); + if (flutterpi.flutter.paths->flutter_engine_path != NULL) { + engine_handle = dlopen(flutterpi.flutter.paths->flutter_engine_path, RTLD_LOCAL | RTLD_NOW); + if (engine_handle == NULL) { + LOG_DEBUG( + "Info: Could not load flutter engine from app bundle. dlopen(\"%s\"): %s.\n", + flutterpi.flutter.paths->flutter_engine_path, + dlerror() + ); + } } - free(libflutter_engine_path); - - if (libflutter_engine_handle == NULL) { - if (flutterpi.flutter.runtime_mode == kRelease) { - libflutter_engine_handle = dlopen("libflutter_engine.so.release", RTLD_LOCAL | RTLD_NOW); - if (libflutter_engine_handle == NULL) { - LOG_ERROR("Warning: Could not load libflutter_engine.so.release. dlopen: %s. Trying to open libflutter_engine.so...\n", dlerror()); - } - } else if (flutterpi.flutter.runtime_mode == kProfile) { - libflutter_engine_handle = dlopen("libflutter_engine.so.profile", RTLD_LOCAL | RTLD_NOW); - if (libflutter_engine_handle == NULL) { - LOG_ERROR("Warning: Could not load libflutter_engine.so.profile. dlopen: %s. Trying to open libflutter_engine.so...\n", dlerror()); - } - } else if (flutterpi.flutter.runtime_mode == kDebug) { - libflutter_engine_handle = dlopen("libflutter_engine.so.debug", RTLD_LOCAL | RTLD_NOW); - if (libflutter_engine_handle == NULL) { - LOG_ERROR("Warning: Could not load libflutter_engine.so.debug. dlopen: %s. Trying to open libflutter_engine.so...\n", dlerror()); - } + if (engine_handle == NULL && flutterpi.flutter.paths->flutter_engine_dlopen_name != NULL) { + engine_handle = dlopen(flutterpi.flutter.paths->flutter_engine_dlopen_name, RTLD_LOCAL | RTLD_NOW); + if (engine_handle == NULL) { + LOG_DEBUG( + "Info: Could not load flutter engine. dlopen(\"%s\"): %s.\n", + flutterpi.flutter.paths->flutter_engine_dlopen_name, + dlerror() + ); } } - if (libflutter_engine_handle == NULL) { - libflutter_engine_handle = dlopen("libflutter_engine.so", RTLD_LOCAL | RTLD_NOW); - if (libflutter_engine_handle == NULL) { - LOG_ERROR("Could not load libflutter_engine.so. dlopen: %s\n", dlerror()); - LOG_ERROR("Could not find a fitting libflutter_engine.so, make sure you've installed the engine binaries.\n"); - return EINVAL; + if (engine_handle == NULL && flutterpi.flutter.paths->flutter_engine_dlopen_name_fallback != NULL) { + engine_handle = dlopen(flutterpi.flutter.paths->flutter_engine_dlopen_name_fallback, RTLD_LOCAL | RTLD_NOW); + if (engine_handle == NULL) { + LOG_DEBUG( + "Info: Could not load flutter engine. dlopen(\"%s\"): %s.\n", + flutterpi.flutter.paths->flutter_engine_dlopen_name_fallback, + dlerror() + ); } } + if (engine_handle == NULL) { + LOG_ERROR("Error: Could not load flutter engine from any location. Make sure you have installed the engine binaries.\n"); + return EINVAL; + } + libflutter_engine = &flutterpi.flutter.libflutter_engine; # define LOAD_LIBFLUTTER_ENGINE_PROC(name) \ do { \ - libflutter_engine->name = dlsym(libflutter_engine_handle, #name); \ + libflutter_engine->name = dlsym(engine_handle, #name); \ if (!libflutter_engine->name) {\ perror("[flutter-pi] Could not resolve libflutter_engine procedure " #name ". dlsym"); \ return EINVAL; \ @@ -1968,8 +1961,8 @@ static int init_application(void) { // configure the project project_args = (FlutterProjectArgs) { .struct_size = sizeof(FlutterProjectArgs), - .assets_path = flutterpi.flutter.asset_bundle_path, - .icu_data_path = flutterpi.flutter.icu_data_path, + .assets_path = flutterpi.flutter.paths->asset_bundle_path, + .icu_data_path = flutterpi.flutter.paths->icudtl_path, .command_line_argc = flutterpi.flutter.engine_argc, .command_line_argv = (const char * const*) flutterpi.flutter.engine_argv, .platform_message_callback = on_platform_message, @@ -2010,14 +2003,14 @@ static int init_application(void) { }; bool engine_is_aot = libflutter_engine->FlutterEngineRunsAOTCompiledDartCode(); - if ((engine_is_aot == true) && (flutterpi.flutter.runtime_mode == kDebug)) { + if (engine_is_aot == true && runtime_mode == kDebug) { LOG_ERROR( "The flutter engine was built for release or profile (AOT) mode, but flutter-pi was not started up in release or profile mode.\n" "Either you swap out the libflutter_engine.so with one that was built for debug mode, or you start" "flutter-pi with the --release or --profile flag and make sure a valid \"app.so\" is located inside the asset bundle directory.\n" ); return EINVAL; - } else if ((engine_is_aot == false) && (flutterpi.flutter.runtime_mode != kDebug)) { + } else if (engine_is_aot == false && runtime_mode != kDebug) { LOG_ERROR( "The flutter engine was built for debug mode, but flutter-pi was started up in release mode.\n" "Either you swap out the libflutter_engine.so with one that was built for release mode," @@ -2028,7 +2021,7 @@ static int init_application(void) { if (flutterpi.flutter.runtime_mode != kDebug) { aot_source = (FlutterEngineAOTDataSource) { - .elf_path = flutterpi.flutter.app_elf_path, + .elf_path = flutterpi.flutter.paths->app_elf_path, .type = kFlutterEngineAOTDataSourceTypeElfPath }; @@ -2304,48 +2297,19 @@ static int init_user_input(void) { return 0; } +static bool path_exists(const char *path) { + return access(path, R_OK) == 0; +} -static bool setup_paths(void) { - char *kernel_blob_path, *icu_data_path, *app_elf_path; - #define PATH_EXISTS(path) (access((path),R_OK)==0) - - if (!PATH_EXISTS(flutterpi.flutter.asset_bundle_path)) { - LOG_ERROR("Asset Bundle Directory \"%s\" does not exist\n", flutterpi.flutter.asset_bundle_path); - return false; - } - - asprintf(&kernel_blob_path, "%s/kernel_blob.bin", flutterpi.flutter.asset_bundle_path); - asprintf(&app_elf_path, "%s/app.so", flutterpi.flutter.asset_bundle_path); - - if (flutterpi.flutter.runtime_mode == kDebug) { - if (!PATH_EXISTS(kernel_blob_path)) { - LOG_ERROR("Could not find \"kernel.blob\" file inside \"%s\", which is required for debug mode.\n", flutterpi.flutter.asset_bundle_path); - return false; - } - } else if ((flutterpi.flutter.runtime_mode == kRelease) || (flutterpi.flutter.runtime_mode == kProfile)) { - if (!PATH_EXISTS(app_elf_path)) { - LOG_ERROR("Could not find \"app.so\" file inside \"%s\", which is required for release and profile mode.\n", flutterpi.flutter.asset_bundle_path); - return false; - } - } - - asprintf(&icu_data_path, "%s/icudtl.dat", flutterpi.flutter.asset_bundle_path); - if (!PATH_EXISTS(icu_data_path)) { - free(icu_data_path); - asprintf(&icu_data_path, "/usr/lib/icudtl.dat"); - if (!PATH_EXISTS(icu_data_path)) { - LOG_ERROR("Could not find \"icudtl.dat\" file inside asset bundle or \"/usr/lib/\".\n"); - return false; - } - } - - flutterpi.flutter.kernel_blob_path = kernel_blob_path; - flutterpi.flutter.icu_data_path = icu_data_path; - flutterpi.flutter.app_elf_path = app_elf_path; - - return true; - - #undef PATH_EXISTS +static struct flutter_paths *setup_paths(enum flutter_runtime_mode runtime_mode, const char *app_bundle_path) { +#if defined(FILESYSTEM_LAYOUT_DEFAULT) + return fs_layout_flutterpi_resolve(app_bundle_path, runtime_mode); +#elif defined(FILESYSTEM_LAYOUT_METAFLUTTER) + return fs_layout_metaflutter_resolve(app_bundle_path, runtime_mode); +#else + #error "Exactly one of FILESYSTEM_LAYOUT_DEFAULT or FILESYSTEM_LAYOUT_METAFLUTTER must be defined." + return NULL; +#endif } static bool parse_cmd_args(int argc, char **argv) { @@ -2478,7 +2442,7 @@ static bool parse_cmd_args(int argc, char **argv) { return false; } - flutterpi.flutter.asset_bundle_path = realpath(argv[optind], NULL); + flutterpi.flutter.bundle_path = realpath(argv[optind], NULL); flutterpi.flutter.runtime_mode = runtime_mode_int; argv[optind] = argv[0]; @@ -2489,6 +2453,7 @@ static bool parse_cmd_args(int argc, char **argv) { } int init(int argc, char **argv) { + struct flutter_paths *paths; int ok; #ifdef ENABLE_MTRACE @@ -2500,11 +2465,13 @@ int init(int argc, char **argv) { return EINVAL; } - ok = setup_paths(); - if (ok == false) { + paths = setup_paths(flutterpi.flutter.runtime_mode, flutterpi.flutter.bundle_path); + if (paths == NULL) { return EINVAL; } + flutterpi.flutter.paths = paths; + ok = init_main_loop(); if (ok != 0) { return ok; diff --git a/src/plugins/omxplayer_video_player.c b/src/plugins/omxplayer_video_player.c index 5a2b729f..d6050c18 100644 --- a/src/plugins/omxplayer_video_player.c +++ b/src/plugins/omxplayer_video_player.c @@ -1148,7 +1148,7 @@ static int on_create( player->player_id = omxpvidpp.next_unused_player_id++; player->mgr = mgr; if (asset != NULL) { - snprintf(player->video_uri, sizeof(player->video_uri), "%s/%s", flutterpi.flutter.asset_bundle_path, asset); + snprintf(player->video_uri, sizeof(player->video_uri), "%s/%s", flutterpi.flutter.paths->asset_bundle_path, asset); } else { strncpy(player->video_uri, uri, sizeof(player->video_uri)); }