Use LinkProperties in WifiSettings UI

Change-Id: I6f59328173e9550a2822573a9b25517ebbec4024
diff --git a/res/layout/wifi_config_preference.xml b/res/layout/wifi_config_preference.xml
index 665721e..9c1844b 100644
--- a/res/layout/wifi_config_preference.xml
+++ b/res/layout/wifi_config_preference.xml
@@ -232,9 +232,9 @@
         <TextView
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
-            android:text="@string/wifi_netmask" />
+            android:text="@string/wifi_network_prefix_length" />
 
-        <EditText android:id="@+id/netmask"
+        <EditText android:id="@+id/network_prefix_length"
                   android:layout_width="fill_parent"
                   android:layout_height="wrap_content"
                   android:singleLine="true"
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index a897406..0aa8aa3 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -271,9 +271,9 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="8dip"
-                    android:text="@string/wifi_netmask" />
+                    android:text="@string/wifi_network_prefix_length" />
 
-            <EditText android:id="@+id/netmask"
+            <EditText android:id="@+id/network_prefix_length"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:singleLine="true"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8d5a283..be65107 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -993,16 +993,22 @@
     <string name="wifi_ip_settings_menu_save">Save</string>
     <!-- Menu ietm to cancel the IP settings -->
     <string name="wifi_ip_settings_menu_cancel">Cancel</string>
-    <!-- Error message if the IP address is not valid -->
-    <string name="wifi_ip_settings_invalid_ip">Please type a valid IP address.</string>
+    <!-- Error message if the IP address is not valid [CHAR LIMIT=50]-->
+    <string name="wifi_ip_settings_invalid_ip_address">Please type a valid IP address.</string>
+    <!-- Error message if the gateway is not valid [CHAR LIMIT=50]-->
+    <string name="wifi_ip_settings_invalid_gateway">Please type a valid gateway address.</string>
+    <!-- Error message if the dns is not valid [CHAR LIMIT=50]-->
+    <string name="wifi_ip_settings_invalid_dns">Please type a valid dns address.</string>
+    <!-- Error message if the network prefix length is not valid [CHAR LIMIT=50]-->
+    <string name="wifi_ip_settings_invalid_network_prefix_length">Please type a network prefix length between 0 and 32.</string>
     <!-- Label for the DNS (first one) -->
     <string name="wifi_dns1">DNS 1</string>
     <!-- Label for the DNS (second one)-->
     <string name="wifi_dns2">DNS 2</string>
     <!-- Label for the gateway of the network -->
     <string name="wifi_gateway">Gateway</string>
-    <!-- Label for the netmask of the network -->
-    <string name="wifi_netmask">Netmask</string>
+    <!-- Label for the network prefix of the network [CHAR LIMIT=25]-->
+    <string name="wifi_network_prefix_length">Network prefix length</string>
 
     <!-- Wifi AP settings-->
     <!-- Label for wifi tether checkbox. Toggles Access Point on/off -->
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 03d0610..597c5a3 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -20,7 +20,10 @@
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.net.DhcpInfo;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
 import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkUtils;
 import android.net.Proxy;
 import android.net.ProxyProperties;
 import android.net.wifi.WifiConfiguration;
@@ -36,6 +39,7 @@
 import android.text.InputType;
 import android.text.TextWatcher;
 import android.text.format.Formatter;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -51,6 +55,7 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
