Compare search domains and excluded routes in Builder.equals - #965
Merged
Merged
Conversation
Builder.equals decides whether reload() replaces the live tun or takes the "Native restart" shortcut, so any field it does not capture cannot reach a running interface. Two were still missing after #960 fixed the metered flag: - search domains (addSearchDomain); - the carrier ePDG exclusions (excludeRoute, API 33+). These are re-resolved on every rebuild behind a 1.5s timeout, so a first establish whose lookup timed out was never replaced by a later rebuild that resolved them, and Wi-Fi calling stayed broken until some unrelated change forced a real replacement. Both are now recorded by overriding the corresponding Builder methods and compared like the existing lists. Also: two offline builders (both networkInfo null) now compare equal instead of forcing a needless replacement on every reload while there is no active network, and the cast to Builder is guarded by an instanceof check rather than relying on a following null check. The extra interface replacements this produces go through VpnReplacementSequencer, which was not in place when the issue was first triaged. Refs #763 Claude-Session: https://claude.ai/code/session_016eKiHiWiQwMQosDXj8qY4s
kasnder
marked this pull request as ready for review
September 19, 2026 20:14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the rest of #763, after #960 took the metered half.
The bug
Builder.equalsdecides whetherreload()replaces the live tun or takes the "Native restart" shortcut, so any field the builder does not capture cannot reach a running interface. Two were still missing:addSearchDomain);excludeRoute, API 33+). These are re-resolved on every rebuild behind a 1.5s timeout, so a first establish whose lookup timed out was never replaced by a later rebuild that did resolve them — Wi-Fi calling stayed broken until some unrelated change forced a real replacement. This is the user-visible half of what is left.The change
BuilderoverridesaddSearchDomainandexcludeRouteto record what was added, andequalscompares both lists the same way it compares addresses, routes, DNS and disallowed apps.networkInfonull) now compare equal instead of forcing a needless interface replacement on every reload while there is no active network at all.(Builder) objcast is guarded by aninstanceofcheck rather than by a null check that followed it.The original triage asked for this to be sequenced behind the replacement-race work, since the fix deliberately produces more interface replacements.
VpnReplacementSequenceris now inmaster, so the replacements go through it.Testing
Not compiled locally: this container has no Android SDK. Relying on CI for
compileGithubDebugJavaWithJavac, the unit tests and lint.Builderis a private inner class ofServiceSinkholewith no seam for a unit test, so there is no test to add here.On-device confirmation worth having, on a device with a SIM whose ePDG domain resolves: with Wi-Fi calling active, force a VPN rebuild (network switch) after a start where the ePDG lookup timed out, and check the log shows an interface replacement rather than "Native restart".
https://claude.ai/code/session_016eKiHiWiQwMQosDXj8qY4s
Generated by Claude Code