Remove DhcpInfoInternal

First step in accepting a set of patches.
bug:6799630

Change-Id: I6c894c60aeb3022960c2aaa45451bb1dde2b493b
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 063e5a8..3ba4f26 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -21,7 +21,6 @@
 import android.os.INetworkManagementService;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.DhcpInfoInternal;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
index e2660e4..2b359eb 100644
--- a/core/java/android/net/DhcpInfo.java
+++ b/core/java/android/net/DhcpInfo.java
@@ -22,16 +22,17 @@
 
 /**
  * A simple object for retrieving the results of a DHCP request.
+ * @deprecated - use LinkProperties - To be removed 11/2013
+ * STOPSHIP - make sure we expose LinkProperties through ConnectivityManager
  */
 public class DhcpInfo implements Parcelable {
     public int ipAddress;
     public int gateway;
     public int netmask;
-
     public int dns1;
     public int dns2;
-
     public int serverAddress;
+
     public int leaseDuration;
 
     public DhcpInfo() {
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
deleted file mode 100644
index f3508c1..0000000
--- a/core/java/android/net/DhcpInfoInternal.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2010 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.text.TextUtils;
-import android.util.Log;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * A simple object for retrieving the results of a DHCP request.
- * Replaces (internally) the IPv4-only DhcpInfo class.
- * @hide
- */
-public class DhcpInfoInternal {
-    private final static String TAG = "DhcpInfoInternal";
-    public String ipAddress;
-    public int prefixLength;
-
-    public String dns1;
-    public String dns2;
-
-    public String serverAddress;
-    public int leaseDuration;
-
-    /**
-     * Vendor specific information (from RFC 2132).
-     */
-    public String vendorInfo;
-
-    private Collection<RouteInfo> mRoutes;
-
-    public DhcpInfoInternal() {
-        mRoutes = new ArrayList<RouteInfo>();
-    }
-
-    public void addRoute(RouteInfo routeInfo) {
-        mRoutes.add(routeInfo);
-    }
-
-    public Collection<RouteInfo> getRoutes() {
-        return Collections.unmodifiableCollection(mRoutes);
-    }
-
-    private int convertToInt(String addr) {
-        if (addr != null) {
-            try {
-                InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
-                if (inetAddress instanceof Inet4Address) {
-                    return NetworkUtils.inetAddressToInt(inetAddress);
-                }
-            } catch (IllegalArgumentException e) {}
-        }
-        return 0;
-    }
-
-    public DhcpInfo makeDhcpInfo() {
-        DhcpInfo info = new DhcpInfo();
-        info.ipAddress = convertToInt(ipAddress);
-        for (RouteInfo route : mRoutes) {
-            if (route.isDefaultRoute()) {
-                info.gateway = convertToInt(route.getGateway().getHostAddress());
-                break;
-            }
-        }
-        try {
-            InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
-            info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
-        } catch (IllegalArgumentException e) {}
-        info.dns1 = convertToInt(dns1);
-        info.dns2 = convertToInt(dns2);
-        info.serverAddress = convertToInt(serverAddress);
-        info.leaseDuration = leaseDuration;
-        return info;
-    }
-
-    public LinkAddress makeLinkAddress() {
-        if (TextUtils.isEmpty(ipAddress)) {
-            Log.e(TAG, "makeLinkAddress with empty ipAddress");
-            return null;
-        }
-        return new LinkAddress(NetworkUtils.numericToInetAddress(ipAddress), prefixLength);
-    }
-
-    public LinkProperties makeLinkProperties() {
-        LinkProperties p = new LinkProperties();
-        p.addLinkAddress(makeLinkAddress());
-        for (RouteInfo route : mRoutes) {
-            p.addRoute(route);
-        }
-        //if empty, connectivity configures default DNS
-        if (TextUtils.isEmpty(dns1) == false) {
-            p.addDns(NetworkUtils.numericToInetAddress(dns1));
-        } else {
-            Log.d(TAG, "makeLinkProperties with empty dns1!");
-        }
-        if (TextUtils.isEmpty(dns2) == false) {
-            p.addDns(NetworkUtils.numericToInetAddress(dns2));
-        } else {
-            Log.d(TAG, "makeLinkProperties with empty dns2!");
-        }
-        return p;
-    }
-
-    /* Updates the DHCP fields that need to be retained from
-     * original DHCP request if the DHCP renewal shows them as
-     * being empty
-     */
-    public void updateFromDhcpRequest(DhcpInfoInternal orig) {
-        if (orig == null) return;
-
-        if (TextUtils.isEmpty(dns1)) {
-            dns1 = orig.dns1;
-        }
-
-        if (TextUtils.isEmpty(dns2)) {
-            dns2 = orig.dns2;
-        }
-
-        if (mRoutes.size() == 0) {
-            for (RouteInfo route : orig.getRoutes()) {
-                addRoute(route);
-            }
-        }
-    }
-
-    /**
-     * Test if this DHCP lease includes vendor hint that network link is
-     * metered, and sensitive to heavy data transfers.
-     */
-    public boolean hasMeteredHint() {
-        if (vendorInfo != null) {
-            return vendorInfo.contains("ANDROID_METERED");
-        } else {
-            return false;
-        }
-    }
-
-    public String toString() {
-        String routeString = "";
-        for (RouteInfo route : mRoutes) routeString += route.toString() + " | ";
-        return "addr: " + ipAddress + "/" + prefixLength +
-                " mRoutes: " + routeString +
-                " dns: " + dns1 + "," + dns2 +
-                " dhcpServer: " + serverAddress +
-                " leaseDuration: " + leaseDuration;
-    }
-}
diff --git a/core/java/android/net/DhcpResults.aidl b/core/java/android/net/DhcpResults.aidl
new file mode 100644
index 0000000..f4db3c3
--- /dev/null
+++ b/core/java/android/net/DhcpResults.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2012, 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 DhcpResults;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
new file mode 100644
index 0000000..23297df
--- /dev/null
+++ b/core/java/android/net/DhcpResults.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2012 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.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A simple object for retrieving the results of a DHCP request.
+ * Optimized (attempted) for that jni interface
+ * TODO - remove when DhcpInfo is deprecated.  Move the remaining api to LinkProperties.
+ * @hide
+ */
+public class DhcpResults implements Parcelable {
+    private static final String TAG = "DhcpResults";
+
+    public final LinkProperties linkProperties;
+
+    public InetAddress serverAddress;
+
+    /**
+     * Vendor specific information (from RFC 2132).
+     */
+    public String vendorInfo;
+
+    public int leaseDuration;
+
+    public DhcpResults() {
+        linkProperties = new LinkProperties();
+    }
+
+    /** copy constructor */
+    public DhcpResults(DhcpResults source) {
+        if (source != null) {
+            linkProperties = new LinkProperties(source.linkProperties);
+            serverAddress = source.serverAddress;
+            leaseDuration = source.leaseDuration;
+            vendorInfo = source.vendorInfo;
+        } else {
+            linkProperties = new LinkProperties();
+        }
+    }
+
+    public DhcpResults(LinkProperties lp) {
+        linkProperties = new LinkProperties(lp);
+    }
+
+    /**
+     * Updates the DHCP fields that need to be retained from
+     * original DHCP request if the current renewal shows them
+     * being empty.
+     */
+    public void updateFromDhcpRequest(DhcpResults orig) {
+        if (orig == null || orig.linkProperties == null) return;
+        if (linkProperties.getRoutes().size() == 0) {
+            for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
+        }
+        if (linkProperties.getDnses().size() == 0) {
+            for (InetAddress d : orig.linkProperties.getDnses()) linkProperties.addDns(d);
+        }
+    }
+
+    /**
+     * Test if this DHCP lease includes vendor hint that network link is
+     * metered, and sensitive to heavy data transfers.
+     */
+    public boolean hasMeteredHint() {
+        if (vendorInfo != null) {
+            return vendorInfo.contains("ANDROID_METERED");
+        } else {
+            return false;
+        }
+    }
+
+    public void clear() {
+        linkProperties.clear();
+        serverAddress = null;
+        vendorInfo = null;
+        leaseDuration = 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer str = new StringBuffer(linkProperties.toString());
+
+        str.append(" DHCP server ").append(serverAddress);
+        str.append(" Vendor info ").append(vendorInfo);
+        str.append(" lease ").append(leaseDuration).append(" seconds");
+
+        return str.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof DhcpResults)) return false;
+
+        DhcpResults target = (DhcpResults)obj;
+
+        if (linkProperties == null) {
+            if (target.linkProperties != null) return false;
+        } else if (!linkProperties.equals(target.linkProperties)) return false;
+        if (serverAddress == null) {
+            if (target.serverAddress != null) return false;
+        } else if (!serverAddress.equals(target.serverAddress)) return false;
+        if (vendorInfo == null) {
+            if (target.vendorInfo != null) return false;
+        } else if (!vendorInfo.equals(target.vendorInfo)) return false;
+        if (leaseDuration != target.leaseDuration) return false;
+
+        return true;
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        linkProperties.writeToParcel(dest, flags);
+
+        dest.writeInt(leaseDuration);
+
+        if (serverAddress != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(serverAddress.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
+
+        dest.writeString(vendorInfo);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<DhcpResults> CREATOR =
+        new Creator<DhcpResults>() {
+            public DhcpResults createFromParcel(Parcel in) {
+                DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null));
+
+                prop.leaseDuration = in.readInt();
+
+                if (in.readByte() == 1) {
+                    try {
+                        prop.serverAddress = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
+
+                prop.vendorInfo = in.readString();
+
+                return prop;
+            }
+
+            public DhcpResults[] newArray(int size) {
+                return new DhcpResults[size];
+            }
+        };
+
+    // Utils for jni population - false on success
+    public void setInterfaceName(String interfaceName) {
+        linkProperties.setInterfaceName(interfaceName);
+    }
+
+    public boolean addLinkAddress(String addrString, int prefixLength) {
+        InetAddress addr;
+        try {
+            addr = NetworkUtils.numericToInetAddress(addrString);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addLinkAddress failed with addrString " + addrString);
+            return true;
+        }
+
+        LinkAddress linkAddress = new LinkAddress(addr, prefixLength);
+        linkProperties.addLinkAddress(linkAddress);
+
+        RouteInfo routeInfo = new RouteInfo(linkAddress);
+        linkProperties.addRoute(routeInfo);
+        return false;
+    }
+
+    public boolean addGateway(String addrString) {
+        try {
+            linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString)));
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addGateway failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean addDns(String addrString) {
+        try {
+            linkProperties.addDns(NetworkUtils.numericToInetAddress(addrString));
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addDns failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean setServerAddress(String addrString) {
+        try {
+            serverAddress = NetworkUtils.numericToInetAddress(addrString);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "setServerAddress failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public void setLeaseDuration(int duration) {
+        leaseDuration = duration;
+    }
+
+    public void setVendorInfo(String info) {
+        vendorInfo = info;
+    }
+
+}
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 874e80a..57db91f 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -26,7 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.net.DhcpInfoInternal;
+import android.net.DhcpResults;
 import android.net.NetworkUtils;
 import android.os.Message;
 import android.os.PowerManager;
@@ -64,7 +64,7 @@
     private static final String WAKELOCK_TAG = "DHCP";
 
     //Remember DHCP configuration from first request
-    private DhcpInfoInternal mDhcpInfo;
+    private DhcpResults mDhcpResults;
 
     private static final int DHCP_RENEW = 0;
     private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
@@ -348,21 +348,19 @@
 
     private boolean runDhcp(DhcpAction dhcpAction) {
         boolean success = false;
-        DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+        DhcpResults dhcpResults = new DhcpResults();
 
         if (dhcpAction == DhcpAction.START) {
             if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
-            success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
-            mDhcpInfo = dhcpInfoInternal;
+            success = NetworkUtils.runDhcp(mInterfaceName, dhcpResults);
         } else if (dhcpAction == DhcpAction.RENEW) {
             if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
-            success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal);
-            dhcpInfoInternal.updateFromDhcpRequest(mDhcpInfo);
+            success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpResults);
+            dhcpResults.updateFromDhcpRequest(mDhcpResults);
         }
-
         if (success) {
             if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
-            long leaseDuration = dhcpInfoInternal.leaseDuration; //int to long conversion
+            long leaseDuration = dhcpResults.leaseDuration; //int to long conversion
 
             //Sanity check for renewal
             if (leaseDuration >= 0) {
@@ -382,7 +380,8 @@
                 //infinite lease time, no renewal needed
             }
 
-            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal)
+            mDhcpResults = dhcpResults;
+            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults)
                 .sendToTarget();
         } else {
             Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " +
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 3a06dc0..5b98b8f 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -170,13 +170,12 @@
     private void runDhcp() {
         Thread dhcpThread = new Thread(new Runnable() {
             public void run() {
-                DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
-                if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
+                DhcpResults dhcpResults = new DhcpResults();
+                if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
                     return;
                 }
-                mLinkProperties = dhcpInfoInternal.makeLinkProperties();
-                mLinkProperties.setInterfaceName(mIface);
+                mLinkProperties = dhcpResults.linkProperties;
 
                 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
                 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 75646fd..60bf640b 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -51,7 +51,7 @@
  */
 public class LinkProperties implements Parcelable {
 
-    String mIfaceName;
+    private String mIfaceName;
     private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
     private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
     private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
@@ -181,7 +181,7 @@
     }
 
     /**
-     * Compares this {@code LinkProperties} interface name against the target
+     * Compares this {@code LinkProperties} interface addresses against the target
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
@@ -365,7 +365,6 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(getInterfaceName());
@@ -394,19 +393,15 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public static final Creator<LinkProperties> CREATOR =
         new Creator<LinkProperties>() {
             public LinkProperties createFromParcel(Parcel in) {
                 LinkProperties netProp = new LinkProperties();
+
                 String iface = in.readString();
                 if (iface != null) {
-                    try {
-                        netProp.setInterfaceName(iface);
-                    } catch (Exception e) {
-                        return null;
-                    }
+                    netProp.setInterfaceName(iface);
                 }
                 int addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d39e741e..4ab479e 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,21 +62,21 @@
      * addresses. This call blocks until it obtains a result (either success
      * or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
      * a result (either success or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Shut down the DHCP client daemon.
@@ -124,12 +124,9 @@
      * @param inetAddr is an InetAddress corresponding to the IPv4 address
      * @return the IP address as an integer in network byte order
      */
-    public static int inetAddressToInt(InetAddress inetAddr)
+    public static int inetAddressToInt(Inet4Address inetAddr)
             throws IllegalArgumentException {
         byte [] addr = inetAddr.getAddress();
-        if (addr.length != 4) {
-            throw new IllegalArgumentException("Not an IPv4 address");
-        }
         return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
                 ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
     }
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 275f32a..112e143 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -76,6 +76,10 @@
         this(null, gateway);
     }
 
+    public RouteInfo(LinkAddress host) {
+        this(host, null);
+    }
+
     public static RouteInfo makeHostRoute(InetAddress host) {
         return makeHostRoute(host, null);
     }
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 1f2b1ae..5bdaac6 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -63,15 +63,15 @@
  * to look them up every time.
  */
 static struct fieldIds {
-    jmethodID constructorId;
-    jfieldID ipaddress;
-    jfieldID prefixLength;
-    jfieldID dns1;
-    jfieldID dns2;
-    jfieldID serverAddress;
-    jfieldID leaseDuration;
-    jfieldID vendorInfo;
-} dhcpInfoInternalFieldIds;
+    jmethodID clear;
+    jmethodID setInterfaceName;
+    jmethodID addLinkAddress;
+    jmethodID addGateway;
+    jmethodID addDns;
+    jmethodID setServerAddress;
+    jmethodID setLeaseDuration;
+    jmethodID setVendorInfo;
+} dhcpResultsFieldIds;
 
 static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
 {
@@ -109,7 +109,7 @@
 }
 
 static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
-        jobject info, bool renew)
+        jobject dhcpResults, bool renew)
 {
     int result;
     char  ipaddr[PROPERTY_VALUE_MAX];
@@ -134,42 +134,55 @@
 
     env->ReleaseStringUTFChars(ifname, nameStr);
     if (result == 0) {
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
 
+        // set mIfaceName
+        // dhcpResults->setInterfaceName(ifname)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
+
+        // set the linkAddress
+        // dhcpResults->addLinkAddress(inetAddress, prefixLength)
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
+                env->NewStringUTF(ipaddr), prefixLength);
+    }
+
+    if (result == 0) {
         // 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);
+        // dhcpResults->addGateway(gateway)
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
+    }
 
-        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);
+    if (result == 0) {
+        // dhcpResults->addDns(new InetAddress(dns1))
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
+    }
 
-            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();
-        }
+    if (result == 0) {
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
+    }
 
-        env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
+    if (result == 0) {
+        // dhcpResults->setServerAddress(new InetAddress(server))
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
                 env->NewStringUTF(server));
-        env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.vendorInfo, env->NewStringUTF(vendorInfo));
+    }
+
+    if (result == 0) {
+        // dhcpResults->setLeaseDuration(lease)
+        env->CallVoidMethod(dhcpResults,
+                dhcpResultsFieldIds.setLeaseDuration, lease);
+
+        // dhcpResults->setVendorInfo(vendorInfo)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
+                env->NewStringUTF(vendorInfo));
     }
     return (jboolean)(result == 0);
 }
 
+
 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
 {
     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
@@ -217,8 +230,8 @@
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
-    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
-    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
+    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
+    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -226,16 +239,24 @@
 
 int register_android_net_NetworkUtils(JNIEnv* env)
 {
-    jclass dhcpInfoInternalClass = env->FindClass("android/net/DhcpInfoInternal");
-    LOG_FATAL_IF(dhcpInfoInternalClass == NULL, "Unable to find class android/net/DhcpInfoInternal");
-    dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalClass, "<init>", "()V");
-    dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalClass, "prefixLength", "I");
-    dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalClass, "leaseDuration", "I");
-    dhcpInfoInternalFieldIds.vendorInfo = env->GetFieldID(dhcpInfoInternalClass, "vendorInfo", "Ljava/lang/String;");
+    jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults");
+    LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
+    dhcpResultsFieldIds.clear =
+            env->GetMethodID(dhcpResultsClass, "clear", "()V");
+    dhcpResultsFieldIds.setInterfaceName =
+            env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
+    dhcpResultsFieldIds.addLinkAddress =
+            env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
+    dhcpResultsFieldIds.addGateway =
+            env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.addDns =
+            env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setServerAddress =
+            env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setLeaseDuration =
+            env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V");
+    dhcpResultsFieldIds.setVendorInfo =
+            env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V");
 
     return AndroidRuntime::registerNativeMethods(env,
             NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));