am a47c4019: Merge "Add RouteInfo objects for tracking routes." into honeycomb-LTE

* commit 'a47c40193fcbe9ca07facea78b2828afdae5e025':
  Add RouteInfo objects for tracking routes.
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
index 7396669..860da0a 100644
--- a/core/java/android/net/DhcpInfoInternal.java
+++ b/core/java/android/net/DhcpInfoInternal.java
@@ -22,6 +22,8 @@
 import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
 
 /**
  * A simple object for retrieving the results of a DHCP request.
@@ -31,7 +33,6 @@
 public class DhcpInfoInternal {
     private final static String TAG = "DhcpInfoInternal";
     public String ipAddress;
-    public String gateway;
     public int prefixLength;
 
     public String dns1;
@@ -40,7 +41,14 @@
     public String serverAddress;
     public int leaseDuration;
 
+    private Collection<RouteInfo> routes;
+
     public DhcpInfoInternal() {
+        routes = new ArrayList<RouteInfo>();
+    }
+
+    public void addRoute(RouteInfo routeInfo) {
+        routes.add(routeInfo);
     }
 
     private int convertToInt(String addr) {
@@ -58,7 +66,12 @@
     public DhcpInfo makeDhcpInfo() {
         DhcpInfo info = new DhcpInfo();
         info.ipAddress = convertToInt(ipAddress);
-        info.gateway = convertToInt(gateway);
+        for (RouteInfo route : routes) {
+            if (route.isDefaultRoute()) {
+                info.gateway = convertToInt(route.getGateway().getHostAddress());
+                break;
+            }
+        }
         try {
             InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
             info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
@@ -81,8 +94,8 @@
     public LinkProperties makeLinkProperties() {
         LinkProperties p = new LinkProperties();
         p.addLinkAddress(makeLinkAddress());
-        if (TextUtils.isEmpty(gateway) == false) {
-            p.addGateway(NetworkUtils.numericToInetAddress(gateway));
+        for (RouteInfo route : routes) {
+            p.addRoute(route);
         }
         if (TextUtils.isEmpty(dns1) == false) {
             p.addDns(NetworkUtils.numericToInetAddress(dns1));
@@ -98,8 +111,10 @@
     }
 
     public String toString() {
+        String routeString = "";
+        for (RouteInfo route : routes) routeString += route.toString() + " | ";
         return "addr: " + ipAddress + "/" + prefixLength +
-                " gateway: " + gateway +
+                " routes: " + routeString +
                 " dns: " + dns1 + "," + dns2 +
                 " dhcpServer: " + serverAddress +
                 " leaseDuration: " + leaseDuration;
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index e88292f..61acf2b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -54,7 +54,7 @@
     String mIfaceName;
     private Collection<LinkAddress> mLinkAddresses;
     private Collection<InetAddress> mDnses;
-    private Collection<InetAddress> mGateways;
+    private Collection<RouteInfo> mRoutes;
     private ProxyProperties mHttpProxy;
 
     public LinkProperties() {
@@ -67,7 +67,7 @@
             mIfaceName = source.getInterfaceName();
             mLinkAddresses = source.getLinkAddresses();
             mDnses = source.getDnses();
-            mGateways = source.getGateways();
+            mRoutes = source.getRoutes();
             mHttpProxy = new ProxyProperties(source.getHttpProxy());
         }
     }
@@ -104,11 +104,11 @@
         return Collections.unmodifiableCollection(mDnses);
     }
 
-    public void addGateway(InetAddress gateway) {
-        if (gateway != null) mGateways.add(gateway);
+    public void addRoute(RouteInfo route) {
+        if (route != null) mRoutes.add(route);
     }
-    public Collection<InetAddress> getGateways() {
-        return Collections.unmodifiableCollection(mGateways);
+    public Collection<RouteInfo> getRoutes() {
+        return Collections.unmodifiableCollection(mRoutes);
     }
 
     public void setHttpProxy(ProxyProperties proxy) {
@@ -122,7 +122,7 @@
         mIfaceName = null;
         mLinkAddresses = new ArrayList<LinkAddress>();
         mDnses = new ArrayList<InetAddress>();
-        mGateways = new ArrayList<InetAddress>();
+        mRoutes = new ArrayList<RouteInfo>();
         mHttpProxy = null;
     }
 
@@ -146,12 +146,12 @@
         for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
         dns += "] ";
 
-        String gateways = "Gateways: [";
-        for (InetAddress gw : mGateways) gateways += gw.getHostAddress() + ",";
-        gateways += "] ";
+        String routes = "Routes: [";
+        for (RouteInfo route : mRoutes) routes += route.toString() + ",";
+        routes += "] ";
         String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
 
-        return ifaceName + linkAddresses + gateways + dns + proxy;
+        return ifaceName + linkAddresses + routes + dns + proxy;
     }
 
 
@@ -177,7 +177,7 @@
 
         boolean sameAddresses;
         boolean sameDnses;
-        boolean sameGateways;
+        boolean sameRoutes;
 
         LinkProperties target = (LinkProperties) obj;
 
@@ -190,12 +190,12 @@
         sameDnses = (mDnses.size() == targetDnses.size()) ?
                 mDnses.containsAll(targetDnses) : false;
 
-        Collection<InetAddress> targetGateways = target.getGateways();
-        sameGateways = (mGateways.size() == targetGateways.size()) ?
-                mGateways.containsAll(targetGateways) : false;
+        Collection<RouteInfo> targetRoutes = target.getRoutes();
+        sameRoutes = (mRoutes.size() == targetRoutes.size()) ?
+                mRoutes.containsAll(targetRoutes) : false;
 
         return
-            sameAddresses && sameDnses && sameGateways
+            sameAddresses && sameDnses && sameRoutes
             && TextUtils.equals(getInterfaceName(), target.getInterfaceName())
             && (getHttpProxy() == null ? target.getHttpProxy() == null :
                 getHttpProxy().equals(target.getHttpProxy()));
@@ -211,7 +211,7 @@
         return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
                 + mLinkAddresses.size() * 31
                 + mDnses.size() * 37
-                + mGateways.size() * 41
+                + mRoutes.size() * 41
                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
     }
 
@@ -231,9 +231,9 @@
             dest.writeByteArray(d.getAddress());
         }
 
-        dest.writeInt(mGateways.size());
-        for(InetAddress gw : mGateways) {
-            dest.writeByteArray(gw.getAddress());
+        dest.writeInt(mRoutes.size());
+        for(RouteInfo route : mRoutes) {
+            dest.writeParcelable(route, flags);
         }
 
         if (mHttpProxy != null) {
@@ -272,9 +272,7 @@
                 }
                 addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
-                    try {
-                        netProp.addGateway(InetAddress.getByAddress(in.createByteArray()));
-                    } catch (UnknownHostException e) { }
+                    netProp.addRoute((RouteInfo)in.readParcelable(null));
                 }
                 if (in.readByte() == 1) {
                     netProp.setHttpProxy((ProxyProperties)in.readParcelable(null));
diff --git a/core/java/android/net/RouteInfo.aidl b/core/java/android/net/RouteInfo.aidl
new file mode 100644
index 0000000..2296a57
--- /dev/null
+++ b/core/java/android/net/RouteInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable RouteInfo;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
new file mode 100644
index 0000000..5b10531
--- /dev/null
+++ b/core/java/android/net/RouteInfo.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+/**
+ * A simple container for route information.
+ *
+ * @hide
+ */
+public class RouteInfo implements Parcelable {
+    /**
+     * The IP destination address for this route.
+     */
+    private final LinkAddress mDestination;
+
+    /**
+     * The gateway address for this route.
+     */
+    private final InetAddress mGateway;
+
+    private final boolean mIsDefault;
+
+    public RouteInfo(LinkAddress destination, InetAddress gateway) {
+        if (destination == null) {
+            try {
+                if ((gateway != null) && (gateway instanceof Inet4Address)) {
+                    destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+                } else {
+                    destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+                }
+            } catch (Exception e) {}
+        }
+        mDestination = destination;
+        mGateway = gateway;
+        mIsDefault = isDefault();
+    }
+
+    public RouteInfo(InetAddress gateway) {
+        LinkAddress destination = null;
+        try {
+            if ((gateway != null) && (gateway instanceof Inet4Address)) {
+                destination = new LinkAddress(InetAddress.getByName("0.0.0.0"), 32);
+            } else {
+                destination = new LinkAddress(InetAddress.getByName("::0"), 128);
+            }
+        } catch (Exception e) {}
+        mDestination = destination;
+        mGateway = gateway;
+        mIsDefault = isDefault();
+    }
+
+    private boolean isDefault() {
+        boolean val = false;
+        if (mGateway != null) {
+            if (mGateway instanceof Inet4Address) {
+                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 32);
+            } else {
+                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 128);
+            }
+        }
+        return val;
+    }
+
+    public LinkAddress getDestination() {
+        return mDestination;
+    }
+
+    public InetAddress getGateway() {
+        return mGateway;
+    }
+
+    public boolean isDefaultRoute() {
+        return mIsDefault;
+    }
+
+    public String toString() {
+        String val = "";
+        if (mDestination != null) val = mDestination.toString();
+        if (mGateway != null) val += " -> " + mGateway.getHostAddress();
+        return val;
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        if (mDestination == null) {
+            dest.writeByte((byte) 0);
+        } else {
+            dest.writeByte((byte) 1);
+            dest.writeByteArray(mDestination.getAddress().getAddress());
+            dest.writeInt(mDestination.getNetworkPrefixLength());
+        }
+
+        if (mGateway == null) {
+            dest.writeByte((byte) 0);
+        } else {
+            dest.writeByte((byte) 1);
+            dest.writeByteArray(mGateway.getAddress());
+        }
+    }
+
+    public static final Creator<RouteInfo> CREATOR =
+        new Creator<RouteInfo>() {
+        public RouteInfo createFromParcel(Parcel in) {
+            InetAddress destAddr = null;
+            int prefix = 0;
+            InetAddress gateway = null;
+
+            if (in.readByte() == 1) {
+                byte[] addr = in.createByteArray();
+                prefix = in.readInt();
+
+                try {
+                    destAddr = InetAddress.getByAddress(addr);
+                } catch (UnknownHostException e) {}
+            }
+
+            if (in.readByte() == 1) {
+                byte[] addr = in.createByteArray();
+
+                try {
+                    gateway = InetAddress.getByAddress(addr);
+                } catch (UnknownHostException e) {}
+            }
+
+            LinkAddress dest = null;
+
+            if (destAddr != null) {
+                dest = new LinkAddress(destAddr, prefix);
+            }
+
+            return new RouteInfo(dest, gateway);
+        }
+
+        public RouteInfo[] newArray(int size) {
+            return new RouteInfo[size];
+        }
+    };
+}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 4becad7..904eaf9 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -68,7 +68,6 @@
     jclass dhcpInfoInternalClass;
     jmethodID constructorId;
     jfieldID ipaddress;
