diff --git a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java index dd6f91018..02a6d38e2 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/network/AndroidNetworkManager.java @@ -11,6 +11,8 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkInfo; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventExecutor; @@ -38,6 +40,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; import static android.content.Context.CONNECTIVITY_SERVICE; +import static android.content.Context.WIFI_SERVICE; import static android.content.Intent.ACTION_SCREEN_OFF; import static android.content.Intent.ACTION_SCREEN_ON; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; @@ -111,15 +114,37 @@ class AndroidNetworkManager implements NetworkManager, Service { @Override public NetworkStatus getNetworkStatus() { - NetworkInfo net = connectivityManager.getActiveNetworkInfo(); - boolean connected = net != null && net.isConnected(); - boolean wifi = false, ipv6Only = false; - if (connected) { - wifi = net.getType() == TYPE_WIFI; - if (SDK_INT >= 23) ipv6Only = isActiveNetworkIpv6Only(); - else ipv6Only = areAllAvailableNetworksIpv6Only(); + // https://issuetracker.google.com/issues/175055271 + try { + NetworkInfo net = connectivityManager.getActiveNetworkInfo(); + boolean connected = net != null && net.isConnected(); + boolean wifi = false, ipv6Only = false; + if (connected) { + wifi = net.getType() == TYPE_WIFI; + if (SDK_INT >= 23) ipv6Only = isActiveNetworkIpv6Only(); + else ipv6Only = areAllAvailableNetworksIpv6Only(); + } + return new NetworkStatus(connected, wifi, ipv6Only); + } catch (SecurityException e) { + logException(LOG, WARNING, e); + // Without the ConnectivityManager we can't detect whether we have + // internet access. Assume we do, which is probably less harmful + // than assuming we don't. Likewise, assume the connection is + // IPv6-only. Fall back to the WifiManager to detect whether we + // have a wifi connection. + LOG.info("ConnectivityManager is broken, guessing connectivity"); + boolean connected = true, wifi = false, ipv6Only = true; + WifiManager wm = (WifiManager) app.getSystemService(WIFI_SERVICE); + if (wm != null) { + WifiInfo info = wm.getConnectionInfo(); + if (info != null && info.getIpAddress() != 0) { + LOG.info("Connected to wifi"); + wifi = true; + ipv6Only = false; + } + } + return new NetworkStatus(connected, wifi, ipv6Only); } - return new NetworkStatus(connected, wifi, ipv6Only); } /** @@ -130,23 +155,29 @@ class AndroidNetworkManager implements NetworkManager, Service { */ @TargetApi(23) private boolean isActiveNetworkIpv6Only() { - Network net = connectivityManager.getActiveNetwork(); - if (net == null) { - LOG.info("No active network"); + // https://issuetracker.google.com/issues/175055271 + try { + Network net = connectivityManager.getActiveNetwork(); + if (net == null) { + LOG.info("No active network"); + return false; + } + LinkProperties props = connectivityManager.getLinkProperties(net); + if (props == null) { + LOG.info("No link properties for active network"); + return false; + } + boolean hasIpv6Unicast = false; + for (LinkAddress linkAddress : props.getLinkAddresses()) { + InetAddress addr = linkAddress.getAddress(); + if (addr instanceof Inet4Address) return false; + if (!addr.isMulticastAddress()) hasIpv6Unicast = true; + } + return hasIpv6Unicast; + } catch (SecurityException e) { + logException(LOG, WARNING, e); return false; } - LinkProperties props = connectivityManager.getLinkProperties(net); - if (props == null) { - LOG.info("No link properties for active network"); - return false; - } - boolean hasIpv6Unicast = false; - for (LinkAddress linkAddress : props.getLinkAddresses()) { - InetAddress addr = linkAddress.getAddress(); - if (addr instanceof Inet4Address) return false; - if (!addr.isMulticastAddress()) hasIpv6Unicast = true; - } - return hasIpv6Unicast; } /** diff --git a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java index 22dfbe8df..11e164148 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/plugin/tcp/AndroidLanTcpPlugin.java @@ -175,16 +175,24 @@ class AndroidLanTcpPlugin extends LanTcpPlugin { @TargetApi(21) @Nullable private InetAddress getWifiClientIpv6Address() { - for (Network net : connectivityManager.getAllNetworks()) { - NetworkCapabilities caps = - connectivityManager.getNetworkCapabilities(net); - if (caps == null || !caps.hasTransport(TRANSPORT_WIFI)) continue; - LinkProperties props = connectivityManager.getLinkProperties(net); - if (props == null) continue; - for (LinkAddress linkAddress : props.getLinkAddresses()) { - InetAddress addr = linkAddress.getAddress(); - if (isIpv6LinkLocalAddress(addr)) return addr; + // https://issuetracker.google.com/issues/175055271 + try { + for (Network net : connectivityManager.getAllNetworks()) { + NetworkCapabilities caps = + connectivityManager.getNetworkCapabilities(net); + if (caps == null || !caps.hasTransport(TRANSPORT_WIFI)) { + continue; + } + LinkProperties props = + connectivityManager.getLinkProperties(net); + if (props == null) continue; + for (LinkAddress linkAddress : props.getLinkAddresses()) { + InetAddress addr = linkAddress.getAddress(); + if (isIpv6LinkLocalAddress(addr)) return addr; + } } + } catch (SecurityException e) { + logException(LOG, WARNING, e); } return null; } @@ -227,12 +235,17 @@ class AndroidLanTcpPlugin extends LanTcpPlugin { // network's socket factory may try to connect via another network private SocketFactory getSocketFactory() { if (SDK_INT < 21) return SocketFactory.getDefault(); - for (Network net : connectivityManager.getAllNetworks()) { - NetworkCapabilities caps = - connectivityManager.getNetworkCapabilities(net); - if (caps != null && caps.hasTransport(TRANSPORT_WIFI)) { - return net.getSocketFactory(); + // https://issuetracker.google.com/issues/175055271 + try { + for (Network net : connectivityManager.getAllNetworks()) { + NetworkCapabilities caps = + connectivityManager.getNetworkCapabilities(net); + if (caps != null && caps.hasTransport(TRANSPORT_WIFI)) { + return net.getSocketFactory(); + } } + } catch (SecurityException e) { + logException(LOG, WARNING, e); } LOG.warning("Could not find suitable socket factory"); return SocketFactory.getDefault(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java index b6ea21664..f3c5bf7e5 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/reporting/BriarReportCollector.java @@ -198,38 +198,47 @@ class BriarReportCollector { private ReportItem getConnectivity() { MultiReportInfo connectivityInfo = new MultiReportInfo(); - // Is mobile data available? - ConnectivityManager cm = requireNonNull( - getSystemService(ctx, ConnectivityManager.class)); - NetworkInfo mobile = cm.getNetworkInfo(TYPE_MOBILE); - boolean mobileAvailable = mobile != null && mobile.isAvailable(); - connectivityInfo.add("MobileDataAvailable", mobileAvailable); - - // Is mobile data enabled? - boolean mobileEnabled = false; + // https://issuetracker.google.com/issues/175055271 try { - Class clazz = Class.forName(cm.getClass().getName()); - Method method = clazz.getDeclaredMethod("getMobileDataEnabled"); - method.setAccessible(true); - mobileEnabled = (Boolean) requireNonNull(method.invoke(cm)); - } catch (ClassNotFoundException - | NoSuchMethodException - | IllegalArgumentException - | InvocationTargetException - | IllegalAccessException e) { - connectivityInfo - .add("MobileDataReflectionException", e.toString()); + // Is mobile data available? + ConnectivityManager cm = requireNonNull( + getSystemService(ctx, ConnectivityManager.class)); + NetworkInfo mobile = cm.getNetworkInfo(TYPE_MOBILE); + boolean mobileAvailable = mobile != null && mobile.isAvailable(); + connectivityInfo.add("MobileDataAvailable", mobileAvailable); + + // Is mobile data enabled? + boolean mobileEnabled = false; + try { + Class clazz = Class.forName(cm.getClass().getName()); + Method method = clazz.getDeclaredMethod("getMobileDataEnabled"); + method.setAccessible(true); + mobileEnabled = (Boolean) requireNonNull(method.invoke(cm)); + } catch (ClassNotFoundException + | NoSuchMethodException + | IllegalArgumentException + | InvocationTargetException + | IllegalAccessException e) { + connectivityInfo + .add("MobileDataReflectionException", e.toString()); + } + connectivityInfo.add("MobileDataEnabled", mobileEnabled); + + // Is mobile data connected ? + boolean mobileConnected = mobile != null && mobile.isConnected(); + connectivityInfo.add("MobileDataConnected", mobileConnected); + + // Is wifi available? + NetworkInfo wifi = cm.getNetworkInfo(TYPE_WIFI); + boolean wifiAvailable = wifi != null && wifi.isAvailable(); + connectivityInfo.add("WifiAvailable", wifiAvailable); + + // Is wifi connected? + boolean wifiConnected = wifi != null && wifi.isConnected(); + connectivityInfo.add("WifiConnected", wifiConnected); + } catch (SecurityException e) { + connectivityInfo.add("ConnectivityManagerException", e.toString()); } - connectivityInfo.add("MobileDataEnabled", mobileEnabled); - - // Is mobile data connected ? - boolean mobileConnected = mobile != null && mobile.isConnected(); - connectivityInfo.add("MobileDataConnected", mobileConnected); - - // Is wifi available? - NetworkInfo wifi = cm.getNetworkInfo(TYPE_WIFI); - boolean wifiAvailable = wifi != null && wifi.isAvailable(); - connectivityInfo.add("WifiAvailable", wifiAvailable); // Is wifi enabled? WifiManager wm = getSystemService(ctx, WifiManager.class); @@ -237,10 +246,6 @@ class BriarReportCollector { wm.getWifiState() == WIFI_STATE_ENABLED; connectivityInfo.add("WifiEnabled", wifiEnabled); - // Is wifi connected? - boolean wifiConnected = wifi != null && wifi.isConnected(); - connectivityInfo.add("WifiConnected", wifiConnected); - // Is wifi direct supported? boolean wifiDirect = ctx.getSystemService(WIFI_P2P_SERVICE) != null; connectivityInfo.add("WiFiDirectSupported", wifiDirect);