Skip to content

Fix two battery risks in the per-app remote routing feature - #742

Merged
kasnder merged 1 commit into
masterfrom
claude/battery-usage-review-pkjp7h
Aug 20, 2026
Merged

Fix two battery risks in the per-app remote routing feature#742
kasnder merged 1 commit into
masterfrom
claude/battery-usage-review-pkjp7h

Conversation

@kasnder

@kasnder kasnder commented Aug 20, 2026

Copy link
Copy Markdown
Member

Summary

Reviewed the recent per-app remote (WireGuard) routing work for battery impact and found two risks, both fixed here. Both are traffic-driven, opt-in-feature costs — the shipped default (no routing overrides configured) is unaffected either way.

  • Stale routing prefs stay costly after WireGuard is turned off. ServiceSinkhole.prepareUidAllowed resolved wg_route_mode/wg_route preferences unconditionally, so a user who had switched to selected mode or added a per-app override, then disabled WireGuard, kept paying fwd53's per-DNS-query UID lookup, JNI upcall, and forwarded UDP session — with no tunnel left to route around. Now that state only resolves when hasActiveWireGuard() is true; otherwise it collapses to the no-tunnel defaults (empty override set, default-tunnel, no direct DNS redirect), matching pre-feature behaviour.
  • The native flow-verdict cache (policy.c) was direct-mapped (1024 slots). Two concurrently active flows sharing a hash bucket evicted each other on every packet; each eviction forced a session-table walk (guaranteed futile for tunnelled flows, which never get an ng_session) followed by a per-packet Binder/procfs UID lookup — the exact cost the cache exists to avoid. Replaced with a 4-way set-associative cache (256 sets × 4 ways, same ~56 KB budget), so collisions now need 5 simultaneously-hot flows sharing a set before any fallback lookup is forced.

Test plan

  • ./gradlew :app:compileGithubDebugJavaWithJavac — not run: this session's container has no Android SDK/NDK (android-env reports exit 3; gradlew fails at SDK-location configuration before compiling).
  • ./gradlew :app:testGithubDebugUnitTest — not run, same reason.
  • assembleGithubDebug (native build) — not run, same reason.
  • Manual review: brace/paren balance checked on both edited files; logic re-read against the routing/flow-cache invariants documented in policy.c and RemoteRoutingLogic.java.

Recommend running the above before merge on a machine/session with the Android SDK/NDK available.


Generated by Claude Code

Gate routing-prefs resolution on WireGuard being active: with WG off,
stale wg_route_mode/wg_route prefs no longer keep fwd53's per-DNS-query
UID lookup and upcall path enabled.

Make the native flow-verdict cache 4-way set-associative instead of
direct-mapped, so two concurrently busy flows sharing a hash no longer
guarantee mutual eviction and per-packet fallback to a Binder/procfs
UID lookup.
@kasnder
kasnder marked this pull request as ready for review August 20, 2026 21:43
@kasnder
kasnder merged commit dfda555 into master Aug 20, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants