Add equals and hashCode method for IceCandidate class.

Bug: webrtc:11072
Change-Id: I03568c3290a49466d0f459b1de8c89afaaf020ba
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158860
Commit-Queue: Honghai Zhang <honghaiz@webrtc.org>
Reviewed-by: Alex Glaznev <glaznev@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29695}
diff --git a/BUILD.gn b/BUILD.gn
index 5cef130..73569c5 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -680,6 +680,7 @@
         "sdk/android/tests/src/org/webrtc/FakeMediaCodecWrapper.java",
         "sdk/android/tests/src/org/webrtc/GlGenericDrawerTest.java",
         "sdk/android/tests/src/org/webrtc/HardwareVideoEncoderTest.java",
+        "sdk/android/tests/src/org/webrtc/IceCandidateTest.java",
         "sdk/android/tests/src/org/webrtc/ScalingSettingsTest.java",
         "sdk/android/tests/src/org/webrtc/CryptoOptionsTest.java",
       ]
diff --git a/sdk/android/api/org/webrtc/IceCandidate.java b/sdk/android/api/org/webrtc/IceCandidate.java
index 6df71f0..03725cc 100644
--- a/sdk/android/api/org/webrtc/IceCandidate.java
+++ b/sdk/android/api/org/webrtc/IceCandidate.java
@@ -10,6 +10,8 @@
 
 package org.webrtc;
 
+import android.support.annotation.Nullable;
+import java.util.Arrays;
 import org.webrtc.PeerConnection;
 
 /**
@@ -56,4 +58,29 @@
   String getSdp() {
     return sdp;
   }
+
+  /** equals() checks sdpMid, sdpMLineIndex, and sdp for equality. */
+  @Override
+  public boolean equals(@Nullable Object object) {
+    if (!(object instanceof IceCandidate)) {
+      return false;
+    }
+
+    IceCandidate that = (IceCandidate) object;
+    return objectEquals(this.sdpMid, that.sdpMid) && this.sdpMLineIndex == that.sdpMLineIndex
+        && objectEquals(this.sdp, that.sdp);
+  }
+
+  @Override
+  public int hashCode() {
+    Object[] values = {sdpMid, sdpMLineIndex, sdp};
+    return Arrays.hashCode(values);
+  }
+
+  private static boolean objectEquals(Object o1, Object o2) {
+    if (o1 == null) {
+      return o2 == null;
+    }
+    return o1.equals(o2);
+  }
 }
diff --git a/sdk/android/tests/src/org/webrtc/IceCandidateTest.java b/sdk/android/tests/src/org/webrtc/IceCandidateTest.java
new file mode 100644
index 0000000..e169694
--- /dev/null
+++ b/sdk/android/tests/src/org/webrtc/IceCandidateTest.java
@@ -0,0 +1,52 @@
+/*
+ *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.chromium.testing.local.LocalRobolectricTestRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.webrtc.IceCandidate;
+
+@RunWith(LocalRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class IceCandidateTest {
+  @Test
+  public void testIceCandidateEquals() {
+    IceCandidate c1 = new IceCandidate(
+        "audio", 0, "candidate:1532086002 1 udp 2122194687 192.168.86.144 37138 typ host");
+    IceCandidate c2 = new IceCandidate(
+        "audio", 0, "candidate:1532086002 1 udp 2122194687 192.168.86.144 37138 typ host");
+
+    // c3 differ by sdpMid
+    IceCandidate c3 = new IceCandidate(
+        "video", 0, "candidate:1532086002 1 udp 2122194687 192.168.86.144 37138 typ host");
+    // c4 differ by sdpMLineIndex
+    IceCandidate c4 = new IceCandidate(
+        "audio", 1, "candidate:1532086002 1 udp 2122194687 192.168.86.144 37138 typ host");
+    // c5 differ by sdp.
+    IceCandidate c5 = new IceCandidate(
+        "audio", 0, "candidate:1532086002 1 udp 2122194687 192.168.86.144 37139 typ host");
+
+    assertThat(c1.equals(c2)).isTrue();
+    assertThat(c2.equals(c1)).isTrue();
+    assertThat(c1.equals(null)).isFalse();
+    assertThat(c1.equals(c3)).isFalse();
+    assertThat(c1.equals(c4)).isFalse();
+    assertThat(c5.equals(c1)).isFalse();
+
+    Object o2 = c2;
+    assertThat(c1.equals(o2)).isTrue();
+    assertThat(o2.equals(c1)).isTrue();
+  }
+}
\ No newline at end of file