diff --git a/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java b/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java index 35c49090a3..7a8b41b68f 100644 --- a/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java +++ b/service/src/com/android/server/connectivity/KeepaliveStatsTracker.java @@ -74,6 +74,9 @@ import java.util.concurrent.atomic.AtomicBoolean; 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 @@ public class KeepaliveStatsTracker { 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 @@ public class KeepaliveStatsTracker { } 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 90a0eddc0a..1b964e2a51 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.doCallRealMethod; 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 @@ public class KeepaliveStatsTrackerTest { 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)); } }