-    jfieldID gateway;
     jfieldID prefixLength;
     jfieldID dns1;
     jfieldID dns2;
@@ -182,7 +181,30 @@
     env->ReleaseStringUTFChars(ifname, nameStr);
     if (result == 0 && dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
         env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.gateway, env->NewStringUTF(gateway));
+
+        // set the gateway
+        jclass cls = env->FindClass("java/net/InetAddress");
+        jmethodID method = env->GetStaticMethodID(cls, "getByName",
+                "(Ljava/lang/String;)Ljava/net/InetAddress;");
+        jvalue args[1];
+        args[0].l = env->NewStringUTF(gateway);
+        jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
+
+        if (!env->ExceptionOccurred()) {
+            cls = env->FindClass("android/net/RouteInfo");
+            method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
+            args[0].l = inetAddressObject;
+            jobject routeInfoObject = env->NewObjectA(cls, method, args);
+
+            cls = env->FindClass("android/net/DhcpInfoInternal");
+            method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
+            args[0].l = routeInfoObject;
+            env->CallVoidMethodA(info, method, args);
+        } else {
+            // if we have an exception (host not found perhaps), just don't add the route
+            env->ExceptionClear();
+        }
+
         env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
@@ -262,7 +284,6 @@
     if (dhcpInfoInternalFieldIds.dhcpInfoInternalClass != NULL) {
         dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "<init>", "()V");
         dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
