v1.0.2: stable release signature, idempotent Stop, top-level Settings for CA install (#33)

Three fixes + one behaviour change from v1.0.1 reports.

APK signature is now stable (release.jks committed)
----------------------------------------------------
v1.0.0 and v1.0.1 signed release APKs with Gradle's
auto-generated debug keystore, which is randomly generated per
machine and per CI runner. Result: every upgrade failed with
INSTALL_FAILED_UPDATE_INCOMPATIBLE and users had to uninstall
first. Unfixable without a stable key.

android/app/release.jks now holds that key, committed to the
repo with the password in plaintext in build.gradle.kts. This
is fine for a FOSS sideload project without a Play Store
identity — the trust model is "trust the source tree you
pulled from," not "trust the key we hold." Anyone forking and
shipping a rebranded build should generate their own key.

One-time cost: v1.0.1 → v1.0.2 STILL requires uninstall,
because we're switching signature keys. Every upgrade from
v1.0.2 onward is clean.

Stop no longer (sometimes) closes the app
-----------------------------------------
teardown() is reachable from three paths on two threads:
  1. ACTION_STOP onStartCommand branch  (mhrv-teardown worker)
  2. onDestroy after stopSelf            (main thread)
  3. VpnService revocation out-of-band   (main thread)
Running the full native cleanup sequence twice races the two
threads through Tun2proxy.stop() → fd.close() →
Native.stopProxy(handle) on state that's already been
nullified — SIGSEGV source, user-visible as "tap Stop, app
disappears."

New AtomicBoolean `tornDown` gates entry: first caller wins,
every subsequent caller logs "teardown: already done" and
returns. onDestroy also wraps the call in try/catch — crashing
out of onDestroy takes the whole process with it, which is
exactly the bug we're trying to fix. Smoke-tested on emulator:
teardown now logs

  teardown: begin caller=mhrv-teardown
  ... clean sequence ...
  teardown: done
  onDestroy entered
  teardown: already done, skipping (caller=main)
  onDestroy done

with PID unchanged throughout.

CA install now routes to the Settings search
--------------------------------------------
Old flow: `Settings.ACTION_SECURITY_SETTINGS` deep-link, then
walk "Encryption & credentials → Install a certificate →
CA certificate". That path varies wildly between OEMs (Samsung
buries it under "Biometrics and security → Other security
settings"; Xiaomi under "Passwords & Security → Privacy"; Pixel
splits it between "More security settings" and "Privacy
controls" depending on Android version). Users got lost.

New flow: open the top-level Settings app
(`Settings.ACTION_SETTINGS`) and instruct the user to use the
Settings search bar to find "CA certificate". Search is
consistent across OEMs and Android versions; the menu paths
are not. Dialog, snackbar, and `docs/android.md` copy all
updated to match.

Version bump: 1.0.1 → 1.0.2 (versionCode 101 → 102).
releases/mhrv-rs-android-universal-v1.0.1.apk replaced with
the v1.0.2 build.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Shin (Former Aleph)
2026-04-23 04:19:52 +03:00
committed by GitHub
parent b734f41faa
commit 64409f6b41
10 changed files with 114 additions and 51 deletions
+2 -5
View File
@@ -89,12 +89,9 @@ This step is annoying but unavoidable: the proxy terminates TLS on your behalf s
1. In the app, tap **Install MITM certificate**.
2. Read the confirmation dialog — it shows the certificate fingerprint (handy to verify later). Tap **Install**.
3. The app saves `Downloads/mhrv-ca.crt` and deep-links Android into **Settings → Security & privacy** (or similar; wording varies by OEM).
3. The app saves `Downloads/mhrv-ca.crt` and opens the top-level **Settings** app.
4. If you don't have a screen lock: Android will prompt you to set one. **You have to.** User CAs require a screen lock, period. Set PIN/pattern/password. You can remove it after install if you really want; the cert stays installed.
5. In Settings, navigate: **Encryption & credentials → Install a certificate → "CA certificate"**.
- On Pixel / stock Android: `Security → More security settings → Encryption & credentials → Install a certificate → CA certificate`.
- On Samsung: `Biometrics and security → Other security settings → Install from device storage → CA certificate`.
- On Xiaomi/MIUI: `Passwords & Security → Privacy → Encryption & credentials → Install a certificate → CA certificate`.
5. In Settings, tap the **search bar at the top** and type `CA certificate`. Pick the result labelled **"CA certificate"** (or on some OEMs "Install CA certificate"). The menu path varies wildly between Pixel / Samsung / Xiaomi / etc., which is why searching beats navigating.
- **Do NOT** pick "VPN & app user certificate" or "Wi-Fi certificate" — wrong category, won't work.
6. Android warns you: **"Your network may be monitored by an unknown third party"**. That's us. Tap **Install anyway**.
7. Pick **Downloads** → tap **mhrv-ca.crt**. Give it a friendly name (or accept the default). Tap **OK**.