From c82593525fc62bbd18f34f959f6f5f923dd7e3c1 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 01:48:01 +0100 Subject: [PATCH 1/5] Desktop: Unload animations before FAP is loaded --- applications/services/desktop/desktop.c | 6 ++++-- applications/services/loader/loader.c | 8 ++++++++ applications/services/loader/loader.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 49aa04e35..c5a334a45 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -32,10 +32,12 @@ static void desktop_loader_callback(const void* message, void* context) { Desktop* desktop = context; const LoaderEvent* event = message; - if(event->type == LoaderEventTypeApplicationStarted) { + if(event->type == LoaderEventTypeApplicationBeforeLoad) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted); furi_check(furi_semaphore_acquire(desktop->animation_semaphore, 3000) == FuriStatusOk); - } else if(event->type == LoaderEventTypeApplicationStopped) { + } else if( + event->type == LoaderEventTypeApplicationLoadFailed || + event->type == LoaderEventTypeApplicationStopped) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 5daf99d1d..553be6818 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -255,6 +255,9 @@ static void loader_start_internal_app( const FlipperInternalApplication* app, const char* args) { FURI_LOG_I(TAG, "Starting %s", app->name); + LoaderEvent event; + event.type = LoaderEventTypeApplicationBeforeLoad; + furi_pubsub_publish(loader->pubsub, &event); // store args furi_assert(loader->app.args == NULL); @@ -309,6 +312,9 @@ static LoaderStatus loader_start_external_app( const char* args, FuriString* error_message) { LoaderStatus status = loader_make_success_status(error_message); + LoaderEvent event; + event.type = LoaderEventTypeApplicationBeforeLoad; + furi_pubsub_publish(loader->pubsub, &event); do { loader->app.fap = flipper_application_alloc(storage, firmware_api_interface); @@ -356,6 +362,8 @@ static LoaderStatus loader_start_external_app( if(status != LoaderStatusOk) { flipper_application_free(loader->app.fap); loader->app.fap = NULL; + event.type = LoaderEventTypeApplicationLoadFailed; + furi_pubsub_publish(loader->pubsub, &event); } return status; diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index cca65628f..5e132a9ac 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -18,6 +18,8 @@ typedef enum { } LoaderStatus; typedef enum { + LoaderEventTypeApplicationBeforeLoad, + LoaderEventTypeApplicationLoadFailed, LoaderEventTypeApplicationStarted, LoaderEventTypeApplicationStopped } LoaderEventType; From 092f529ed5a891244f181726168b8f8783a9b443 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:34:24 +0100 Subject: [PATCH 2/5] Loader: Add API to start app detached (returns instantly, queues app start) --- applications/services/loader/loader.c | 35 ++++++++++++++++++++----- applications/services/loader/loader.h | 14 +++++++--- applications/services/loader/loader_i.h | 1 + 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 553be6818..c552b5776 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -47,13 +47,7 @@ LoaderStatus return result.value; } -LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { - furi_check(loader); - furi_check(name); - - FuriString* error_message = furi_string_alloc(); - LoaderStatus status = loader_start(loader, name, args, error_message); - +static void loader_show_gui_error(LoaderStatus status, FuriString* error_message) { if(status == LoaderStatusErrorUnknownApp && loader_find_external_application_by_name(name) != NULL) { // Special case for external apps @@ -75,6 +69,7 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const dialog_message_set_header(message, "Error", 64, 0, AlignCenter, AlignTop); dialog_message_set_buttons(message, NULL, NULL, NULL); + furi_string_replace(error_message, ":", "\n"); furi_string_replace(error_message, "/ext/apps/", ""); furi_string_replace(error_message, ", ", "\n"); furi_string_replace(error_message, ": ", "\n"); @@ -86,11 +81,31 @@ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const dialog_message_free(message); furi_record_close(RECORD_DIALOGS); } +} +LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { + furi_check(loader); + furi_check(name); + + FuriString* error_message = furi_string_alloc(); + LoaderStatus status = loader_start(loader, name, args, error_message); + loader_show_gui_error(status, error_message); furi_string_free(error_message); return status; } +void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args) { + furi_check(loader); + furi_check(name); + + LoaderMessage message = { + .type = LoaderMessageTypeStartByNameDetachedWithGuiError, + .start.name = name ? strdup(name) : NULL, + .start.args = args ? strdup(args) : NULL, + }; + furi_message_queue_put(loader->queue, &message, FuriWaitForever); +} + bool loader_lock(Loader* loader) { furi_check(loader); @@ -536,6 +551,12 @@ int32_t loader_srv(void* p) { loader, message.start.name, message.start.args, message.start.error_message); api_lock_unlock(message.api_lock); break; + case LoaderMessageTypeStartByNameDetachedWithGuiError: { + loader_start_with_gui_error(loader, message.start.name, message.start.args); + if(message.start.name) free((void*)message.start.name); + if(message.start.args) free((void*)message.start.args); + break; + } case LoaderMessageTypeShowMenu: loader_do_menu_show(loader); break; diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index 5e132a9ac..d57ba7da1 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -34,7 +34,7 @@ typedef struct { * @param[in] name application name or id * @param[in] args application arguments * @param[out] error_message detailed error message, can be NULL - * @return LoaderStatus + * @return LoaderStatus */ LoaderStatus loader_start(Loader* instance, const char* name, const char* args, FuriString* error_message); @@ -44,11 +44,19 @@ LoaderStatus * @param[in] instance loader instance * @param[in] name application name or id * @param[in] args application arguments - * @return LoaderStatus + * @return LoaderStatus */ LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args); -/** +/** + * @brief Start application detached with GUI error message + * @param[in] instance loader instance + * @param[in] name application name or id + * @param[in] args application arguments + */ +void loader_start_detached_with_gui_error(Loader* loader, const char* name, const char* args); + +/** * @brief Lock application start * @param[in] instance loader instance * @return true on success diff --git a/applications/services/loader/loader_i.h b/applications/services/loader/loader_i.h index 688b8fb66..daa5484d3 100644 --- a/applications/services/loader/loader_i.h +++ b/applications/services/loader/loader_i.h @@ -30,6 +30,7 @@ typedef enum { LoaderMessageTypeLock, LoaderMessageTypeUnlock, LoaderMessageTypeIsLocked, + LoaderMessageTypeStartByNameDetachedWithGuiError, } LoaderMessageType; typedef struct { From 5f7e6980170ee61246ffc566863190c7204aef88 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:36:41 +0100 Subject: [PATCH 3/5] Desktop: Fix early animation unload deadlocks --- .../services/desktop/scenes/desktop_scene_main.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index a659ff4e3..955d64fe2 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -64,21 +64,17 @@ static void static void desktop_scene_main_open_app_or_profile(Desktop* desktop, FavoriteApp* application) { bool load_ok = false; if(strlen(application->name_or_path) > 0) { - if(loader_start(desktop->loader, application->name_or_path, NULL, NULL) == - LoaderStatusOk) { - load_ok = true; - } - } - if(!load_ok) { - loader_start(desktop->loader, "Passport", NULL, NULL); + loader_start_detached_with_gui_error(desktop->loader, application->name_or_path, NULL); + } else { + loader_start_detached_with_gui_error(desktop->loader, "Passport", NULL); } } static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) { if(strlen(application->name_or_path) > 0) { - loader_start_with_gui_error(desktop->loader, application->name_or_path, NULL); + loader_start_detached_with_gui_error(desktop->loader, application->name_or_path); } else { - loader_start(desktop->loader, LOADER_APPLICATIONS_NAME, NULL, NULL); + loader_start_detached_with_gui_error(desktop->loader, LOADER_APPLICATIONS_NAME, NULL); } } @@ -141,7 +137,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; case DesktopMainEventOpenPowerOff: { - loader_start(desktop->loader, "Power", "off", NULL); + loader_start_detached_with_gui_error(desktop->loader, "Power", "off"); consumed = true; break; } From 0290996beae4f08f5586c2ab3a845d59cbccdc36 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 21:53:45 +0100 Subject: [PATCH 4/5] Update symbols --- targets/f18/api_symbols.csv | 3 ++- targets/f7/api_symbols.csv | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index f6199445d..38914ad4f 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,60.4,, +Version,+,60.5,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1748,6 +1748,7 @@ Function,+,loader_is_locked,_Bool,Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void,Loader* Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*, FuriString*" +Function,+,loader_start_detached_with_gui_error,void,"Loader*, const char*, const char*" Function,+,loader_start_with_gui_error,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_unlock,void,Loader* Function,+,loading_alloc,Loading*, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 6e65b9471..ee3ece431 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,60.4,, +Version,+,60.5,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -2128,6 +2128,7 @@ Function,+,loader_is_locked,_Bool,Loader* Function,+,loader_lock,_Bool,Loader* Function,+,loader_show_menu,void,Loader* Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*, FuriString*" +Function,+,loader_start_detached_with_gui_error,void,"Loader*, const char*, const char*" Function,+,loader_start_with_gui_error,LoaderStatus,"Loader*, const char*, const char*" Function,+,loader_unlock,void,Loader* Function,+,loading_alloc,Loading*, From 8e57a4f089a96082c52ff250f5d517795ede7573 Mon Sep 17 00:00:00 2001 From: Willy-JL <49810075+Willy-JL@users.noreply.github.com> Date: Fri, 5 Apr 2024 22:00:34 +0100 Subject: [PATCH 5/5] Fix build and cleanup --- .../services/desktop/scenes/desktop_scene_main.c | 3 +-- applications/services/loader/loader.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index 955d64fe2..41b1c3e75 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -62,7 +62,6 @@ static void #endif static void desktop_scene_main_open_app_or_profile(Desktop* desktop, FavoriteApp* application) { - bool load_ok = false; if(strlen(application->name_or_path) > 0) { loader_start_detached_with_gui_error(desktop->loader, application->name_or_path, NULL); } else { @@ -72,7 +71,7 @@ static void desktop_scene_main_open_app_or_profile(Desktop* desktop, FavoriteApp static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) { if(strlen(application->name_or_path) > 0) { - loader_start_detached_with_gui_error(desktop->loader, application->name_or_path); + loader_start_detached_with_gui_error(desktop->loader, application->name_or_path, NULL); } else { loader_start_detached_with_gui_error(desktop->loader, LOADER_APPLICATIONS_NAME, NULL); } diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index c552b5776..8221f4eb0 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -47,7 +47,13 @@ LoaderStatus return result.value; } -static void loader_show_gui_error(LoaderStatus status, FuriString* error_message) { +LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { + furi_check(loader); + furi_check(name); + + FuriString* error_message = furi_string_alloc(); + LoaderStatus status = loader_start(loader, name, args, error_message); + if(status == LoaderStatusErrorUnknownApp && loader_find_external_application_by_name(name) != NULL) { // Special case for external apps @@ -81,15 +87,7 @@ static void loader_show_gui_error(LoaderStatus status, FuriString* error_message dialog_message_free(message); furi_record_close(RECORD_DIALOGS); } -} -LoaderStatus loader_start_with_gui_error(Loader* loader, const char* name, const char* args) { - furi_check(loader); - furi_check(name); - - FuriString* error_message = furi_string_alloc(); - LoaderStatus status = loader_start(loader, name, args, error_message); - loader_show_gui_error(status, error_message); furi_string_free(error_message); return status; }