-        dhcpInfoInternalFieldIds.gateway = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "gateway", "Ljava/lang/String;");
         dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "prefixLength", "I");
         dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
         dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalFieldIds.dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index d22356d..27363e8 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -30,6 +30,7 @@
 import android.net.wifi.WifiConfiguration.ProxySettings;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.RouteInfo;
 import android.util.Log;
 
 import java.io.InputStream;
@@ -301,7 +302,7 @@
                     if (!InetAddress.isNumeric(gwAddr)) {
                         throw new SAXException();
                     }
-                    mLinkProperties.addGateway(InetAddress.getByName(gwAddr));
+                    mLinkProperties.addRoute(new RouteInfo(InetAddress.getByName(gwAddr)));
                 } catch (UnknownHostException e) {
                     throw new SAXException();
                 }
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index 50666b4..e3b6b5f 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.net.LinkProperties;
+import android.net.RouteInfo;
 import android.test.suitebuilder.annotation.SmallTest;
 import junit.framework.TestCase;
 
@@ -55,8 +56,8 @@
             source.addDns(NetworkUtils.numericToInetAddress(DNS1));
             source.addDns(NetworkUtils.numericToInetAddress(DNS2));
             // set 2 gateways
-            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
 
             LinkProperties target = new LinkProperties();
 
@@ -68,8 +69,8 @@
                     NetworkUtils.numericToInetAddress(ADDRV6), 128));
             target.addDns(NetworkUtils.numericToInetAddress(DNS1));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
 
             assertTrue(source.equals(target));
             assertTrue(source.hashCode() == target.hashCode());
@@ -83,8 +84,8 @@
                     NetworkUtils.numericToInetAddress(ADDRV6), 128));
             target.addDns(NetworkUtils.numericToInetAddress(DNS1));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
             assertFalse(source.equals(target));
 
             target.clear();
@@ -96,8 +97,8 @@
                     NetworkUtils.numericToInetAddress(ADDRV6), 128));
             target.addDns(NetworkUtils.numericToInetAddress(DNS1));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
             assertFalse(source.equals(target));
 
             target.clear();
@@ -109,8 +110,8 @@
             // change dnses
             target.addDns(NetworkUtils.numericToInetAddress("75.208.7.2"));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
             assertFalse(source.equals(target));
 
             target.clear();
@@ -122,8 +123,8 @@
             target.addDns(NetworkUtils.numericToInetAddress(DNS1));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
             // change gateway
-            target.addGateway(NetworkUtils.numericToInetAddress("75.208.8.2"));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
             assertFalse(source.equals(target));
 
         } catch (Exception e) {
@@ -146,8 +147,8 @@
             source.addDns(NetworkUtils.numericToInetAddress(DNS1));
             source.addDns(NetworkUtils.numericToInetAddress(DNS2));
             // set 2 gateways
-            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
-            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
+            source.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
 
             LinkProperties target = new LinkProperties();
             // Exchange order
@@ -158,8 +159,8 @@
                     NetworkUtils.numericToInetAddress(ADDRV4), 32));
             target.addDns(NetworkUtils.numericToInetAddress(DNS2));
             target.addDns(NetworkUtils.numericToInetAddress(DNS1));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
