From e3ca293eee588c155eac7b389ab7f7e2768d43e0 Mon Sep 17 00:00:00 2001 From: WillyJL <49810075+Willy-JL@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:42:03 +0100 Subject: [PATCH] Desktop/Loader: Unload animations before loading FAPs (#3573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Desktop: Unload animations before FAP is loaded * Loader: Add API to start detached (returns instantly, queues event) * Desktop: Fix early animation unload deadlocks * Loader: remove redundant event * Bump api symbols Co-authored-by: あく Co-authored-by: SG --- applications/services/desktop/desktop.c | 6 ++- .../desktop/scenes/desktop_scene_main.c | 17 +++--- applications/services/loader/loader.c | 53 ++++++++++++++----- applications/services/loader/loader.h | 17 ++++-- applications/services/loader/loader_i.h | 1 + targets/f18/api_symbols.csv | 3 +- targets/f7/api_symbols.csv | 3 +- 7 files changed, 69 insertions(+), 31 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/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index a659ff4e3..41b1c3e75 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -62,23 +62,18 @@ 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) { - 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, NULL); } else { - loader_start(desktop->loader, LOADER_APPLICATIONS_NAME, NULL, NULL); + loader_start_detached_with_gui_error(desktop->loader, LOADER_APPLICATIONS_NAME, NULL); } } @@ -141,7 +136,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; } diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index 5daf99d1d..1527807cc 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -47,13 +47,8 @@ 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, const char* name, FuriString* error_message) { if(status == LoaderStatusErrorUnknownApp && loader_find_external_application_by_name(name) != NULL) { // Special case for external apps @@ -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, name, 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); @@ -166,11 +181,7 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con Loader* loader = context; - if(thread_state == FuriThreadStateRunning) { - LoaderEvent event; - event.type = LoaderEventTypeApplicationStarted; - furi_pubsub_publish(loader->pubsub, &event); - } else if(thread_state == FuriThreadStateStopped) { + if(thread_state == FuriThreadStateStopped) { LoaderMessage message; message.type = LoaderMessageTypeAppClosed; furi_message_queue_put(loader->queue, &message, FuriWaitForever); @@ -255,6 +266,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 +323,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 +373,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; @@ -528,6 +547,16 @@ 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: { + FuriString* error_message = furi_string_alloc(); + LoaderStatus status = loader_do_start_by_name( + loader, message.start.name, message.start.args, error_message); + loader_show_gui_error(status, message.start.name, error_message); + if(message.start.name) free((void*)message.start.name); + if(message.start.args) free((void*)message.start.args); + furi_string_free(error_message); + break; + } case LoaderMessageTypeShowMenu: loader_do_menu_show(loader); break; diff --git a/applications/services/loader/loader.h b/applications/services/loader/loader.h index cca65628f..ae914117d 100644 --- a/applications/services/loader/loader.h +++ b/applications/services/loader/loader.h @@ -18,7 +18,8 @@ typedef enum { } LoaderStatus; typedef enum { - LoaderEventTypeApplicationStarted, + LoaderEventTypeApplicationBeforeLoad, + LoaderEventTypeApplicationLoadFailed, LoaderEventTypeApplicationStopped } LoaderEventType; @@ -32,7 +33,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); @@ -42,11 +43,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 { diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 72116ccfd..7944bc58f 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,60.5,, +Version,+,60.6,, 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 4ddff921b..8fd9f4c9b 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,60.5,, +Version,+,60.6,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -2139,6 +2139,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*,