From d9f1d39cab64b8fb2fe277c5133a89fe84418434 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Sat, 1 Aug 2026 17:26:43 -0600 Subject: [PATCH 1/2] ADFA-4986: keep the boot gate on re-entry during a live install Tapping the install notification (or relaunching) mid-install re-entered LibraryActivity without EXTRA_INSTALLING, so onCreate took the normal-boot path: its autostart (~3.5s) and safety-dismiss (GATE_SAFETY_MS) timers fired, starting the server mid-provisioning and opening the gate over a system that was still downloading/extracting -> a broken library. - Derive `installing` also from the live install state: EXTRA_INSTALLING || InstallProgressRepository.get().current().isRunning() (DOWNLOADING/EXTRACTING/PROVISIONING), so a live install keeps the progress gate and skips the normal-boot timers. - Defense-in-depth: guard the autostart and safety-dismiss timers with !installing so a race (repo reports running just after onCreate) still can't start the server or lift the gate. Dismissal stays driven by the install SUCCESS terminal path; covers download and extraction. --- .../iiab/controller/redesign/LibraryActivity.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java b/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java index 76c16a46..eb975f0b 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java @@ -132,7 +132,12 @@ protected void onCreate(Bundle savedInstanceState) { // ADFA-4915: extract detail is one middle-ellipsized line so long file names never overlap. installDetail.setMaxLines(1); installDetail.setEllipsize(android.text.TextUtils.TruncateAt.MIDDLE); - installing = getIntent().getBooleanExtra(EXTRA_INSTALLING, false); + // ADFA-4986: also treat a live install as "installing" even when re-entered WITHOUT the extra + // (tapping the install notification, or a relaunch). isRunning() covers DOWNLOADING/EXTRACTING/ + // PROVISIONING. Otherwise the gate takes the normal-boot path and its autostart/safety timers + // start the server and OPEN over a system that is still provisioning -> a broken library. + installing = getIntent().getBooleanExtra(EXTRA_INSTALLING, false) + || InstallProgressRepository.get().current().isRunning(); // The Lottie has a text layer (OPEN/CLOSED sign). Use the system typeface (Noto-based, // global script fallback) so localized words render in any language; a TextDelegate maps // the OPEN/CLOSED source text to the localized @string values. @@ -288,16 +293,18 @@ public android.graphics.Typeface fetchFont(String fontFamily) { // If the stack isn't up after one poll cycle, start it. if (systemInstalled) { main.postDelayed(() -> { - if (!isFinishing() + // ADFA-4986: never autostart the server if an install went live after onCreate. + if (!isFinishing() && !installing && !ServerStateRepository.get().current().alive && targetServerState == null) { serverController.handleServerLaunchClick(findViewById(android.R.id.content)); } }, AUTOSTART_DELAY_MS); } - // Safety: never trap the user behind the gate. + // Safety: never trap the user behind the gate — but ADFA-4986: don't lift it mid-install + // (a live download/extraction drives its own dismissal on SUCCESS via the terminal path). main.postDelayed(() -> { - if (!gateDismissed) { + if (!gateDismissed && !installing) { onServerReady(); } }, systemInstalled ? GATE_SAFETY_MS : NO_SYSTEM_GATE_MS); From 87aff5dbd504ede967cbb068993b20a197be5f07 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Sat, 1 Aug 2026 17:47:19 -0600 Subject: [PATCH 2/2] ADFA-4986: document the mid-install safety-timeout trade-off (review note) --- .../org/iiab/controller/redesign/LibraryActivity.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java b/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java index eb975f0b..be59724a 100644 --- a/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java +++ b/controller/app/src/main/java/org/iiab/controller/redesign/LibraryActivity.java @@ -301,8 +301,13 @@ public android.graphics.Typeface fetchFont(String fontFamily) { } }, AUTOSTART_DELAY_MS); } - // Safety: never trap the user behind the gate — but ADFA-4986: don't lift it mid-install - // (a live download/extraction drives its own dismissal on SUCCESS via the terminal path). + // Safety: never trap the user behind the gate — but ADFA-4986: don't lift it mid-install. + // Deliberate trade-off: while an install is live there is intentionally NO safety-timeout + // dismissal here; the gate is lifted only when the install reaches a terminal state (the + // InstallProgressRepository observer: SUCCESS starts the server then opens, FAILED opens + // to the offline library) — the same contract as the first-run `if (installing)` branch, + // which also has no safety net. A genuinely hung install (no terminal) is a separate + // concern owned by the installer, not something to paper over by opening a broken system. main.postDelayed(() -> { if (!gateDismissed && !installing) { onServerReady();