13.14.2
Changelog
Changes in v13.14.1..HEAD:
Highlights
- Waze Bridge Repair Survives Process Death — the repair target lived only in memory, and a repair spans a system uninstall that puts Hush in the background — where it can be killed. Reproduced on a real device: repair started, bridge removed, process recreated, and the repair was simply forgotten, leaving the bridge gone and nothing installing the bundled one. The target is now persisted (with a 15-minute staleness rule), so the second half runs whichever process performs it. (Hush)
- Bridge Installs Are Patient Enough for the Prompts They Cause — a Bridge install on a real device is not one dialog: it is the installer, then Play Protect's "Scan app", then the vendor's own "Continue installation". Three prompts took longer than the ~33s the attempt allowed, so a working install was reported as a failure and only the retry rescued it. The wait is now ~46s per pass, counted from measurement rather than guesswork. (Hush)
- A Verification Completed in Settings Now Wakes Playback — the Audio Sources screen hosted its own challenge and, unlike the overlay and the browser route, never reported success. A track parked waiting for that source was never resumed, the "SpotiFLAC needs verification" card stayed up over a source that was already fine, and the freshly earned session was never mirrored into the vault. All three surfaces now report through one entry point. (Hush)
- A Release Gate for the Waze Bridge Lifecycle — a shell-driven smoke test that exercises detect → remove → install → verify → update in place → uninstall → repair → restore against a real device, with machine-readable verdicts and its own exit codes, so the lifecycle that breaks users on release day is checked before a release rather than after. (Hush)
Waze Bridge
- Repair target persisted across process restarts —
WazeBridgeRepairwrites the Bridge it is repairing to storage and restores it on the next start, bounded byMAX_AGE_MSso a repair from an unrelated session is never resumed. Verified on device by force-stopping the app between the removal and the completion: the new process reportedrepair complete: com.spotify.music is gone; installing the bundled bridgeand installed 1711. (Hush) - Install attempt watches long enough for the platform's own prompt chain —
WazeBridgeInstallAttemptpolls for ~46s per pass instead of ~33s, keeping the single automatic retry. The wait still ends the moment an install lands, so a prompt install is unaffected. (Hush) - A platform-aborted install is named, not guessed at — when the device's package verifier gives up on a sideloaded Bridge, or the platform refuses a correctly-signed Bridge because it still holds a record of the one that was removed (
INSTALL_FAILED_DUPLICATE_PERMISSION,INSTALL_FAILED_UPDATE_INCOMPATIBLE), the attempt reports that condition with its evidence instead of a bare failure. (Hush)
Verification
- One entry point for "this source is verified" —
SpotiFLAutoVerifier.notifyVerifiedis now what every surface calls (the automatic overlay, the browser route, the Audio Sources challenge, and the grant deep link), so a verification cannot complete without waking a parked track and clearing the notice that asked for it. Safe for a source the automatic queue never held: it records the success and resumes playback without disturbing a run in flight. (Hush) - The automatic queue can no longer be corrupted by its own callers —
SpotiFLAutoVerifierkept its queue, cooldowns and attempt map in plainLinkedHashSet/HashMapfields while being finished from five places on five threads (playback, the runtime bridge's preflight, the browser route's process-wideDispatchers.Defaultscope, and the two in-app screens on main). A mutation from two of those at once could lose an entry or throw out ofqueued(), and a source leftactiveforever makes every later source wait behind it — which is exactly what "verification sometimes does nothing" looks like. The collections are guarded by one lock, held only around themselves so a re-entering callback cannot deadlock, and the ticker increment is inside the same critical section because two surfaces can report the same verification at once. Covered by a concurrency regression test. (Hush) - "Re-verify" is only offered when there is a check to raise — a source with a healthy session has nothing to solve (the runtime keeps the challenge it registered, and that one is already spent), so the button could only answer "already verified", which reads as a broken button. It now appears for a source that needs a check, or one whose session has lapsed; routine renewal stays with "Renew now". (Hush)
- Manual and automatic routes unchanged in behaviour — the in-app WebView remains the default wherever the engine can run Cloudflare's check; the browser route stays the one-tap alternative that hands its grant back on its own (no code to copy), and the only route on a device whose embedded WebView is older than Cloudflare supports. (Hush)
Release Engineering
scripts/waze-bridge-lifecycle-smoke.sh— drives the debug-only repair receiver and reports one machine-readable verdict per step, with--jsonfor a CI consumer and exit codes0(passed) /1(failed) /2(usage or device) /3(the device's own package verifier blocked a step, so nothing was proved either way). It taps only system-owned prompts, never Hush's own UI. (Hush)- In-place update is actually testable — the platform refuses a version downgrade over an installed release-signed package, so the leg stages an older Bridge on a clean slate and then requires Hush to replace it, proving the update was in place (the platform's
firstInstallTimeis unchanged) rather than a remove-and-reinstall. (Hush) - Repair can be exercised on demand —
--mismatch-apkstages a differently-signed Bridge for the repair leg, moving the other Bridges aside first (all three declare the same signature-level permission, so a foreign-signed one cannot coexist with them) and restoring them afterwards. (Hush) - A failing run still restores the Bridge under test — so a release gate can never leave a device without a Bridge. (Hush)
Housekeeping
- Version bumped to 13.14.2 (versionCode 172, app + waze-shim). (Hush)
- Unit tests pass (407 tests, all green), including new coverage for the resumable repair target and for a verification completed outside the automatic queue. (Hush)
- Lint
fossMobileUniversalDebug: 0 errors. Debug build installed and exercised on a connected device: all three BridgesBRIDGE_CURRENTat 1711, and four SpotiFLAC gateway sessions self-renewing with no manual check required. (Hush)
Upstream credits
Hush is built on ArchiveTune and combines features, fixes, and UI from several open-source YouTube Music clients—including Metrolist, Vivi Music, and Echo Music. Those projects are credited below; their licenses and copyright notices are preserved in source.
Thank you to the maintainers and contributors of every project listed above.