[Replicant] [PATCH] fix repwifi connection not reported to userspace apps. fix reverse-tether connection not reported to userspace apps.

Fil fil.bergamo at riseup.net
Mon May 22 21:47:41 UTC 2017


Dear Replicant fellows,

As reported on the tracker I've finished my work on issue #1792.
Here-below is my very first patch to replicant (hurray!!!).
It is my very first patch to anything, to say the truth, so I just hope everything was done properly and I hope it works as expected.
Please pardon me if I messed up with anything while packing up the patch.
Here it is:

---
 api/current.txt                                    |   2 +
 api/system-current.txt                             |   2 +
 core/java/android/net/NetworkInfo.java             | 268 +++++++++++++++++++++
 .../com/android/server/ConnectivityService.java    |  11 +
 4 files changed, 283 insertions(+)

diff --git a/api/current.txt b/api/current.txt
index c45cc3dbbf4..2a3ab95c4bf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18372,9 +18372,11 @@ package android.net {
     method public android.net.NetworkInfo.DetailedState getDetailedState();
     method public java.lang.String getExtraInfo();
     method public java.lang.String getReason();
+    method public static android.net.NetworkInfo getRepWifiNetworkInfo();
     method public android.net.NetworkInfo.State getState();
     method public int getSubtype();
     method public java.lang.String getSubtypeName();
+    method public static android.net.NetworkInfo getTetherNetworkInfo();
     method public int getType();
     method public java.lang.String getTypeName();
     method public boolean isAvailable();
diff --git a/api/system-current.txt b/api/system-current.txt
index 1e7b94e883e..12f87e9d2a6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19885,9 +19885,11 @@ package android.net {
     method public android.net.NetworkInfo.DetailedState getDetailedState();
     method public java.lang.String getExtraInfo();
     method public java.lang.String getReason();
+    method public static android.net.NetworkInfo getRepWifiNetworkInfo();
     method public android.net.NetworkInfo.State getState();
     method public int getSubtype();
     method public java.lang.String getSubtypeName();
+    method public static android.net.NetworkInfo getTetherNetworkInfo();
     method public int getType();
     method public java.lang.String getTypeName();
     method public boolean isAvailable();
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index af7a4658808..8f61c83d989 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -21,6 +21,9 @@ import android.os.Parcel;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.EnumMap;
 
 /**
@@ -471,4 +474,269 @@ public class NetworkInfo implements Parcelable {
                 return new NetworkInfo[size];
             }
         };
+
+        // ****** Extension methods for RepWifi ********** 
+        // Introduced by Fil Bergamo, 2017-05-16.
+        //
+        public static NetworkInfo getRepWifiNetworkInfo(){
+                return RepWifiConnection.getNetworkInfo(RepWifiConnection.INTERFACE_NAME_WIFI);
+        }
+        
+        public static NetworkInfo getTetherNetworkInfo(){
+                return RepWifiConnection.getNetworkInfo(RepWifiConnection.INTERFACE_NAME_TETHER);
+        }
+        
+        static class RepWifiConnection{
+
+                static final String INTERFACE_NAME_WIFI = "wlan0";
+                static final String INTERFACE_NAME_TETHER = "rndis0";
+
+                static class ShellCommand {
+
+                        protected String _cmdOut = "";
+                        protected String _cmdTxt = "";
+
+                        public ShellCommand(String commandText) {
+                                this._cmdTxt = commandText;
+                        }
+
+                        public int execute() throws Exception {
+
+                                if (this._cmdTxt == null) {
+                                        return -9;
+                                }
+
+                                java.lang.Process cmd = Runtime.getRuntime().exec(this._cmdTxt);
+
+                                InputStream os = cmd.getInputStream();
+                                InputStream es = cmd.getErrorStream();
+
+                                StringBuilder sb = new StringBuilder();
+
+                                sb.append(getStringFromStream(es));
+                                sb.append(getStringFromStream(os));
+
+                                int res = cmd.waitFor();
+
+                                // re-read the output, in case it was empty when first tried
+                                sb.append(getStringFromStream(es));
+                                sb.append(getStringFromStream(os));
+
+                                this._cmdOut = sb.toString();
+
+                                return res;
+
+                        }
+
+                        protected String getStringFromStream(InputStream s) throws IOException {
+
+                                StringBuilder sb = new StringBuilder();
+                                while ((s.available() > 0)) {
+                                        int b = s.read();
+                                        if (b >= 0) {
+                                                sb.append((char) b);
+                                        } else {
+                                                break;
+                                        }
+                                }
+
+                                return sb.toString();
+
+                        }
+
+                        public String getOutput() {
+                                return this._cmdOut;
+                        }
+
+                }
+
+                public static NetworkInfo getNetworkInfo(String interfaceName){
+
+                        NetworkInfo netInfo;
+                        if (interfaceName.equals(INTERFACE_NAME_WIFI)){
+                                netInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
+                                
+                        }else if (interfaceName.equals(INTERFACE_NAME_TETHER)){
+                                netInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0,"ETHERNET", "");
+                                
+                        }else{
+                                return null;
+                        }
+                        
+                        netInfo.mState = getState(interfaceName);
+                        netInfo.mDetailedState = getDetailedState(interfaceName);
+                        netInfo.mIsAvailable = isAvailable(interfaceName);
+                        return netInfo;
+
+                }
+
+                public static boolean isAvailable(String interfaceName){
+                        
+                        String[] ifaces = getAvailableInterfaces();
+                        if (ifaces == null){
+                                return false;
+                        }
+
+                        if (ifaces.length == 0){
+                                return false;
+                        }
+
+                        for (String i : ifaces){
+                                if (i.equals(interfaceName)){
+                                        return true;
+                                }
+                        }
+                        
+                        return false;
+                        
+                }
+                
+                public static State getState(String interfaceName){
+
+                        if (interfaceName.equals(INTERFACE_NAME_WIFI) && (! isWpaSupplicantRunning())){
+                                return State.DISCONNECTED;
+                        }
+
+                        String gw = getGateway(interfaceName);
+                        if (gw == null){
+                                return State.DISCONNECTED;
+                        }
+                        else{
+                                //assuming the following:
+                                //if there's a gateway set for the interface,
+                                //then there's a route for the interface,
+                                //then RepWifi or reverse-tether must have established that route,
+                                //then RepWifi or reverse-tether is connected.
+                                return State.CONNECTED;
+                        }
+
+                }
+        
+                public static DetailedState getDetailedState(String interfaceName){
+
+                        State currentState = getState(interfaceName);
+                        if (currentState == State.CONNECTED){
+                                return DetailedState.CONNECTED;                                
+                        }
+                        else{
+                                return DetailedState.DISCONNECTED;
+                        }               
+
+                }
+
+                private static boolean isWpaSupplicantRunning(){
+
+                        boolean retval = false;
+
+                        try {
+
+                                ShellCommand su = new ShellCommand("pidof wpa_supplicant");
+                                if (su.execute() == 0){
+
+                                        if (su.getOutput().trim().equals("")){
+                                                retval = false;
+                                        }else{
+                                                retval = true;
+                                        }
+
+                                }else {
+                                        retval = false;
+                                }
+
+
+                        } catch (Exception e) {
+                                retval = false;
+                        }
+
+                        return retval;
+
+                }
+
+                protected static String getGateway(String interfaceName){
+
+                        try {
+
+                                //doesn't need root (tested)
+                                ShellCommand cmd = new ShellCommand("ip route show dev " + interfaceName);
+                                if (cmd.execute() != 0){
+                                        return null;
+                                }
+
+                                //read command output
+                                String out = cmd.getOutput();
+                                if (out == null){
+                                        return null;
+                                }
+
+                                String[] lines = out.split("\n");
+
+                                for (String l : lines){
+
+                                        if (l.contains("default via")){
+
+                                                String[] f = l.split(" ");
+                                                if (f.length > 2){
+
+                                                        //found route's address:
+                                                        return f[2];
+
+                                                }
+                                        }
+                                }
+
+                                return null;
+
+                        } catch (Exception e) {
+                                return null;
+                        }
+
+                }
+
+                protected static String[] getAvailableInterfaces(){
+
+                        try {
+
+                                // No need for root for "ip link"
+                                // tested 2017-03-24 - Fil
+                                ShellCommand cmd = new ShellCommand("ip link");
+                                if (cmd.execute() == 0){
+
+                                        String out = cmd.getOutput();
+                                        if (out == null || out.contains("\n") == false){
+                                                return null;
+                                        }
+
+                                        ArrayList<String> list = new ArrayList<String>();
+
+                                        String[] lines = out.split("\n");
+                                        for (String l : lines){
+
+                                                String[] fields = l.split(":");
+                                                if (fields.length != 3){
+                                                        continue;
+                                                }
+
+                                                String interfName = fields[1].trim();
+                                                list.add(interfName);
+
+                                        }
+
+                                        String[] retArr = new String[list.size()];
+                                        retArr = list.toArray(retArr);
+
+                                        return retArr;
+
+                                }
+                                else{
+                                        return null;
+                                }
+
+                        } catch (Exception e) {
+                                return null;
+                        }
+
+                }
+
+        }
+        //***** End of Extension methods for RepWifi***************
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1489fd8713a..bf7165682fe 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1017,6 +1017,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
         final int uid = Binder.getCallingUid();
         NetworkState state = getUnfilteredActiveNetworkState(uid);
         NetworkInfo ni = getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
+
+        //***** Begin Extension for RepWifi *******
+       //introduced by Fil Bergamo 2017-05-16
+        if (ni == null){
+               ni = NetworkInfo.getRepWifiNetworkInfo();
+        }
+        if (ni == null || ni.isAvailable() == false || ni.getState() != NetworkInfo.State.CONNECTED){
+               ni = NetworkInfo.getTetherNetworkInfo();
+        }
+        //***** End of Extension for RepWifi. *****
+
         maybeLogBlockedNetworkInfo(ni, uid);
         return ni;
     }
-- 
2.11.0
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/replicant/attachments/20170522/59b8db69/attachment.asc>


More information about the Replicant mailing list