Skip to content

Shizuku stability, IME bubble dual-mode, Samsung USB advisory#42

Merged
Suprhimp merged 5 commits into
masterfrom
shizuku-stability
Apr 24, 2026
Merged

Shizuku stability, IME bubble dual-mode, Samsung USB advisory#42
Suprhimp merged 5 commits into
masterfrom
shizuku-stability

Conversation

@Suprhimp
Copy link
Copy Markdown
Owner

Supersedes #41 (closed as a side-effect of renaming the branch from devplanningo/shizuku-stabilityshizuku-stability; all commits preserved). Adds IME bubble dual-mode fix and Shizuku token-mismatch recovery on top of the original scope.

Summary

Shizuku OEM-kill hardening

  • Dual-layer watchdog (outer supervisor + inner respawner) keeps shizuku_server alive through Samsung-class OEM kills.
  • Acquire WIFI_MODE_FULL_HIGH_PERF WifiLock so the radio doesn't sleep on screen-off, preventing the AdbDebuggingManager "Network disconnected. Disabling adbwifi" cascade that killed Shizuku within 1-10s of lock on Galaxy Flip.
  • Quick-death counter: if Shizuku's binder dies <15s after being received 3 times in a row, stop auto-relaunching the manager and post an ongoing notification explaining the user's options. Breaks the relaunch loop on unrecoverable kills.

Shizuku token mismatch after reinstall (new)

  • On install/update (including adb install -r with no version bump), shizuku_server holds a stale user-service record pointing at the previous process's dead binder. The next bindUserService either never delivers onServiceConnected or connects then immediately disconnects.
  • Detect reinstall via PackageInfo.lastUpdateTime vs. a saved SharedPrefs value on init; when they differ, call unbindUserService(args, conn, remove=true) before the first bind so the stale record is wiped.
  • Also watch the user-service ServiceConnection: sessions that end within 3s trigger one automatic force unbind-rebind (capped at two retries) to cover cases the reinstall detector missed.

Samsung USB config advisory (new)

  • Samsung's Default USB Configuration = File Transfer (MTP/PTP) restarts USB on every screen lock, which kills Shizuku even before our WifiLock can help. Classify the device's persist.sys.usb.config at startup and surface a dialog prompting the user to switch to "Charging only", with a shortcut to Developer Options. Respects a don't-show-again flag.

IME bubble mirrors phone keyboard visibility strictly

  • Single-VD mode now relies on the global IME state (mInputShown / mShowRequested) alone, so the bubble only appears when the phone keyboard actually shows. The dumpsys window imeInputTarget fallback is gated to true Samsung dual-VD where cross-display focus mismatch makes the global state lie.
  • 200ms hide watchdog while the bubble is visible so it disappears as soon as the keyboard dismisses (previously felt laggy).
  • bubbleClosed signal from browser → server suppresses the hasTarget fallback until the user re-engages (touch-down on the mirror), so a user-dismissed bubble doesn't immediately re-open.

Misc

  • Client-side frame-arrival watchdog so a silently stalled video socket (Shizuku death, encoder stall, VD end) no longer freezes the last frame.
  • Relocate Home / density / playback-profile controls into a collapsible overlay menu; move split ratio controls into the same overlay panel.

Test plan

  • ./gradlew :app:assembleDebug green
  • ./gradlew :app:testDebugUnitTest — Shizuku + utils tests pass (ShizukuReinstallDetectorTest, UsbConfigCheckerTest, ImeTargetParserTest)
  • Galaxy Flip (SM-F741N, Android 14): WiFi on + USB unplugged + screen lock — Shizuku now survives ~40s (previously 1-10s). ShizukuWifiLock acquired confirmed in logcat; no Network disconnected. Disabling adbwifi event.
  • adb install -r reinstall flow: Reinstall detected (saved=... current=...) — force unbind before first bind logged; user service reconnects without manual Shizuku-manager restart.
  • Single-VD bubble: only shows when phone keyboard actually appears; hides within 200ms of keyboard dismiss; re-tap after manual close works.
  • App-switch cleanup verified: on goHome the previous app is am force-stopped; only the active app's process remains on the VD.
  • Follow-up: a separate death trigger still kicks in ~24s after screen lock on some devices (likely Samsung doze/process freezer). Give-up notification remains the user-facing mitigation there.

🤖 Generated with Claude Code

