From af7c25d2df73c20f898aa5e248e5abf4cc92e8c8 Mon Sep 17 00:00:00 2001
From: Fil Bergamo <fil.bergamo@riseup.net>
Date: Fri, 4 Aug 2017 22:44:51 +0000
Subject: [PATCH v2] Fix "RepWifi connection not correctly reported to userspace
 apps" Issue #1792.

When a WiFi connection is established using an external dongle via the
RepWifi app, although it's perfectly working, the framework still
presents the WiFi connection as disabled or disconnected to the
user-space apps. This misleads apps that rely on this mechanism, so
that they prevent the user from doing network-related tasks.
This patch solves the issue by modifying getActiveNetworkInfo() method
in ConnectivityService.java, adding a basic mechanism to check if the
WiFi interface is connected.
java.net.NetworkInterface.getByName() is used to look for either
"wlan0" (RepWifi) or "rndis0"(Tethering).
If any one of the two interfaces is present, getInetAddresses() is
called on it, to see if it has any IP address.
If the interface has an IP address in the "local" range
(e.g. 192.168.x.x), then it is considered to be connected. So an
instance of android.net.NetworkInfo is created, and its state is set
as "Connected".
Finally, that instance gets returned to the caller. The result should
be so that user-space apps are now able to "see" the internet
connection made via RepWifi or via reverse tethering.

Signed-off-by: Fil Bergamo <fil.bergamo@riseup.net>
Reviewed-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
---

Changes since v1:

	- No changes to the framework's public API
	- All code inside the ConnectivityService class
	- No external shell commands involved, all is pure Java.

 .../com/android/server/ConnectivityService.java    | 68 ++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1489fd8713a..fadc4f4f914 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -145,11 +145,13 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
 import java.net.UnknownHostException;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.SortedSet;
@@ -1017,9 +1019,75 @@ public class ConnectivityService extends IConnectivityManager.Stub
         final int uid = Binder.getCallingUid();
         NetworkState state = getUnfilteredActiveNetworkState(uid);
         NetworkInfo ni = getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
+
+        // TODO RepWifi extension. Remove when a low-level, long-lived solution is found.
+        if (ni == null) {
+            ni = getNetworkInfoByInterfaceName(IFACE_NAME_WIFI);
+        }
+        if (ni == null) {
+            ni = getNetworkInfoByInterfaceName(IFACE_NAME_TETHER);
+        }
+
         maybeLogBlockedNetworkInfo(ni, uid);
         return ni;
     }
+
+    // TODO RepWifi extension. Remove when a low-level, long-lived solution is found.
+    private static final String IFACE_NAME_WIFI = "wlan0";
+    private static final String IFACE_NAME_TETHER = "rndis0";
+    private NetworkInfo getNetworkInfoByInterfaceName(String ifname) {
+        try {
+
+            int type = 0;
+            String typeName = null;
+
+            if (ifname == IFACE_NAME_WIFI) {
+                type = ConnectivityManager.TYPE_WIFI;
+                typeName = "WIFI";
+
+            } else if (ifname == IFACE_NAME_TETHER) {
+                type = ConnectivityManager.TYPE_ETHERNET;
+                typeName = "ETHERNET";
+
+            } else {
+                return null;
+            }
+
+            NetworkInterface nifRep = NetworkInterface.getByName(ifname);
+            if (nifRep == null) {
+                return null;
+            }
+
+            Enumeration<InetAddress> ads = nifRep.getInetAddresses();
+            if (ads == null) {
+                return null;
+            }
+
+            while (ads.hasMoreElements()) {
+
+                InetAddress a = ads.nextElement();
+
+                if (a.getHostAddress() != null && a.isSiteLocalAddress()) {
+                    // if the interface has a valid IP address in the range of a
+                    // local network we consider it is connected to an AP.
+                    NetworkInfo ninfo = new NetworkInfo(type, 0, typeName, "");
+                    ninfo.setDetailedState(DetailedState.CONNECTED, null, null);
+                    ninfo.setIsAvailable(true);
+                    return ninfo;
+                }
+
+            }
+
+            // if we reached here, the interface has no valid address
+            return null;
+
+        } catch (Exception e) {
+            // Exceptions are suppressed to avoid crashing the surrounding system service.
+            // This is only a best-effort hack.
+            return null;
+        }
+
+    }
 
     @Override
     public Network getActiveNetwork() {
-- 
2.11.0

