mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 07:28:36 -07:00
Preload extmainapps
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
54
applications/services/loader/loader_preload.c
Normal file
54
applications/services/loader/loader_preload.c
Normal 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);
|
||||
}
|
||||
6
applications/services/loader/loader_preload.h
Normal file
6
applications/services/loader/loader_preload.h
Normal 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);
|
||||
Reference in New Issue
Block a user