Add equals, hashCode to MulticastRoutingConfig

Add helper functions to help compare if MulticastRoutingConfig
has changed.

Test: atest MulticastRoutingConfigTest
Change-Id: I30ed4796efbaafbcf1a273c12a9231ec02bc36f0
diff --git a/framework/src/android/net/MulticastRoutingConfig.java b/framework/src/android/net/MulticastRoutingConfig.java
index 1f4071c..4a3e1be 100644
--- a/framework/src/android/net/MulticastRoutingConfig.java
+++ b/framework/src/android/net/MulticastRoutingConfig.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -30,7 +31,9 @@
 import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Objects;
 import java.util.Set;
+import java.util.StringJoiner;
 
 /**
  * A class representing a configuration for multicast routing.
@@ -162,15 +165,6 @@
         }
     };
 
-    @Override
-    public String toString() {
-        return "MulticastRoutingConfig{"
-                + "ForwardingMode=" + forwardingModeToString(mForwardingMode)
-                + ", MinScope=" + mMinScope
-                + ", ListeningAddresses=" + mListeningAddresses
-                + '}';
-    }
-
     private static String forwardingModeToString(final int forwardingMode) {
         switch (forwardingMode) {
             case FORWARD_NONE: return "NONE";
@@ -301,4 +295,41 @@
             default: return "unknown multicast routing mode " + mode;
         }
     }
+
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        } else if (!(other instanceof MulticastRoutingConfig)) {
+            return false;
+        } else {
+            final MulticastRoutingConfig otherConfig = (MulticastRoutingConfig) other;
+            return mForwardingMode == otherConfig.mForwardingMode
+                && mMinScope == otherConfig.mMinScope
+                && mListeningAddresses.equals(otherConfig.mListeningAddresses);
+        }
+    }
+
+    public int hashCode() {
+        return Objects.hash(mForwardingMode, mMinScope, mListeningAddresses);
+    }
+
+    public String toString() {
+        final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
+
+        resultJoiner.add("ForwardingMode:");
+        resultJoiner.add(modeToString(mForwardingMode));
+
+        if (mForwardingMode == FORWARD_WITH_MIN_SCOPE) {
+            resultJoiner.add("MinScope:");
+            resultJoiner.add(Integer.toString(mMinScope));
+        }
+
+        if (mForwardingMode == FORWARD_SELECTED && !mListeningAddresses.isEmpty()) {
+            resultJoiner.add("ListeningAddresses: [");
+            resultJoiner.add(TextUtils.join(",", mListeningAddresses));
+            resultJoiner.add("]");
+        }
+
+        return resultJoiner.toString();
+    }
 }