Skip to content

Commit

Permalink
Desktop/Loader: Unload animations before loading FAPs (#3573)
Browse files Browse the repository at this point in the history
* 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: あく <[email protected]>
Co-authored-by: SG <[email protected]>
  • Loading branch information
3 people authored Apr 9, 2024
1 parent 58da27f commit e3ca293
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 31 deletions.
6 changes: 4 additions & 2 deletions applications/services/desktop/desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
17 changes: 6 additions & 11 deletions applications/services/desktop/scenes/desktop_scene_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
}
Expand Down
53 changes: 41 additions & 12 deletions applications/services/loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 13 additions & 4 deletions applications/services/loader/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ typedef enum {
} LoaderStatus;

typedef enum {
LoaderEventTypeApplicationStarted,
LoaderEventTypeApplicationBeforeLoad,
LoaderEventTypeApplicationLoadFailed,
LoaderEventTypeApplicationStopped
} LoaderEventType;

Expand All @@ -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);
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions applications/services/loader/loader_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ typedef enum {
LoaderMessageTypeLock,
LoaderMessageTypeUnlock,
LoaderMessageTypeIsLocked,
LoaderMessageTypeStartByNameDetachedWithGuiError,
} LoaderMessageType;

typedef struct {
Expand Down
3 changes: 2 additions & 1 deletion targets/f18/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -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,,
Expand Down Expand Up @@ -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*,
Expand Down
3 changes: 2 additions & 1 deletion targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -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,,
Expand Down Expand Up @@ -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*,
Expand Down

0 comments on commit e3ca293

Please sign in to comment.