Preload extmainapps

This commit is contained in:
Willy-JL
2023-05-28 00:27:58 +01:00
parent d325a1a43e
commit fc56e39075
8 changed files with 121 additions and 31 deletions

View File

@@ -15,6 +15,7 @@ typedef struct {
const size_t stack_size;
const Icon* icon;
const FlipperApplicationFlag flags;
void* preload;
} FlipperApplication;
typedef void (*FlipperOnStartHook)(void);
@@ -24,32 +25,32 @@ extern const char* FLIPPER_AUTORUN_APP_NAME;
/* Services list
* Spawned on startup
*/
extern const FlipperApplication FLIPPER_SERVICES[];
extern FlipperApplication FLIPPER_SERVICES[];
extern const size_t FLIPPER_SERVICES_COUNT;
/* Apps list
* Spawned by loader
*/
extern const FlipperApplication FLIPPER_APPS[];
extern FlipperApplication FLIPPER_APPS[];
extern const size_t FLIPPER_APPS_COUNT;
/* On system start hooks
* Called by loader, after OS initialization complete
*/
extern const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[];
extern FlipperOnStartHook FLIPPER_ON_SYSTEM_START[];
extern const size_t FLIPPER_ON_SYSTEM_START_COUNT;
/* System apps
* Can only be spawned by loader by name
*/
extern const FlipperApplication FLIPPER_SYSTEM_APPS[];
extern FlipperApplication FLIPPER_SYSTEM_APPS[];
extern const size_t FLIPPER_SYSTEM_APPS_COUNT;
/* Separate scene app holder
* Spawned by loader
*/
extern const FlipperApplication FLIPPER_SCENE;
extern const FlipperApplication FLIPPER_SCENE_APPS[];
extern FlipperApplication FLIPPER_SCENE_APPS[];
extern const size_t FLIPPER_SCENE_APPS_COUNT;
extern const FlipperApplication FLIPPER_ARCHIVE;
@@ -57,5 +58,5 @@ extern const FlipperApplication FLIPPER_ARCHIVE;
/* Settings list
* Spawned by loader
*/
extern const FlipperApplication FLIPPER_SETTINGS_APPS[];
extern FlipperApplication FLIPPER_SETTINGS_APPS[];
extern const size_t FLIPPER_SETTINGS_APPS_COUNT;

View File

@@ -1,6 +1,7 @@
#include "loader.h"
#include "loader_i.h"
#include "loader_menu.h"
#include "loader_preload.h"
#include <applications.h>
#include <furi_hal.h>
#include <core/dangerous_defines.h>
@@ -147,29 +148,38 @@ static Loader* loader_alloc() {
loader->app.insomniac = false;
ExtMainAppList_init(loader->ext_main_apps);
Storage* storage = furi_record_open(RECORD_STORAGE);
FuriString* path = furi_string_alloc();
FuriString* name = furi_string_alloc();
Stream* stream = file_stream_alloc(storage);
if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
while(stream_read_line(stream, path)) {
furi_string_replace_all(path, "\r", "");
furi_string_replace_all(path, "\n", "");
const Icon* icon;
if(!loader_menu_load_fap_meta(storage, path, name, &icon)) continue;
ExtMainAppList_push_back(
loader->ext_main_apps,
(ExtMainApp){
.name = strdup(furi_string_get_cstr(name)),
.path = strdup(furi_string_get_cstr(path)),
.icon = icon});
if(furi_hal_is_normal_boot()) {
Storage* storage = furi_record_open(RECORD_STORAGE);
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
if(FLIPPER_APPS[i].app != NULL) continue;
if(storage_common_exists(storage, FLIPPER_APPS[i].appid)) {
void* preload = loader_preload(storage, FLIPPER_APPS[i].appid);
FLIPPER_APPS[i].preload = preload;
}
}
FuriString* path = furi_string_alloc();
FuriString* name = furi_string_alloc();
Stream* stream = file_stream_alloc(storage);
if(file_stream_open(stream, XTREME_APPS_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
while(stream_read_line(stream, path)) {
furi_string_replace_all(path, "\r", "");
furi_string_replace_all(path, "\n", "");
const Icon* icon;
if(!loader_menu_load_fap_meta(storage, path, name, &icon)) continue;
ExtMainAppList_push_back(
loader->ext_main_apps,
(ExtMainApp){
.name = strdup(furi_string_get_cstr(name)),
.path = strdup(furi_string_get_cstr(path)),
.icon = icon});
}
}
file_stream_close(stream);
stream_free(stream);
furi_string_free(name);
furi_string_free(path);
furi_record_close(RECORD_STORAGE);
}
file_stream_close(stream);
stream_free(stream);
furi_string_free(name);
furi_string_free(path);
furi_record_close(RECORD_STORAGE);
return loader;
}
@@ -214,6 +224,10 @@ static void
FURI_LOG_I(TAG, "Starting %s", app->name);
if(app->app == NULL) {
if(app->preload != NULL) {
loader_preload_start(app->preload, app->appid);
return;
}
args = app->appid;
app = loader_find_application_by_name_in_list(
FAP_LOADER_APP_NAME, FLIPPER_APPS, FLIPPER_APPS_COUNT);

View File

@@ -0,0 +1,54 @@
#include <flipper_application/flipper_application.h>
#include <loader/firmware_api/firmware_api.h>
#include <furi_hal.h>
#include <toolbox/path.h>
#define TAG "Preload"
void* loader_preload(Storage* storage, const char* path) {
FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
size_t start = furi_get_tick();
FURI_LOG_I(TAG, "Loading %s", path);
FlipperApplicationPreloadStatus preload_res = flipper_application_preload(app, path);
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
return NULL;
}
FURI_LOG_I(TAG, "Mapping");
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(app);
if(load_status != FlipperApplicationLoadStatusSuccess) {
const char* err_msg = flipper_application_load_status_to_string(load_status);
FURI_LOG_E(TAG, "Failed to map to memory %s: %s", path, err_msg);
return NULL;
}
FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start));
return app;
}
void loader_preload_start(void* _app, const char* path) {
FlipperApplication* app = _app;
FURI_LOG_I(TAG, "Starting app");
FuriThread* thread = flipper_application_spawn(app, NULL);
/* This flag is set by the debugger - to break on app start */
if(furi_hal_debug_is_gdb_session_active()) {
FURI_LOG_W(TAG, "Triggering BP for debugger");
/* After hitting this, you can set breakpoints in your .fap's code
* Note that you have to toggle breakpoints that were set before */
__asm volatile("bkpt 0");
}
FuriString* app_name = furi_string_alloc();
path_extract_filename_no_ext(path, app_name);
furi_thread_set_appid(thread, furi_string_get_cstr(app_name));
furi_string_free(app_name);
furi_thread_start(thread);
furi_thread_join(thread);
flipper_application_despawn(app);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <storage/storage.h>
void* loader_preload(Storage* storage, const char* path);
void loader_preload_start(void* app, const char* path);