-            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY2)));
+            target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(GATEWAY1)));
 
             assertTrue(source.equals(target));
             assertTrue(source.hashCode() == target.hashCode());
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index e867b0b..56b6c54 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -34,6 +34,7 @@
 import android.net.NetworkUtils;
 import android.net.Proxy;
 import android.net.ProxyProperties;
+import android.net.RouteInfo;
 import android.net.vpn.VpnManager;
 import android.net.wifi.WifiStateTracker;
 import android.os.Binder;
@@ -1417,14 +1418,19 @@
         if (p == null) return;
         String interfaceName = p.getInterfaceName();
         if (TextUtils.isEmpty(interfaceName)) return;
-        for (InetAddress gateway : p.getGateways()) {
+        for (RouteInfo route : p.getRoutes()) {
 
-            if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
-                    NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
-                if (DBG) {
-                    NetworkInfo networkInfo = nt.getNetworkInfo();
-                    log("addDefaultRoute for " + networkInfo.getTypeName() +
-                            " (" + interfaceName + "), GatewayAddr=" + gateway.getHostAddress());
+            //TODO - handle non-default routes
+            if (route.isDefaultRoute()) {
+                InetAddress gateway = route.getGateway();
+                if (NetworkUtils.addHostRoute(interfaceName, gateway, null) &&
+                        NetworkUtils.addDefaultRoute(interfaceName, gateway)) {
+                    if (DBG) {
+                        NetworkInfo networkInfo = nt.getNetworkInfo();
+                        log("addDefaultRoute for " + networkInfo.getTypeName() +
+                                " (" + interfaceName + "), GatewayAddr=" +
+                                gateway.getHostAddress());
+                    }
                 }
             }
         }
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index a883e8e..1d67d45 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -20,6 +20,7 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
+import android.net.RouteInfo;
 import android.os.SystemProperties;
 import android.util.Log;
 
@@ -196,7 +197,7 @@
                     } catch (IllegalArgumentException e) {
                         throw new UnknownHostException("Non-numeric gateway addr=" + addr);
                     }
-                    linkProperties.addGateway(ia);
+                    linkProperties.addRoute(new RouteInfo(ia));
                 }
 
                 result = SetupResult.SUCCESS;
@@ -223,5 +224,3 @@
         return result;
     }
 }
-
-
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 6455d84..7f9fc31 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -23,6 +23,7 @@
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
 import android.net.ProxyProperties;
+import android.net.RouteInfo;
 import android.net.wifi.WifiConfiguration.IpAssignment;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.ProxySettings;
@@ -120,7 +121,7 @@
     private static final String ipConfigFile = Environment.getDataDirectory() +
             "/misc/wifi/ipconfig.txt";
 
-    private static final int IPCONFIG_FILE_VERSION = 1;
+    private static final int IPCONFIG_FILE_VERSION = 2;
 
     /* IP and proxy configuration keys */
     private static final String ID_KEY = "id";
@@ -445,9 +446,8 @@
             if (iter.hasNext()) {
                 LinkAddress linkAddress = iter.next();
                 dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
-                Iterator<InetAddress>gateways = linkProperties.getGateways().iterator();
-                if (gateways.hasNext()) {
-                    dhcpInfoInternal.gateway = gateways.next().getHostAddress();
+                for (RouteInfo route : linkProperties.getRoutes()) {
+                    dhcpInfoInternal.addRoute(route);
                 }
                 dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
                 Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
@@ -604,9 +604,22 @@
                                     out.writeUTF(linkAddr.getAddress().getHostAddress());
                                     out.writeInt(linkAddr.getNetworkPrefixLength());
                                 }
-                                for (InetAddress gateway : linkProperties.getGateways()) {
+                                for (RouteInfo route : linkProperties.getRoutes()) {
                                     out.writeUTF(GATEWAY_KEY);
-                                    out.writeUTF(gateway.getHostAddress());
+                                    LinkAddress dest = route.getDestination();
+                                    if (dest != null) {
+                                        out.writeInt(1);
+                                        out.writeUTF(dest.getAddress().getHostAddress());
+                                        out.writeInt(dest.getNetworkPrefixLength());
+                                    } else {
+                                        out.writeInt(0);
+                                    }
+                                    if (route.getGateway() != null) {
+                                        out.writeInt(1);
+                                        out.writeUTF(route.getGateway().getHostAddress());
+                                    } else {
+                                        out.writeInt(0);
+                                    }
                                 }
                                 for (InetAddress inetAddr : linkProperties.getDnses()) {
                                     out.writeUTF(DNS_KEY);
@@ -682,7 +695,8 @@
             in = new DataInputStream(new BufferedInputStream(new FileInputStream(
                     ipConfigFile)));
 
-            if (in.readInt() != IPCONFIG_FILE_VERSION) {
+            int version = in.readInt();
+            if (version != 2 && version != 1) {
                 Log.e(TAG, "Bad version on IP configuration file, ignore read");
                 return;
             }
@@ -709,8 +723,22 @@
                                     NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt());
                             linkProperties.addLinkAddress(linkAddr);
                         } else if (key.equals(GATEWAY_KEY)) {
-                            linkProperties.addGateway(
-                                    NetworkUtils.numericToInetAddress(in.readUTF()));
+                            LinkAddress dest = null;
+                            InetAddress gateway = null;
+                            if (version == 1) {
+                                // only supported default gateways - leave the dest/prefix empty
+                                gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                            } else {
+                                if (in.readInt() == 1) {
+                                    dest = new LinkAddress(
+                                            NetworkUtils.numericToInetAddress(in.readUTF()),
+                                            in.readInt());
+                                }
+                                if (in.readInt() == 1) {
+                                    gateway = NetworkUtils.numericToInetAddress(in.readUTF());
+                                }
+                            }
+                            linkProperties.addRoute(new RouteInfo(dest, gateway));
                         } else if (key.equals(DNS_KEY)) {
                             linkProperties.addDns(
                                     NetworkUtils.numericToInetAddress(in.readUTF()));
@@ -1022,22 +1050,21 @@
                         .getLinkAddresses();
                 Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses();
                 Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses();
-                Collection<InetAddress> currentGateways =
-                        currentConfig.linkProperties.getGateways();
-                Collection<InetAddress> newGateways = newConfig.linkProperties.getGateways();
+                Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes();
+                Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes();
 
                 boolean linkAddressesDiffer =
                         (currentLinkAddresses.size() != newLinkAddresses.size()) ||
                         !currentLinkAddresses.containsAll(newLinkAddresses);
                 boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) ||
                         !currentDnses.containsAll(newDnses);
-                boolean gatewaysDiffer = (currentGateways.size() != newGateways.size()) ||
-                        !currentGateways.containsAll(newGateways);
+                boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) ||
+                        !currentRoutes.containsAll(newRoutes);
 
                 if ((currentConfig.ipAssignment != newConfig.ipAssignment) ||
                         linkAddressesDiffer ||
                         dnsesDiffer ||
-                        gatewaysDiffer) {
+                        routesDiffer) {
                     ipChanged = true;
                 }
                 break;
@@ -1112,8 +1139,8 @@
         for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) {
             linkProperties.addLinkAddress(linkAddr);
         }
-        for (InetAddress gateway : config.linkProperties.getGateways()) {
-            linkProperties.addGateway(gateway);
+        for (RouteInfo route : config.linkProperties.getRoutes()) {
+            linkProperties.addRoute(route);
         }
         for (InetAddress dns : config.linkProperties.getDnses()) {
             linkProperties.addDns(dns);