Check for connectivity changes

This commit is contained in:
M66B 2020-07-15 20:41:58 +02:00
parent a6a7c43c14
commit b184a2f344
1 changed files with 84 additions and 54 deletions

View File

@ -1693,78 +1693,107 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
} }
private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
private Boolean last4 = null; private NetworkCapabilities lastActiveCaps = null;
private Boolean last6 = null; private LinkProperties lastActiveProps = null;
@Override @Override
public void onAvailable(@NonNull Network network) { public void onAvailable(@NonNull Network network) {
try { try {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getNetworkInfo(network); NetworkInfo ni = cm.getNetworkInfo(network);
NetworkCapabilities caps = cm.getNetworkCapabilities(network); NetworkInfo ani = cm.getActiveNetworkInfo();
EntityLog.log(ServiceSynchronize.this, "Available network=" + network + " info=" + ni + " active=" + ani);
// Transition from metered to unmetered?
boolean transition = false;
if (caps != null &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
caps.hasCapability((NetworkCapabilities.NET_CAPABILITY_NOT_METERED))) {
Network[] networks = cm.getAllNetworks();
for (Network other : networks)
if (!network.equals(other)) {
NetworkCapabilities c = cm.getNetworkCapabilities(other);
if (c != null &&
c.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
!c.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)) {
transition = true;
break;
}
}
}
EntityLog.log(ServiceSynchronize.this,
"Available network=" + network + " info=" + ni + " caps=" + caps + " transition=" + transition);
if (transition)
reload(ServiceSynchronize.this, -1L, false, "unmetered");
} catch (Throwable ex) { } catch (Throwable ex) {
Log.w(ex); Log.w(ex);
} }
updateState(network, null); updateState(network, null);
} }
@Override @Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities capabilities) { public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities caps) {
updateState(network, capabilities); updateState(network, caps);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
try {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Network active = cm.getActiveNetwork();
if (active != null && active.equals(network)) {
boolean reload = (lastActiveCaps != null &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) &&
lastActiveCaps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) &&
!lastActiveCaps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
if (reload || BuildConfig.DEBUG)
EntityLog.log(ServiceSynchronize.this, "Connectivity changed " + network +
" caps=" + caps + " reload=" + reload);
if (reload)
reload(ServiceSynchronize.this, -1L, false, "unmetered");
lastActiveCaps = caps;
}
} catch (Throwable ex) {
Log.e(ex);
}
} }
@Override @Override
public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties properties) { public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties props) {
try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
// Monitor IP v4/v6 availability try {
boolean has4 = false; ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean has6 = false; Network active = cm.getActiveNetwork();
String name = properties.getInterfaceName(); if (active != null && active.equals(network)) {
NetworkInterface ni = NetworkInterface.getByName(name); boolean ahas4 = false;
if (ni != null) boolean ahas6 = false;
for (InterfaceAddress iaddr : ni.getInterfaceAddresses()) { boolean lhas4 = false;
InetAddress addr = iaddr.getAddress(); boolean lhas6 = false;
if (!addr.isLoopbackAddress() && !addr.isLinkLocalAddress()) if (lastActiveProps != null) {
if (addr instanceof Inet4Address) String aname = props.getInterfaceName();
has4 = true; String lname = lastActiveProps.getInterfaceName();
else if (addr instanceof Inet6Address) if (!TextUtils.isEmpty(aname) && !TextUtils.isEmpty(lname)) {
has6 = true; NetworkInterface aintf = NetworkInterface.getByName(aname);
NetworkInterface lintf = NetworkInterface.getByName(lname);
if (aintf != null && lintf != null) {
for (InterfaceAddress iaddr : aintf.getInterfaceAddresses()) {
InetAddress addr = iaddr.getAddress();
if (!addr.isLoopbackAddress() && !addr.isLinkLocalAddress())
if (addr instanceof Inet4Address)
ahas4 = true;
else if (addr instanceof Inet6Address)
ahas6 = true;
}
for (InterfaceAddress iaddr : lintf.getInterfaceAddresses()) {
InetAddress addr = iaddr.getAddress();
if (!addr.isLoopbackAddress() && !addr.isLinkLocalAddress())
if (addr instanceof Inet4Address)
lhas4 = true;
else if (addr instanceof Inet6Address)
lhas6 = true;
}
}
}
}
boolean reload = ((ahas4 && !lhas4) || (ahas6 && !lhas6));
if (reload || BuildConfig.DEBUG)
EntityLog.log(ServiceSynchronize.this, "Connectivity changed " + network +
" props=" + props + " reload=" + reload);
if (reload)
reload(ServiceSynchronize.this, -1L, false, "connectivity");
lastActiveProps = props;
} }
EntityLog.log(ServiceSynchronize.this, } catch (Throwable ex) {
"IP intf=" + name + "/" + ni.getDisplayName() + " v4=" + last4 + "/" + has4 + " v6=" + last6 + "/" + has6); Log.e(ex);
if ((last4 != null && last4 && !has4) || (last6 != null && last6 && !has6)) }
reload(ServiceSynchronize.this, -1L, false, "IP");
last4 = has4;
last6 = has6;
} catch (Throwable ex) {
Log.w(ex);
}
} }
@Override @Override
@ -1778,6 +1807,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
} catch (Throwable ex) { } catch (Throwable ex) {
Log.w(ex); Log.w(ex);
} }
updateState(network, null); updateState(network, null);
} }