AndroidUsingLinkProperties.java

 1package eu.siacs.conversations.utils;
 2
 3import android.annotation.TargetApi;
 4import android.content.Context;
 5import android.net.ConnectivityManager;
 6import android.net.LinkProperties;
 7import android.net.Network;
 8import android.net.NetworkInfo;
 9import android.net.RouteInfo;
10import android.os.Build;
11
12import java.net.Inet4Address;
13import java.net.InetAddress;
14import java.util.ArrayList;
15import java.util.List;
16
17import de.measite.minidns.dnsserverlookup.AbstractDNSServerLookupMechanism;
18import de.measite.minidns.dnsserverlookup.AndroidUsingExec;
19
20public class AndroidUsingLinkProperties extends AbstractDNSServerLookupMechanism {
21
22    private final Context context;
23
24    protected AndroidUsingLinkProperties(Context context) {
25        super(AndroidUsingLinkProperties.class.getSimpleName(), AndroidUsingExec.PRIORITY - 1);
26        this.context = context;
27    }
28
29    @Override
30    public boolean isAvailable() {
31        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
32    }
33
34    @Override
35    @TargetApi(21)
36    public String[] getDnsServerAddresses() {
37        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
38        Network[] networks = connectivityManager == null ? null : connectivityManager.getAllNetworks();
39        if (networks == null) {
40            return new String[0];
41        }
42        List<String> servers = new ArrayList<>();
43        int vpnOffset = 0;
44        for(Network network : networks) {
45            LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
46            NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
47            if (linkProperties != null) {
48                if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_VPN) {
49                    final List<String> tmp = getIPv4First(linkProperties.getDnsServers());
50                    servers.addAll(0, tmp);
51                    vpnOffset += tmp.size();
52                } else if (hasDefaultRoute(linkProperties)) {
53                    servers.addAll(vpnOffset, getIPv4First(linkProperties.getDnsServers()));
54                } else {
55                    servers.addAll(getIPv4First(linkProperties.getDnsServers()));
56                }
57            }
58        }
59        return servers.toArray(new String[servers.size()]);
60    }
61
62    private static List<String> getIPv4First(List<InetAddress> in) {
63        List<String> out = new ArrayList<>();
64        for(InetAddress addr : in) {
65            if (addr instanceof Inet4Address) {
66                out.add(0, addr.getHostAddress());
67            } else {
68                out.add(addr.getHostAddress());
69            }
70        }
71        return out;
72    }
73
74    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
75    private static boolean hasDefaultRoute(LinkProperties linkProperties) {
76        for(RouteInfo route: linkProperties.getRoutes()) {
77            if (route.isDefaultRoute()) {
78                return true;
79            }
80        }
81        return false;
82    }
83}