+import java.util.Iterator;
 
 /**
  * The class for allowing UIs like {@link WifiDialog} and {@link WifiConfigPreference} to
@@ -93,11 +98,13 @@
     public static final int PROXY_NONE = 0;
     public static final int PROXY_STATIC = 1;
 
+    private static final String TAG = "WifiConfigController";
+
     private Spinner mNetworkSetupSpinner;
     private Spinner mIpSettingsSpinner;
     private TextView mIpAddressView;
     private TextView mGatewayView;
-    private TextView mNetmaskView;
+    private TextView mNetworkPrefixLengthView;
     private TextView mDns1View;
     private TextView mDns2View;
 
@@ -330,17 +337,12 @@
         if (config.ipAssignment == IpAssignment.STATIC) {
             //TODO: A better way to do this is to not dismiss the
             //dialog as long as one of the fields is invalid
-            try {
-                config.ipConfig.ipAddress = stringToIpAddr(mIpAddressView.getText().toString());
-                config.ipConfig.gateway = stringToIpAddr(mGatewayView.getText().toString());
-                config.ipConfig.netmask = stringToIpAddr(mNetmaskView.getText().toString());
-                config.ipConfig.dns1 = stringToIpAddr(mDns1View.getText().toString());
-                if (mDns2View.getText() != null && mDns2View.getText().length() > 0) {
-                    config.ipConfig.dns2 = stringToIpAddr(mDns2View.getText().toString());
-                }
-            } catch (UnknownHostException e) {
-                Toast.makeText(mConfigUi.getContext(), R.string.wifi_ip_settings_invalid_ip,
-                        Toast.LENGTH_LONG).show();
+            LinkProperties linkProperties = new LinkProperties();
+            int result = validateIpConfigFields(linkProperties);
+            if (result == 0) {
+                config.linkProperties = linkProperties;
+            } else {
+                Toast.makeText(mConfigUi.getContext(), result, Toast.LENGTH_LONG).show();
                 config.ipAssignment = IpAssignment.UNASSIGNED;
             }
         }
@@ -355,9 +357,11 @@
             String exclusionList = mProxyExclusionListView.getText().toString();
             int result = ProxySelector.validate(host, port, exclusionList);
             if (result == 0) {
-                config.proxyProperties.setSocketAddress(
+                ProxyProperties proxyProperties= new ProxyProperties();
+                proxyProperties.setSocketAddress(
                         InetSocketAddress.createUnresolved(host, Integer.parseInt(port)));
-                config.proxyProperties.setExclusionList(exclusionList);
+                proxyProperties.setExclusionList(exclusionList);
+                config.linkProperties.setHttpProxy(proxyProperties);
             } else {
                 Toast.makeText(mConfigUi.getContext(), result, Toast.LENGTH_LONG).show();
                 config.proxySettings = ProxySettings.UNASSIGNED;
@@ -367,6 +371,51 @@
         return config;
     }
 
+    private int validateIpConfigFields(LinkProperties linkProperties) {
+        try {
+            String ipAddr = mIpAddressView.getText().toString();
+            if (!NetworkUtils.isIpAddress(ipAddr)) {
+                return R.string.wifi_ip_settings_invalid_ip_address;
+            }
+            InetAddress inetAddr = InetAddress.getByName(ipAddr);
+
+            int networkPrefixLength = Integer.parseInt(mNetworkPrefixLengthView.getText()
+                    .toString());
+            if (networkPrefixLength < 0 || networkPrefixLength > 32) {
+                return R.string.wifi_ip_settings_invalid_network_prefix_length;
+            }
+
+            linkProperties.addLinkAddress(new LinkAddress(inetAddr, networkPrefixLength));
+
+            String gateway = mGatewayView.getText().toString();
+            if (!NetworkUtils.isIpAddress(gateway)) {
+                return R.string.wifi_ip_settings_invalid_gateway;
+            }
+            linkProperties.setGateway(InetAddress.getByName(gateway));
+
+            String dns = mDns1View.getText().toString();
+            if (!NetworkUtils.isIpAddress(dns)) {
+                return R.string.wifi_ip_settings_invalid_dns;
+            }
+            linkProperties.addDns(InetAddress.getByName(dns));
+            if (mDns2View.length() > 0) {
+                dns = mDns2View.getText().toString();
+                if (!NetworkUtils.isIpAddress(dns)) {
+                    return R.string.wifi_ip_settings_invalid_dns;
+                }
+                linkProperties.addDns(InetAddress.getByName(dns));
+            }
+
+        } catch (NumberFormatException ignore) {
+            return R.string.wifi_ip_settings_invalid_network_prefix_length;
+        } catch (UnknownHostException e) {
+            //Should not happen since we have already validated addresses
+            Log.e(TAG, "Failure to validate IP configuration " + e);
+            return R.string.wifi_ip_settings_invalid_ip_address;
+        }
+        return 0;
+    }
+
     int chosenNetworkSetupMethod() {
         if (mNetworkSetupSpinner != null) {
             return mNetworkSetupSpinner.getSelectedItemPosition();
@@ -471,18 +520,30 @@
             if (mIpAddressView == null) {
                 mIpAddressView = (TextView) mView.findViewById(R.id.ipaddress);
                 mGatewayView = (TextView) mView.findViewById(R.id.gateway);
-                mNetmaskView = (TextView) mView.findViewById(R.id.netmask);
+                mNetworkPrefixLengthView = (TextView) mView.findViewById(
+                        R.id.network_prefix_length);
                 mDns1View = (TextView) mView.findViewById(R.id.dns1);
                 mDns2View = (TextView) mView.findViewById(R.id.dns2);
             }
             if (config != null) {
-                DhcpInfo ipConfig = config.ipConfig;
-                if (ipConfig != null && ipConfig.ipAddress != 0) {
-                    mIpAddressView.setText(intToIpString(ipConfig.ipAddress));
-                    mGatewayView.setText(intToIpString(ipConfig.gateway));
-                    mNetmaskView.setText(intToIpString(ipConfig.netmask));
-                    mDns1View.setText(intToIpString(ipConfig.dns1));
-                    if (ipConfig.dns2 != 0) mDns2View.setText(intToIpString(ipConfig.dns2));
+                LinkProperties linkProperties = config.linkProperties;
+                Iterator<LinkAddress> iterator = linkProperties.getLinkAddresses().iterator();
+                if (iterator.hasNext()) {
+                    LinkAddress linkAddress = iterator.next();
+                    mIpAddressView.setText(linkAddress.getAddress().getHostAddress());
+                    mNetworkPrefixLengthView.setText(Integer.toString(linkAddress
+                            .getNetworkPrefixLength()));
+                }
+                InetAddress gateway = linkProperties.getGateway();
+                if (gateway != null) {
+                    mGatewayView.setText(linkProperties.getGateway().getHostAddress());
+                }
+                Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
+                if (dnsIterator.hasNext()) {
+                    mDns1View.setText(dnsIterator.next().getHostAddress());
+                }
+                if (dnsIterator.hasNext()) {
+                    mDns2View.setText(dnsIterator.next().getHostAddress());
                 }
             }
         } else {
@@ -507,7 +568,7 @@
                 mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
             }
             if (config != null) {
-                ProxyProperties proxyProperties = config.proxyProperties;
+                ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
                 if (proxyProperties != null) {
                     InetSocketAddress sockAddr = proxyProperties.getSocketAddress();
                     if (sockAddr != null) {
@@ -602,29 +663,4 @@
     @Override
     public void onNothingSelected(AdapterView<?> parent) {
     }
-
-    /* TODO: should go away when we move to IPv6 based config storage */
-    private static int stringToIpAddr(String addrString) throws UnknownHostException {
-        try {
-            String[] parts = addrString.split("\\.");
-            if (parts.length != 4) {
-                throw new UnknownHostException(addrString);
-            }
-
-            int a = Integer.parseInt(parts[0]);
-            int b = Integer.parseInt(parts[1]) << 8;
-            int c = Integer.parseInt(parts[2]) << 16;
-            int d = Integer.parseInt(parts[3]) << 24;
-
-            return a | b | c | d;
-        } catch (NumberFormatException e) {
-            throw new UnknownHostException(addrString);
-        }
-    }
-
-    private static String intToIpString(int i) {
-        return (i & 0xFF) + "." + ((i >>  8 ) & 0xFF) + "." +((i >> 16 ) & 0xFF) + "." +
-            ((i >> 24 ) & 0xFF);
-    }
-
 }