You've already forked android-client
mirror of
https://github.com/netbirdio/android-client.git
synced 2026-05-22 17:10:49 -07:00
Bind process to default network and ignore initial callback burst
Pin the process's outgoing sockets to the current default Android Network via ConnectivityManager.bindProcessToNetwork so fresh dials after a WiFi/cellular switch do not stall on TCP SYN retransmits through the departing interface. Skip the initial onAvailable burst fired right after registering the NetworkCallback. That burst reflects current state, not a transition, and was triggering a spurious EngineRestarter restart that cancelled the in-flight login on cold start.
This commit is contained in:
+18
-2
@@ -4,8 +4,13 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ConcreteNetworkAvailabilityListener implements NetworkAvailabilityListener {
|
||||
// Grace window after subscribing a listener during which Android's initial
|
||||
// onAvailable burst is treated as state seeding, not as a transition.
|
||||
private static final long INITIAL_BURST_GRACE_MS = 3000;
|
||||
|
||||
private final Map<Integer, Boolean> availableNetworkTypes;
|
||||
private NetworkToggleListener listener;
|
||||
private volatile long listenerSubscribedAt = 0;
|
||||
|
||||
public ConcreteNetworkAvailabilityListener() {
|
||||
this.availableNetworkTypes = new ConcurrentHashMap<>();
|
||||
@@ -38,16 +43,27 @@ public class ConcreteNetworkAvailabilityListener implements NetworkAvailabilityL
|
||||
}
|
||||
|
||||
private void notifyListener() {
|
||||
if (listener != null) {
|
||||
listener.onNetworkTypeChanged();
|
||||
NetworkToggleListener l = listener;
|
||||
if (l == null) {
|
||||
return;
|
||||
}
|
||||
// Skip Android's initial onAvailable burst that fires right after the
|
||||
// NetworkCallback is registered; that is the current state, not a
|
||||
// transition, and must not trigger an engine restart.
|
||||
long subscribedAt = listenerSubscribedAt;
|
||||
if (subscribedAt != 0 && System.currentTimeMillis() - subscribedAt < INITIAL_BURST_GRACE_MS) {
|
||||
return;
|
||||
}
|
||||
l.onNetworkTypeChanged();
|
||||
}
|
||||
|
||||
public void subscribe(NetworkToggleListener listener) {
|
||||
this.listener = listener;
|
||||
this.listenerSubscribedAt = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void unsubscribe() {
|
||||
this.listener = null;
|
||||
this.listenerSubscribedAt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ public class NetworkChangeDetector {
|
||||
private static final String LOGTAG = NetworkChangeDetector.class.getSimpleName();
|
||||
private final ConnectivityManager connectivityManager;
|
||||
private ConnectivityManager.NetworkCallback networkCallback;
|
||||
private ConnectivityManager.NetworkCallback defaultNetworkCallback;
|
||||
private volatile NetworkAvailabilityListener listener;
|
||||
|
||||
public NetworkChangeDetector(ConnectivityManager connectivityManager) {
|
||||
this.connectivityManager = connectivityManager;
|
||||
initNetworkCallback();
|
||||
initDefaultNetworkCallback();
|
||||
}
|
||||
|
||||
private void checkNetworkCapabilities(Network network, Consumer<Integer> operation) {
|
||||
@@ -58,10 +60,37 @@ public class NetworkChangeDetector {
|
||||
};
|
||||
}
|
||||
|
||||
private void initDefaultNetworkCallback() {
|
||||
defaultNetworkCallback = new ConnectivityManager.NetworkCallback() {
|
||||
@Override
|
||||
public void onAvailable(@NonNull Network network) {
|
||||
Log.d(LOGTAG, "default network became " + network + ", binding process to it");
|
||||
try {
|
||||
if (!connectivityManager.bindProcessToNetwork(network)) {
|
||||
Log.w(LOGTAG, "bindProcessToNetwork returned false for " + network);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "bindProcessToNetwork failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(@NonNull Network network) {
|
||||
Log.d(LOGTAG, "default network " + network + " lost, clearing process binding");
|
||||
try {
|
||||
connectivityManager.bindProcessToNetwork(null);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "bindProcessToNetwork(null) failed", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void registerNetworkCallback() {
|
||||
NetworkRequest.Builder builder = new NetworkRequest.Builder();
|
||||
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
|
||||
connectivityManager.registerNetworkCallback(builder.build(), networkCallback);
|
||||
connectivityManager.registerDefaultNetworkCallback(defaultNetworkCallback);
|
||||
}
|
||||
|
||||
public void unregisterNetworkCallback() {
|
||||
@@ -70,6 +99,16 @@ public class NetworkChangeDetector {
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "failed to unregister network callback", e);
|
||||
}
|
||||
try {
|
||||
connectivityManager.unregisterNetworkCallback(defaultNetworkCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "failed to unregister default network callback", e);
|
||||
}
|
||||
try {
|
||||
connectivityManager.bindProcessToNetwork(null);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "bindProcessToNetwork(null) on unregister failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void subscribe(NetworkAvailabilityListener listener) {
|
||||
|
||||
Reference in New Issue
Block a user