Updater visual fixes (#2391)

* updater: removed unused code; fbt: fixed build error processing in certain cases
* updater: simplified internal pre-update state
* updater: rebalanced stage weights; fixed progress hiccups
This commit is contained in:
hedger 2023-02-13 18:07:53 +04:00 committed by GitHub
parent 5a730e3adc
commit d0c6c3402c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 62 additions and 49 deletions

View File

@ -58,8 +58,12 @@ bool updater_scene_error_on_event(void* context, SceneManagerEvent event) {
} }
void updater_scene_error_on_exit(void* context) { void updater_scene_error_on_exit(void* context) {
furi_assert(context);
Updater* updater = (Updater*)context; Updater* updater = (Updater*)context;
widget_reset(updater->widget); widget_reset(updater->widget);
free(updater->pending_update);
if(updater->loaded_manifest) {
update_manifest_free(updater->loaded_manifest);
}
} }

View File

@ -21,11 +21,9 @@ void updater_scene_loadcfg_apply_callback(GuiButtonType result, InputType type,
void updater_scene_loadcfg_on_enter(void* context) { void updater_scene_loadcfg_on_enter(void* context) {
Updater* updater = (Updater*)context; Updater* updater = (Updater*)context;
UpdaterManifestProcessingState* pending_upd = updater->pending_update = UpdateManifest* loaded_manifest = updater->loaded_manifest = update_manifest_alloc();
malloc(sizeof(UpdaterManifestProcessingState));
pending_upd->manifest = update_manifest_alloc();
if(update_manifest_init(pending_upd->manifest, furi_string_get_cstr(updater->startup_arg))) { if(update_manifest_init(loaded_manifest, furi_string_get_cstr(updater->startup_arg))) {
widget_add_string_element( widget_add_string_element(
updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update"); updater->widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, "Update");
@ -37,7 +35,7 @@ void updater_scene_loadcfg_on_enter(void* context) {
32, 32,
AlignCenter, AlignCenter,
AlignCenter, AlignCenter,
furi_string_get_cstr(pending_upd->manifest->version), furi_string_get_cstr(loaded_manifest->version),
true); true);
widget_add_button_element( widget_add_button_element(
@ -95,13 +93,12 @@ bool updater_scene_loadcfg_on_event(void* context, SceneManagerEvent event) {
} }
void updater_scene_loadcfg_on_exit(void* context) { void updater_scene_loadcfg_on_exit(void* context) {
furi_assert(context);
Updater* updater = (Updater*)context; Updater* updater = (Updater*)context;
if(updater->pending_update) {
update_manifest_free(updater->pending_update->manifest);
furi_string_free(updater->pending_update->message);
}
widget_reset(updater->widget); widget_reset(updater->widget);
free(updater->pending_update);
if(updater->loaded_manifest) {
update_manifest_free(updater->loaded_manifest);
}
} }

View File

@ -33,12 +33,6 @@ typedef enum {
UpdaterCustomEventSdUnmounted, UpdaterCustomEventSdUnmounted,
} UpdaterCustomEvent; } UpdaterCustomEvent;
typedef struct UpdaterManifestProcessingState {
UpdateManifest* manifest;
FuriString* message;
bool ready_to_be_applied;
} UpdaterManifestProcessingState;
typedef struct { typedef struct {
// GUI // GUI
Gui* gui; Gui* gui;
@ -49,7 +43,7 @@ typedef struct {
UpdaterMainView* main_view; UpdaterMainView* main_view;
UpdaterManifestProcessingState* pending_update; UpdateManifest* loaded_manifest;
UpdatePrepareResult preparation_result; UpdatePrepareResult preparation_result;
UpdateTask* update_task; UpdateTask* update_task;

View File

@ -41,22 +41,22 @@ typedef struct {
static const UpdateTaskStageGroupMap update_task_stage_progress[] = { static const UpdateTaskStageGroupMap update_task_stage_progress[] = {
[UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0),
[UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5), [UpdateTaskStageReadManifest] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 45),
[UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 15), [UpdateTaskStageLfsBackup] = STAGE_DEF(UpdateTaskStageGroupPreUpdate, 5),
[UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15), [UpdateTaskStageRadioImageValidate] = STAGE_DEF(UpdateTaskStageGroupRadio, 15),
[UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), [UpdateTaskStageRadioErase] = STAGE_DEF(UpdateTaskStageGroupRadio, 35),
[UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 80), [UpdateTaskStageRadioWrite] = STAGE_DEF(UpdateTaskStageGroupRadio, 60),
[UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 60), [UpdateTaskStageRadioInstall] = STAGE_DEF(UpdateTaskStageGroupRadio, 30),
[UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 80), [UpdateTaskStageRadioBusy] = STAGE_DEF(UpdateTaskStageGroupRadio, 5),
[UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 10), [UpdateTaskStageOBValidation] = STAGE_DEF(UpdateTaskStageGroupOptionBytes, 2),
[UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 50), [UpdateTaskStageValidateDFUImage] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30),
[UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 200), [UpdateTaskStageFlashWrite] = STAGE_DEF(UpdateTaskStageGroupFirmware, 150),
[UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 30), [UpdateTaskStageFlashValidate] = STAGE_DEF(UpdateTaskStageGroupFirmware, 15),
[UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 30), [UpdateTaskStageLfsRestore] = STAGE_DEF(UpdateTaskStageGroupPostUpdate, 5),
[UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255), [UpdateTaskStageResourcesUpdate] = STAGE_DEF(UpdateTaskStageGroupResources, 255),
[UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5), [UpdateTaskStageSplashscreenInstall] = STAGE_DEF(UpdateTaskStageGroupSplashscreen, 5),

View File

@ -41,6 +41,14 @@ static bool update_task_pre_update(UpdateTask* update_task) {
return success; return success;
} }
typedef enum {
UpdateTaskResourcesWeightsFileCleanup = 20,
UpdateTaskResourcesWeightsDirCleanup = 20,
UpdateTaskResourcesWeightsFileUnpack = 60,
} UpdateTaskResourcesWeights;
#define UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT 90
typedef struct { typedef struct {
UpdateTask* update_task; UpdateTask* update_task;
int32_t total_files, processed_files; int32_t total_files, processed_files;
@ -54,33 +62,36 @@ static bool update_task_resource_unpack_cb(const char* name, bool is_directory,
update_task_set_progress( update_task_set_progress(
unpack_progress->update_task, unpack_progress->update_task,
UpdateTaskStageProgress, UpdateTaskStageProgress,
/* For this stage, last 70% of progress = extraction */ /* For this stage, last progress segment = extraction */
30 + (unpack_progress->processed_files * 70) / (unpack_progress->total_files + 1)); (UpdateTaskResourcesWeightsFileCleanup + UpdateTaskResourcesWeightsDirCleanup) +
(unpack_progress->processed_files * UpdateTaskResourcesWeightsFileUnpack) /
(unpack_progress->total_files + 1));
return true; return true;
} }
static void static void update_task_cleanup_resources(UpdateTask* update_task, const uint32_t n_tar_entries) {
update_task_cleanup_resources(UpdateTask* update_task, uint32_t n_approx_file_entries) {
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage); ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(update_task->storage);
do { do {
FURI_LOG_I(TAG, "Cleaning up old manifest"); FURI_LOG_D(TAG, "Cleaning up old manifest");
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) { if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("Manifest"))) {
FURI_LOG_W(TAG, "No existing manifest"); FURI_LOG_W(TAG, "No existing manifest");
break; break;
} }
/* We got # of entries in TAR file. Approx 1/4th is dir entries, we skip them */ const uint32_t n_approx_file_entries =
n_approx_file_entries = n_approx_file_entries * 3 / 4 + 1; n_tar_entries * UPDATE_TASK_RESOURCES_FILE_TO_TOTAL_PERCENT / 100 + 1;
uint32_t n_processed_files = 0; uint32_t n_dir_entries = 1;
ResourceManifestEntry* entry_ptr = NULL; ResourceManifestEntry* entry_ptr = NULL;
uint32_t n_processed_entries = 0;
while((entry_ptr = resource_manifest_reader_next(manifest_reader))) { while((entry_ptr = resource_manifest_reader_next(manifest_reader))) {
if(entry_ptr->type == ResourceManifestEntryTypeFile) { if(entry_ptr->type == ResourceManifestEntryTypeFile) {
update_task_set_progress( update_task_set_progress(
update_task, update_task,
UpdateTaskStageProgress, UpdateTaskStageProgress,
/* For this stage, first 20% of progress = cleanup files */ /* For this stage, first pass = old manifest's file cleanup */
(n_processed_files++ * 20) / (n_approx_file_entries + 1)); (n_processed_entries++ * UpdateTaskResourcesWeightsFileCleanup) /
n_approx_file_entries);
FuriString* file_path = furi_string_alloc(); FuriString* file_path = furi_string_alloc();
path_concat( path_concat(
@ -88,16 +99,21 @@ static void
FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path)); FURI_LOG_D(TAG, "Removing %s", furi_string_get_cstr(file_path));
storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path)); storage_simply_remove(update_task->storage, furi_string_get_cstr(file_path));
furi_string_free(file_path); furi_string_free(file_path);
} else if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
n_dir_entries++;
} }
} }
n_processed_entries = 0;
while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) { while((entry_ptr = resource_manifest_reader_previous(manifest_reader))) {
if(entry_ptr->type == ResourceManifestEntryTypeDirectory) { if(entry_ptr->type == ResourceManifestEntryTypeDirectory) {
update_task_set_progress( update_task_set_progress(
update_task, update_task,
UpdateTaskStageProgress, UpdateTaskStageProgress,
/* For this stage, second 10% of progress = cleanup directories */ /* For this stage, second 10% of progress = cleanup directories */
(n_processed_files++ * 10) / (n_approx_file_entries + 1)); UpdateTaskResourcesWeightsFileCleanup +
(n_processed_entries++ * UpdateTaskResourcesWeightsDirCleanup) /
n_dir_entries);
FuriString* folder_path = furi_string_alloc(); FuriString* folder_path = furi_string_alloc();
File* folder_file = storage_file_alloc(update_task->storage); File* folder_file = storage_file_alloc(update_task->storage);

View File

@ -106,6 +106,7 @@ void tar_archive_set_file_callback(TarArchive* archive, tar_unpack_file_cb callb
static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) { static int tar_archive_entry_counter(mtar_t* tar, const mtar_header_t* header, void* param) {
UNUSED(tar); UNUSED(tar);
UNUSED(header); UNUSED(header);
furi_assert(param);
int32_t* counter = param; int32_t* counter = param;
(*counter)++; (*counter)++;
return 0; return 0;

View File

@ -1,6 +1,6 @@
from SCons.Builder import Builder from SCons.Builder import Builder
from SCons.Action import Action from SCons.Action import Action
from SCons.Script import Delete, Mkdir, GetBuildFailures from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten
import multiprocessing import multiprocessing
import webbrowser import webbrowser
import atexit import atexit
@ -30,13 +30,14 @@ def atexist_handler():
return return
for bf in GetBuildFailures(): for bf in GetBuildFailures():
if bf.node.exists and bf.node.name.endswith(".html"): for node in Flatten(bf.node):
# macOS if node.exists and node.name.endswith(".html"):
if sys.platform == "darwin": # macOS
subprocess.run(["open", bf.node.abspath]) if sys.platform == "darwin":
else: subprocess.run(["open", node.abspath])
webbrowser.open(bf.node.abspath) else:
break webbrowser.open(node.abspath)
break
def generate(env): def generate(env):