package com.evsuite.abrp; import android.content.Context; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * What an update check writes down about the connection before and after it fails: the networks * Android sees, whether the server's name can be looked up, and whether the internet answers at * all, which tells a SIM without data from a server that is down. Blocking: background thread. * Never logs the server's address or anything about the car. — UNSTABLE BUILDS ONLY. */ final class UpdateNetworkCheck { /** Android's own connectivity test, as Android itself uses it; no data about the car is sent. */ private static final String INTERNET_TEST = "https://www.gstatic.com/generate_204"; private static final int TIMEOUT_MS = 10_000; private UpdateNetworkCheck() {} /** One line per network, or one saying there is none. */ static List networks(Context app) { List out = new ArrayList<>(); try { ConnectivityManager cm = (ConnectivityManager) app.getSystemService(Context.CONNECTIVITY_SERVICE); if (cm == null) { out.add("Network: no connectivity service"); return out; } Network active = cm.getActiveNetwork(); if (active == null) out.add("Network: none in use"); for (Network network : cm.getAllNetworks()) { NetworkCapabilities caps = cm.getNetworkCapabilities(network); if (caps == null) continue; NetworkInfo info = cm.getNetworkInfo(network); out.add("Network: " + UpdateDiagnosis.network(transports(caps), caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET), caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED), network.equals(active), info != null && info.isRoaming())); } } catch (RuntimeException e) { out.add("Network: unreadable (" + e.getClass().getSimpleName() + ")"); } return out; } private static List transports(NetworkCapabilities caps) { List out = new ArrayList<>(); if (caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) out.add("cellular"); if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) out.add("Wi-Fi"); if (caps.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) out.add("ethernet"); if (caps.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) out.add("Bluetooth"); if (caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) out.add("VPN"); return out; } /** Whether the host's name resolves, without saying the name. */ static String lookup(String host) { long started = System.currentTimeMillis(); try { InetAddress.getByName(host); return "Server's name: found in " + (System.currentTimeMillis() - started) + " ms"; } catch (IOException | RuntimeException e) { return "Server's name: " + UpdateDiagnosis.failure(e); } } /** Whether the world outside the car server answers. */ static String internet() { HttpURLConnection conn = null; try { conn = (HttpURLConnection) new URL(INTERNET_TEST).openConnection(); conn.setInstanceFollowRedirects(false); conn.setConnectTimeout(TIMEOUT_MS); conn.setReadTimeout(TIMEOUT_MS); return "Internet test: " + UpdateDiagnosis.internet(conn.getResponseCode()); } catch (IOException | RuntimeException e) { return "Internet test: " + UpdateDiagnosis.failure(e); } finally { if (conn != null) conn.disconnect(); } } }