From 3d48db83c9b70ccefbf576825e49f663c45a5f2f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 12 May 2026 01:16:58 +0100 Subject: [PATCH] Garmin: fix transfer notification leaks and stray pre-start posts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three lifecycle bugs in GarminSupport's transferNotification: * addFileToDownloadList incremented totalSize unconditionally, so a directory listing arriving on connect posted a notification with the unlocalised "Unknown transfer" fallback title before any transfer started. * The start/finish pair gated on gbDevice.isBusy(), which other paths set and clear — start could be skipped while the matching finish ran anyway, or vice versa. * dispose() didn't finish the notification, leaving it pinned after a mid-sync disconnect. Gate the increments and the start/finish pair on the private isBusyFetching flag, and finish + clear the flag in dispose(). --- .../service/devices/garmin/GarminSupport.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java index 5c2ffd4234..4ea492bdc5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java @@ -213,6 +213,10 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC public void dispose() { synchronized (ConnectionMonitor) { LOG.info("Garmin dispose()"); + // Clear any in-flight transfer notification; otherwise a disconnect + // mid-sync leaves the progress notification pinned indefinitely. + transferNotification.finish(); + isBusyFetching = false; if (communicator != null) { communicator.dispose(); } @@ -248,14 +252,16 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC return; } filesToDownload.add(new FileToDownload(directoryEntry)); - if (directoryEntry.getFiletype() != FileType.FILETYPE.DIRECTORY) { + // Only grow the visible total once a transfer is active; before start() + // the initial size is computed from the queue sum in processDownloadQueue. + if (isBusyFetching && directoryEntry.getFiletype() != FileType.FILETYPE.DIRECTORY) { transferNotification.incrementTotalSize(directoryEntry.getFileSize()); } } public void addFileToDownloadList(GdiFileSyncService.File file) { filesToDownload.add(new FileToDownload(file)); - if (file.hasSize()) { + if (isBusyFetching && file.hasSize()) { transferNotification.incrementTotalSize(file.getSize()); } } @@ -866,7 +872,10 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC if (!filesToDownload.isEmpty() && currentlyDownloading == null) { LOG.debug("Processing next file of {}", filesToDownload.size()); - if (!gbDevice.isBusy()) { + // Gate on our own fetch state, not gbDevice.isBusy(): the latter can + // be set/cleared by unrelated paths and would desync the notification's + // start/finish pairing. + if (!isBusyFetching) { LOG.debug("Starting download queue"); isBusyFetching = true; @@ -937,7 +946,7 @@ public class GarminSupport extends AbstractBTLESingleDeviceSupport implements IC if (filesToProcess.isEmpty()) { LOG.debug("No pending files to process"); // No downloaded fit files to process - if (gbDevice.isBusy() && isBusyFetching) { + if (isBusyFetching) { getDevice().unsetBusyTask(); GB.signalActivityDataFinish(getDevice()); transferNotification.finish();