feat(controller): in-app OTA update progress dialog + cancel (F15, PR B)#32
Merged
Conversation
…X (PR B) First piece of PR B (UpdateViewModel + in-app progress/cancel/state UX, on top of PR A #30). Pure domain DownloadProgress (status + downloaded/total bytes, percent with clamping, indeterminate + terminal helpers), unit-tested. ViewModel, data source (DownloadManager query), cancel, and the in-app progress UI follow.
…ress (PR B) Presentation/data slice for PR B (on top of PR A #30), behavior-neutral until wired: - domain: OtaDownloadGateway port (query progress / cancel). - data: DownloadManagerGateway (queries DownloadManager COLUMN_STATUS / bytes; remove() to cancel). - presentation: UpdateUiState (IDLE/DOWNLOADING/VERIFYING/READY/INSTALLING/ERROR + percent, with pure fromDownload mapping) + UpdateViewModel (polls ~400ms while downloading; cancel) + UpdateViewModelFactory. Unit-tested (UpdateUiStateTest + DownloadProgressTest). Next: modal progress dialog layout + MainActivity wiring (keep system notification).
Wires the PR B slice into the real OTA flow (modal dialog; system notification kept): - startDownload: track(id) + show modal dialog after enqueue. - downloadReceiver: on success -> verifyDownloadedApk() -> VM.onReady() (or onError). - split installApk() into verifyDownloadedApk() (exists + same-cert signature) and launchInstaller() (unknown-sources check + FileProvider install), driven by the dialog's Install button; VM.onInstalling() on launch. - dialog: determinate bar + % while downloading, indeterminate for verify/install, '✓ Signature verified' ready state; Cancel -> VM.cancel() -> DownloadManager.remove(id). - new layout dialog_ota_progress.xml; 9 strings x 6 locales (escaped).
luisguzman-adfa
added a commit
that referenced
this pull request
Jun 24, 2026
- Status banner: Phase 0 done + Phase 1 core-complete; Phase 2 not started (~37 raw threads); Phase 3 partial (slices land but god classes grew — DeployFragment ~3022, MainActivity ~2384); M15 done, M8/M9 open. - Phase 1 line: F15 A+B (#30/#32) + rootfs validation (#31) + integrity (#37) done. - Integrity/writer entry: marked DONE via #37 (was 'next PR'). - F4 + M7: confirmed mitigated by inspection (onPause teardown + remove-before-post). - Lint workaround: added root-cause analysis with concrete carve targets (addNewTerminalSession ~727 LOC; DeployFragment bind* methods) for D1/F1. Docs only; no code change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR B — in-app OTA update progress UX (stacked on #30 / PR A)
Builds the user-facing half of the OTA updater on top of PR A (
feat/ota-updater-security-redesign, #30). This branch is based on it, so the diff here is PR B only.What this adds
A modal progress dialog that appears when an update download starts, showing live progress and a Cancel/Install flow. The DownloadManager system notification is kept alongside it.
State machine:
IDLE → DOWNLOADING → VERIFYING → READY → INSTALLING(orERROR).%while the total size is known; indeterminate otherwise. Cancel removes the download (DownloadManager.remove(id)).Clean Architecture slice (
org.iiab.controller.update)DownloadProgress(pure value object),OtaDownloadGateway(port: query/cancel). Unit-tested, no Android deps.DownloadManagerGatewayimplements the port overDownloadManager(COLUMN_STATUS/ bytes;remove()to cancel).UpdateUiState(with purefromDownloadmapping),UpdateViewModel(androidx.lifecycle, polls ~400ms,cancel),UpdateViewModelFactory(manual DI, mirrors the other slices).MainActivity wiring
startDownload:track(id)+ show dialog afterenqueue.downloadReceiver: on success →verifyDownloadedApk()→onReady()/onError().installApk()split intoverifyDownloadedApk()(exists + same-cert signature) andlaunchInstaller()(unknown-sources check + FileProvider install), driven by the dialog's Install button.i18n
9 new strings added to all 6 locales (en/es/fr/pt/hi/ru), apostrophes escaped for AAPT2.
Tests
DownloadProgressTest(percent clamp/round, indeterminate, terminal, negative clamp) andUpdateUiStateTest(running→downloading, indeterminate, success→verifying, failed→error). Pure JVM.Verification done locally
Brace balance, all 6 string XMLs parse, and all new
R.string/R.id/R.layoutrefs resolve. Full lint/compile via CI gate.Author/copyright: AppDevForAll.