Add Log.wtf when keepalive metrics are unexpected.

To debug unexpected keepalive metrics values, print the built
metrics in a Log.wtf before writing it to statsd.

Bug: 297292877
Test: atest FrameworksNetTests
Change-Id: I5fffc13721e50e28f24b0da12a961364f3f77e21
diff --git a/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java b/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java
index 35c4909..7a8b41b 100644
--- a/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java
+++ b/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java
@@ -74,6 +74,9 @@
 public class KeepaliveStatsTracker {
     private static final String TAG = KeepaliveStatsTracker.class.getSimpleName();
     private static final int INVALID_KEEPALIVE_ID = -1;
+    // 1 hour acceptable deviation in metrics collection duration time.
+    private static final long MAX_EXPECTED_DURATION_MS =
+            AutomaticOnOffKeepaliveTracker.METRICS_COLLECTION_DURATION_MS + 1 * 60 * 60 * 1_000L;
 
     @NonNull private final Handler mConnectivityServiceHandler;
     @NonNull private final Dependencies mDependencies;
@@ -710,6 +713,36 @@
         return mEnabled.get();
     }
 
+    /**
+     * Checks the DailykeepaliveInfoReported for the following:
+     * 1. total active durations/lifetimes <= total registered durations/lifetimes.
+     * 2. Total time in Durations == total time in Carrier lifetime stats
+     * 3. The total elapsed real time spent is within expectations.
+     */
+    @VisibleForTesting
+    public boolean allMetricsExpected(DailykeepaliveInfoReported dailyKeepaliveInfoReported) {
+        int totalRegistered = 0;
+        int totalActiveDurations = 0;
+        int totalTimeSpent = 0;
+        for (DurationForNumOfKeepalive durationForNumOfKeepalive: dailyKeepaliveInfoReported
+                .getDurationPerNumOfKeepalive().getDurationForNumOfKeepaliveList()) {
+            final int n = durationForNumOfKeepalive.getNumOfKeepalive();
+            totalRegistered += durationForNumOfKeepalive.getKeepaliveRegisteredDurationsMsec() * n;
+            totalActiveDurations += durationForNumOfKeepalive.getKeepaliveActiveDurationsMsec() * n;
+            totalTimeSpent += durationForNumOfKeepalive.getKeepaliveRegisteredDurationsMsec();
+        }
+        int totalLifetimes = 0;
+        int totalActiveLifetimes = 0;
+        for (KeepaliveLifetimeForCarrier keepaliveLifetimeForCarrier: dailyKeepaliveInfoReported
+                .getKeepaliveLifetimePerCarrier().getKeepaliveLifetimeForCarrierList()) {
+            totalLifetimes += keepaliveLifetimeForCarrier.getLifetimeMsec();
+            totalActiveLifetimes += keepaliveLifetimeForCarrier.getActiveLifetimeMsec();
+        }
+        return totalActiveDurations <= totalRegistered && totalActiveLifetimes <= totalLifetimes
+                && totalLifetimes == totalRegistered && totalActiveLifetimes == totalActiveDurations
+                && totalTimeSpent <= MAX_EXPECTED_DURATION_MS;
+    }
+
     /** Writes the stored metrics to ConnectivityStatsLog and resets. */
     public void writeAndResetMetrics() {
         ensureRunningOnHandlerThread();
@@ -725,6 +758,9 @@
         }
 
         final DailykeepaliveInfoReported dailyKeepaliveInfoReported = buildAndResetMetrics();
+        if (!allMetricsExpected(dailyKeepaliveInfoReported)) {
+            Log.wtf(TAG, "Unexpected metrics values: " + dailyKeepaliveInfoReported.toString());
+        }
         mDependencies.writeStats(dailyKeepaliveInfoReported);
     }
 
diff --git a/tests/unit/java/com/android/server/connectivity/KeepaliveStatsTrackerTest.java b/tests/unit/java/com/android/server/connectivity/KeepaliveStatsTrackerTest.java
index 90a0edd..1b964e2 100644
--- a/tests/unit/java/com/android/server/connectivity/KeepaliveStatsTrackerTest.java
+++ b/tests/unit/java/com/android/server/connectivity/KeepaliveStatsTrackerTest.java
@@ -37,6 +37,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.BroadcastReceiver;
@@ -1293,5 +1294,18 @@
                 expectRegisteredDurations,
                 expectActiveDurations,
                 new KeepaliveCarrierStats[0]);
+
+        assertTrue(mKeepaliveStatsTracker.allMetricsExpected(dailyKeepaliveInfoReported));
+
+        // Write time after 26 hours.
+        final int writeTime2 = 26 * 60 * 60 * 1000;
+        setElapsedRealtime(writeTime2);
+
+        visibleOnHandlerThread(mTestHandler, () -> mKeepaliveStatsTracker.writeAndResetMetrics());
+        verify(mDependencies, times(2)).writeStats(dailyKeepaliveInfoReportedCaptor.capture());
+        final DailykeepaliveInfoReported dailyKeepaliveInfoReported2 =
+                dailyKeepaliveInfoReportedCaptor.getValue();
+
+        assertFalse(mKeepaliveStatsTracker.allMetricsExpected(dailyKeepaliveInfoReported2));
     }
 }