Suprhimp and others added 5 commits April 18, 2026 17:04
Addresses repeated Shizuku death on Samsung (FreecessController kills
shell-UID processes aggressively, taking both shizuku_server and the
single-layer watchdog with it). Users had to re-run wireless-debugging
setup every time the hotspot transition killed the server.

New resilience stack:
- Dual-layer watchdog (outer supervises inner; inner supervises
  shizuku_server) spawned with nohup+setsid for session detachment.
- Heartbeat file written every 5s; 15s staleness threshold triggers
  reinstall.
- Best-effort fortification: doze whitelist, appops RUN_ANY/IN_BG,
  oom_score_adj = -900 on shizuku_server and the watchdogs.
- Staged rollback-safe install: write .new scripts, rename, teardown
  old processes via PID-file + exact argv-element cmdline match,
  spawn outer, verify.
- ShellDiag marker protocol (__STEP_BEGIN__/__STEP_END__ rc=$?) so
  stdout-only IPC can recover per-step exit codes and fail fast.
- Exact argv-element cmdline validation via tr '\0' '\n' | grep -Fxq
  (no substring or space-boundary heuristics).
- Single synchronized entrypoint ensureShizukuHardened() called from
  MainActivity and MirrorForegroundService.
- Legacy single-script watchdog cleanup via /proc/*/cmdline
  enumeration.
- SHIZUKU_FORTIFIED diagnostic event (informational; classifier ignores).

45 unit tests: 21 new for ShellDiag + ShizukuHealth, 3 regression
tests for DisconnectCauseClassifier's treatment of the new event.

Reviewed via DUUL (plan + code phases, approved).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Acquire WIFI_MODE_FULL_HIGH_PERF lock in ShizukuSetup so wireless
  ADB does not get torn down by the radio sleeping on screen-off
  (fixes the AdbDebuggingManager "Network disconnected. Disabling
  adbwifi" cascade that killed Shizuku within 1-10s of lock).
- Add quick-death counter: if the binder dies <15s after being
  received 3 times in a row, stop auto-relaunching the Shizuku
  manager and post a high-priority ongoing notification telling the
  user to plug USB back in or keep the screen on. Avoids an infinite
  relaunch loop on OEM kill.
- Add client-side frame-arrival watchdog so a silently stalled
  video socket (Shizuku death, encoder stall, VD end) no longer
  freezes the last frame on screen.
- Relocate Home / density / playback-profile controls into a
  collapsible overlay menu to tidy the on-screen chrome.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Samsung's Default USB Configuration = File Transfer (MTP/PTP) causes the
OS to restart USB on every screen lock, killing Shizuku. Detect the
misconfig at startup and prompt the user to switch to Charging only,
with a shortcut to Developer Options. Respects a don't-show-again flag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Single-VD mode: rely on the global IME state (mInputShown / mShowRequested)
alone so the bubble only appears when the phone keyboard actually shows.
The dumpsys window imeInputTarget fallback is reserved for true Samsung
dual-VD where cross-display focus mismatch makes the global state lie.

Add a 200ms hide watchdog while the bubble is visible so it disappears as
soon as the keyboard dismisses, and a browser→server bubbleClosed signal
that suppresses the hasTarget fallback until the user re-engages, so a
user-dismissed bubble doesn't immediately re-open.

Also move the split ratio controls into the overlay menu panel instead of
the separate floating toolbar/tap-zone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
After an install/update (including adb install -r with no version bump),
shizuku_server holds a cached user-service record pointing at our previous
process's binder. Without intervention, the next bindUserService call
either never delivers onServiceConnected or connects then immediately
disconnects — the symptom users see as "Shizuku not responding until I
restart the manager".

Detect reinstall by comparing PackageInfo.lastUpdateTime against a saved
SharedPreferences value on init, and when they differ call
unbindUserService(args, conn, remove=true) before the first bind so the
stale record is wiped. Also watch the user-service ServiceConnection:
sessions that end within 3s of connecting trigger one automatic force
unbind-rebind (capped at two retries) to cover the case where the stale
record slipped past detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Suprhimp Suprhimp added the minor Version bump: minor (1.2.3 → 1.3.0) label Apr 24, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website Ready Ready Preview, Comment Apr 24, 2026 3:26am

@Suprhimp Suprhimp merged commit 549c15d into master Apr 24, 2026
5 checks passed
@Suprhimp Suprhimp deleted the shizuku-stability branch April 24, 2026 07:20
Suprhimp added a commit that referenced this pull request Apr 24, 2026
* Harden Shizuku against OEM kills with dual-layer watchdog

Addresses repeated Shizuku death on Samsung (FreecessController kills
shell-UID processes aggressively, taking both shizuku_server and the
single-layer watchdog with it). Users had to re-run wireless-debugging
setup every time the hotspot transition killed the server.

New resilience stack:
- Dual-layer watchdog (outer supervises inner; inner supervises
  shizuku_server) spawned with nohup+setsid for session detachment.
- Heartbeat file written every 5s; 15s staleness threshold triggers
  reinstall.
- Best-effort fortification: doze whitelist, appops RUN_ANY/IN_BG,
  oom_score_adj = -900 on shizuku_server and the watchdogs.
- Staged rollback-safe install: write .new scripts, rename, teardown
  old processes via PID-file + exact argv-element cmdline match,
  spawn outer, verify.
- ShellDiag marker protocol (__STEP_BEGIN__/__STEP_END__ rc=$?) so
  stdout-only IPC can recover per-step exit codes and fail fast.
- Exact argv-element cmdline validation via tr '\0' '\n' | grep -Fxq
  (no substring or space-boundary heuristics).
- Single synchronized entrypoint ensureShizukuHardened() called from
  MainActivity and MirrorForegroundService.
- Legacy single-script watchdog cleanup via /proc/*/cmdline
  enumeration.
