Dump cached services

Before:
DiscoveryManager:
  ServiceTypeClient: Type{_nearby_presence._tcp.local} \
  SocketKey{ network=100 interfaceIndex=47 } with 1 listeners.

After:
DiscoveryManager:
  Clients:
  ServiceTypeClient: Type{_nearby_presence._tcp.local} \
  SocketKey{ network=100 interfaceIndex=47 } with 1 listeners.

  Cached services:
    CacheKey{ ServiceType=_NEARBY_PRESENCE._TCP.LOCAL, \
    SocketKey{ network=100 interfaceIndex=47 } }
      Response{ Name: NsdManagerTest7899._nearby_presence._tcp.\
      local, pointerRecords: [PTR: _nearby_presence._tcp.local \
      -> NsdManagerTest7899._nearby_presence._tcp.local], \
      serviceRecord: SRV: Android_cd17d10e43bc43789ea73f54a739a\
      b76.local:12345 (prio=0, weight=0), textRecord: TXT: { T=0 \
      SAI=800 SAT=4000 SII=800}, inet4AddressRecords: [A: \
      Inet4Address: /192.168.86.219 Inet6Address: null], inet6Add\
      ressRecords: [AAAA: Inet4Address: null Inet6Address: /fe80::\
      9c4c:52ff:fe61:3509, AAAA: Inet4Address: null Inet6Address: \
      /2001:b400:e408:5eb3:9c4c:52ff:fe61:3509, AAAA: \
      Inet4Address: null Inet6Address: /2001:b400:e408:5eb3:8525:\
      7b76:3c94:56ba], interfaceIndex: 47, network: 100, \
      lastUpdateTime: 2024-07-29T08:42:58.940940Z }

Bug: 355421878
Test: atest FrameworksNetTests NsdManagerTest
Change-Id: I13792d737841e0829722cbc5cfa318511d10ef96
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index 8123d27..7fa605a 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -390,12 +390,18 @@
      */
     public void dump(PrintWriter pw) {
         discoveryExecutor.checkAndRunOnHandlerThread(() -> {
-            pw.println();
+            pw.println("Clients:");
             // Dump ServiceTypeClients
             for (MdnsServiceTypeClient serviceTypeClient
                     : perSocketServiceTypeClients.getAllMdnsServiceTypeClient()) {
                 serviceTypeClient.dump(pw);
             }
+            pw.println();
+            // Dump ServiceCache
+            pw.println("Cached services:");
+            if (serviceCache != null) {
+                serviceCache.dump(pw, "  ");
+            }
         });
     }
 }
\ No newline at end of file
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
index 3636644..2957da5 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsResponse.java
@@ -19,11 +19,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.net.Network;
+import android.os.SystemClock;
+import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.net.module.util.DnsUtils;
 
 import java.io.IOException;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -426,4 +429,18 @@
 
         return count;
     }
+
+    @Override
+    public String toString() {
+        return "Name: " + TextUtils.join(".", serviceName)
+                + ", pointerRecords: " + pointerRecords
+                + ", serviceRecord: " + serviceRecord
+                + ", textRecord: " + textRecord
+                + ", inet4AddressRecords: " + inet4AddressRecords
+                + ", inet6AddressRecords: " + inet6AddressRecords
+                + ", interfaceIndex: " + interfaceIndex
+                + ", network: " + network
+                + ", lastUpdateTime: " + Instant.now().minusMillis(
+                        SystemClock.elapsedRealtime() - lastUpdateTime);
+    }
 }
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java
index a8a4ef1..591ed8b 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceCache.java
@@ -32,6 +32,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.connectivity.mdns.util.MdnsUtils;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -71,6 +72,11 @@
             return Objects.equals(mUpperCaseServiceType, ((CacheKey) other).mUpperCaseServiceType)
                     && Objects.equals(mSocketKey, ((CacheKey) other).mSocketKey);
         }
+
+        @Override
+        public String toString() {
+            return "CacheKey{ ServiceType=" + mUpperCaseServiceType + ", " + mSocketKey + " }";
+        }
     }
     /**
      * A map of cached services. Key is composed of service type and socket. Value is the list of
@@ -353,6 +359,22 @@
         mNextExpirationTime = getNextExpirationTime(now);
     }
 
+    /**
+     * Dump ServiceCache state.
+     */
+    public void dump(PrintWriter pw, String indent) {
+        ensureRunningOnHandlerThread(mHandler);
+        // IndentingPrintWriter cannot be used on the mDNS stack build. So, manually add an indent.
+        for (int i = 0; i < mCachedServices.size(); i++) {
+            final CacheKey key = mCachedServices.keyAt(i);
+            pw.println(indent + key);
+            for (MdnsResponse response : mCachedServices.valueAt(i)) {
+                pw.println(indent + "  Response{ " + response + " }");
+            }
+            pw.println();
+        }
+    }
+
     /*** Callbacks for listening service expiration */
     public interface ServiceExpiredCallback {
         /*** Notify the service is expired */