summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFil Bergamo <fil.bergamo@riseup.net>2017-08-04 22:44:51 +0000
committerWolfgang Wiedmeyer <wolfgit@wiedmeyer.de>2017-08-13 01:57:36 +0200
commit9971175ea84fdbaf2d4671e30460792385b28859 (patch)
tree32c923c0adb7f93a2d2d995e7040c9791d2cb56b
parenta0ce80942766948d4cd1036b97e2ee721ed8ecce (diff)
downloadframeworks_base-9971175ea84fdbaf2d4671e30460792385b28859.tar.gz
frameworks_base-9971175ea84fdbaf2d4671e30460792385b28859.tar.bz2
frameworks_base-9971175ea84fdbaf2d4671e30460792385b28859.zip
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>
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java68
1 files changed, 68 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1489fd8713a..058af4a9a51 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,10 +1019,76 @@ 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() {
enforceAccessPermission();