- SHIZUKU_FORTIFIED diagnostic event (informational; classifier ignores).

45 unit tests: 21 new for ShellDiag + ShizukuHealth, 3 regression
tests for DisconnectCauseClassifier's treatment of the new event.

Reviewed via DUUL (plan + code phases, approved).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Hold Shizuku alive across screen-off via WifiLock + loop defense

- Acquire WIFI_MODE_FULL_HIGH_PERF lock in ShizukuSetup so wireless
  ADB does not get torn down by the radio sleeping on screen-off
  (fixes the AdbDebuggingManager "Network disconnected. Disabling
  adbwifi" cascade that killed Shizuku within 1-10s of lock).
- Add quick-death counter: if the binder dies <15s after being
  received 3 times in a row, stop auto-relaunching the Shizuku
  manager and post a high-priority ongoing notification telling the
  user to plug USB back in or keep the screen on. Avoids an infinite
  relaunch loop on OEM kill.
- Add client-side frame-arrival watchdog so a silently stalled
  video socket (Shizuku death, encoder stall, VD end) no longer
  freezes the last frame on screen.
- Relocate Home / density / playback-profile controls into a
  collapsible overlay menu to tidy the on-screen chrome.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Advise on Samsung USB config that kills Shizuku on screen lock

Samsung's Default USB Configuration = File Transfer (MTP/PTP) causes the
OS to restart USB on every screen lock, killing Shizuku. Detect the
misconfig at startup and prompt the user to switch to Charging only,
with a shortcut to Developer Options. Respects a don't-show-again flag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Mirror phone keyboard visibility strictly in the input bubble

Single-VD mode: rely on the global IME state (mInputShown / mShowRequested)
alone so the bubble only appears when the phone keyboard actually shows.
The dumpsys window imeInputTarget fallback is reserved for true Samsung
dual-VD where cross-display focus mismatch makes the global state lie.

Add a 200ms hide watchdog while the bubble is visible so it disappears as
soon as the keyboard dismisses, and a browser→server bubbleClosed signal
that suppresses the hasTarget fallback until the user re-engages, so a
user-dismissed bubble doesn't immediately re-open.

Also move the split ratio controls into the overlay menu panel instead of
the separate floating toolbar/tap-zone.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Recover Shizuku user-service from token mismatch after reinstall

After an install/update (including adb install -r with no version bump),
shizuku_server holds a cached user-service record pointing at our previous
process's binder. Without intervention, the next bindUserService call
either never delivers onServiceConnected or connects then immediately
disconnects — the symptom users see as "Shizuku not responding until I
restart the manager".

Detect reinstall by comparing PackageInfo.lastUpdateTime against a saved
SharedPreferences value on init, and when they differ call
unbindUserService(args, conn, remove=true) before the first bind so the
stale record is wiped. Also watch the user-service ServiceConnection:
sessions that end within 3s of connecting trigger one automatic force
unbind-rebind (capped at two retries) to cover the case where the stale
record slipped past detection.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Version bump: minor (1.2.3 → 1.3.0)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant