am 5d6f1167: Merge "Make LinkProperties comparable." into honeycomb-LTE

* commit '5d6f1167039e22889545212ce18192460f9b503e':
  Make LinkProperties comparable.
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 9c36b12..f6a114c 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -78,6 +78,14 @@
             this.prefixLength == linkAddress.prefixLength;
     }
 
+    @Override
+    /*
+     * generate hashcode based on significant fields
+     */
+    public int hashCode() {
+        return ((null == address) ? 0 : address.hashCode()) + prefixLength;
+    }
+
     /**
      * Returns the InetAddress for this address.
      */
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 81d62a0..e88292f 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -19,11 +19,9 @@
 import android.net.ProxyProperties;
 import android.os.Parcelable;
 import android.os.Parcel;
-import android.util.Log;
+import android.text.TextUtils;
 
 import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -141,7 +139,7 @@
         String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " ");
 
         String linkAddresses = "LinkAddresses: [";
-        for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString();
+        for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ",";
         linkAddresses += "] ";
 
         String dns = "DnsAddresses: [";
@@ -156,6 +154,67 @@
         return ifaceName + linkAddresses + gateways + dns + proxy;
     }
 
+
+    @Override
+    /**
+     * Compares this {@code LinkProperties} instance against the target
+     * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
+     * all their fields are equal in values.
+     *
+     * For collection fields, such as mDnses, containsAll() is used to check
+     * if two collections contains the same elements, independent of order.
+     * There are two thoughts regarding containsAll()
+     * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
+     * 2. Worst case performance is O(n^2).
+     *
+     * @param obj the object to be tested for equality.
+     * @return {@code true} if both objects are equal, {@code false} otherwise.
+     */
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof LinkProperties)) return false;
+
+        boolean sameAddresses;
+        boolean sameDnses;
+        boolean sameGateways;
+
+        LinkProperties target = (LinkProperties) obj;
+
+        Collection<InetAddress> targetAddresses = target.getAddresses();
+        Collection<InetAddress> sourceAddresses = getAddresses();
+        sameAddresses = (sourceAddresses.size() == targetAddresses.size()) ?
+                sourceAddresses.containsAll(targetAddresses) : false;
+
+        Collection<InetAddress> targetDnses = target.getDnses();
+        sameDnses = (mDnses.size() == targetDnses.size()) ?
+                mDnses.containsAll(targetDnses) : false;
+
+        Collection<InetAddress> targetGateways = target.getGateways();
+        sameGateways = (mGateways.size() == targetGateways.size()) ?
+                mGateways.containsAll(targetGateways) : false;
+
+        return
+            sameAddresses && sameDnses && sameGateways
+            && TextUtils.equals(getInterfaceName(), target.getInterfaceName())
+            && (getHttpProxy() == null ? target.getHttpProxy() == null :
+                getHttpProxy().equals(target.getHttpProxy()));
+    }
+
+    @Override
+    /**
+     * generate hashcode based on significant fields
+     * Equal objects must produce the same hash code, while unequal objects
+     * may have the same hash codes.
+     */
+    public int hashCode() {
+        return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
+                + mLinkAddresses.size() * 31
+                + mDnses.size() * 37
+                + mGateways.size() * 41
+                + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
+    }
+
     /**
      * Implement the Parcelable interface.
      * @hide
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index cbe4445..44dbec1 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -163,6 +163,16 @@
         return 0;
     }
 
+    @Override
+    /*
+     * generate hashcode based on significant fields
+     */
+    public int hashCode() {
+        return ((null == mHost) ? 0 : mHost.hashCode())
+        + ((null == mExclusionList) ? 0 : mExclusionList.hashCode())
+        + mPort;
+    }
+
     /**
      * Implement the Parcelable interface.
      * @hide
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
new file mode 100644
index 0000000..50666b4
--- /dev/null
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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.net.LinkProperties;
+import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
+import java.net.InetAddress;
+
+public class LinkPropertiesTest extends TestCase {
+    private static String ADDRV4 = "75.208.6.1";
+    private static String ADDRV6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
+    private static String DNS1 = "75.208.7.1";
+    private static String DNS2 = "69.78.7.1";
+    private static String GATEWAY1 = "75.208.8.1";
+    private static String GATEWAY2 = "69.78.8.1";
+    private static String NAME = "qmi0";
+
+    @SmallTest
+    public void testEqualsNull() {
+        LinkProperties source = new LinkProperties();
+        LinkProperties target = new LinkProperties();
+
+        assertFalse(source == target);
+        assertTrue(source.equals(target));
+        assertTrue(source.hashCode() == target.hashCode());
+    }
+
+    @SmallTest
+    public void testEqualsSameOrder() {
+        try {
+            LinkProperties source = new LinkProperties();
+            source.setInterfaceName(NAME);
+            // set 2 link addresses
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            // set 2 dnses
+            source.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            // set 2 gateways
+            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+
+            LinkProperties target = new LinkProperties();
+
+            // All fields are same
+            target.setInterfaceName(NAME);
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+
+            assertTrue(source.equals(target));
+            assertTrue(source.hashCode() == target.hashCode());
+
+            target.clear();
+            // change Interface Name
+            target.setInterfaceName("qmi1");
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            assertFalse(source.equals(target));
+
+            target.clear();
+            target.setInterfaceName(NAME);
+            // change link addresses
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            assertFalse(source.equals(target));
+
+            target.clear();
+            target.setInterfaceName(NAME);
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            // 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));
+            assertFalse(source.equals(target));
+
+            target.clear();
+            target.setInterfaceName(NAME);
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            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));
+            assertFalse(source.equals(target));
+
+        } catch (Exception e) {
+            throw new RuntimeException(e.toString());
+            //fail();
+        }
+    }
+
+    @SmallTest
+    public void testEqualsDifferentOrder() {
+        try {
+            LinkProperties source = new LinkProperties();
+            source.setInterfaceName(NAME);
+            // set 2 link addresses
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            // set 2 dnses
+            source.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            source.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            // set 2 gateways
+            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+            source.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+
+            LinkProperties target = new LinkProperties();
+            // Exchange order
+            target.setInterfaceName(NAME);
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS2));
+            target.addDns(NetworkUtils.numericToInetAddress(DNS1));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY2));
+            target.addGateway(NetworkUtils.numericToInetAddress(GATEWAY1));
+
+            assertTrue(source.equals(target));
+            assertTrue(source.hashCode() == target.hashCode());
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+    @SmallTest
+    public void testEqualsDuplicated() {
+        try {
+            LinkProperties source = new LinkProperties();
+            // set 3 link addresses, eg, [A, A, B]
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            source.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+
+            LinkProperties target = new LinkProperties();
+            // set 3 link addresses, eg, [A, B, B]
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV4), 32));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+            target.addLinkAddress(new LinkAddress(
+                    NetworkUtils.numericToInetAddress(ADDRV6), 128));
+
+            assertTrue(source.equals(target));
+            assertTrue(source.hashCode() == target.hashCode());
+        } catch (Exception e) {
+            fail();
+        }
+    }
+
+}